blob: ddf133a5be562830a1ae84907a382421cb5bea7e [file] [log] [blame]
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// DisplayOzone.h: Ozone implementation of egl::Display
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <string>
#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
struct gbm_device;
struct gbm_bo;
namespace gl
class FramebufferState;
namespace rx
class FramebufferGL;
class RendererEGL;
// TODO(fjhenigman) Implement swap control. The following struct will be used for that.
// State-tracking data for the swap control to allow DisplayOzone to remember per
// drawable information for swap control.
struct SwapControlData final
// Set by the drawable
int targetSwapInterval;
// DisplayOzone-side state-tracking
int maxSwapInterval;
int currentSwapInterval;
class DisplayOzone final : public DisplayEGL
struct NativeWindow
int32_t x;
int32_t y;
int32_t width;
int32_t height;
int32_t borderWidth;
int32_t borderHeight;
int32_t visible;
int32_t depth;
class Buffer final : angle::NonCopyable
Buffer(DisplayOzone *display,
uint32_t useFlags,
uint32_t gbmFormat,
uint32_t drmFormat,
uint32_t drmFormatFB,
int depthBits,
int stencilBits);
bool initialize(const NativeWindow *window);
bool initialize(int32_t width, int32_t height);
void reset();
bool resize(int32_t width, int32_t height);
GLuint createGLFB(const gl::Context *context);
FramebufferGL *framebufferGL(const gl::Context *context, const gl::FramebufferState &state);
void present(const gl::Context *context);
uint32_t getDRMFB();
void bindTexImage();
GLuint getTexture();
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
const NativeWindow *getNative() const { return mNative; }
bool createRenderbuffers();
DisplayOzone *mDisplay;
const NativeWindow *mNative;
int mWidth;
int mHeight;
const int mDepthBits;
const int mStencilBits;
const uint32_t mUseFlags;
const uint32_t mGBMFormat;
const uint32_t mDRMFormat;
const uint32_t mDRMFormatFB;
gbm_bo *mBO;
int mDMABuf;
bool mHasDRMFB;
uint32_t mDRMFB;
EGLImageKHR mImage;
GLuint mColorBuffer;
GLuint mDSBuffer;
GLuint mTexture;
DisplayOzone(const egl::DisplayState &state);
~DisplayOzone() override;
egl::Error initialize(egl::Display *display) override;
void terminate() override;
SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) override;
ContextImpl *createContext(const gl::State &state,
gl::ErrorSet *errorSet,
const egl::Config *configuration,
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
egl::ConfigSet generateConfigs() override;
bool testDeviceLost() override;
egl::Error restoreLostDevice(const egl::Display *display) override;
bool isValidNativeWindow(EGLNativeWindowType window) const override;
DeviceImpl *createDevice() override;
egl::Error waitClient(const gl::Context *context) override;
egl::Error waitNative(const gl::Context *context, EGLint engine) override;
gl::Version getMaxSupportedESVersion() const override;
void destroyNativeContext(EGLContext context) override;
// TODO(fjhenigman) Implement this.
// Swap interval can be set globally or per drawable.
// This function will make sure the drawable's swap interval is the
// one required so that the subsequent swapBuffers acts as expected.
void setSwapInterval(EGLSurface drawable, SwapControlData *data);
WorkerContext *createWorkerContext(std::string *infoLog,
EGLContext sharedContext,
const native_egl::AttributeVector workerAttribs) override;
void initializeFrontendFeatures(angle::FrontendFeatures *features) const override;
void populateFeatureList(angle::FeatureList *features) override;
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
GLuint makeShader(GLuint type, const char *src);
void drawBuffer(const gl::Context *context, Buffer *buffer);
void drawWithTexture(const gl::Context *context, Buffer *buffer);
void flushGL();
bool hasUsableScreen(int fd);
void presentScreen();
static void pageFlipHandler(int fd,
unsigned int sequence,
unsigned int tv_sec,
unsigned int tv_usec,
void *data);
void pageFlipHandler(unsigned int sequence, uint64_t tv);
std::shared_ptr<RendererEGL> mRenderer;
gbm_device *mGBM;
drmModeConnectorPtr mConnector;
drmModeModeInfoPtr mMode;
drmModeCrtcPtr mCRTC;
bool mSetCRTC;
int32_t mWidth;
int32_t mHeight;
// Three scanout buffers cycle through four states. The state of a buffer
// is indicated by which of these pointers points to it.
// TODO(fjhenigman) It might be simpler/clearer to use a ring buffer.
Buffer *mScanning;
Buffer *mPending;
Buffer *mDrawing;
Buffer *mUnused;
GLuint mProgram;
GLuint mVertexShader;
GLuint mFragmentShader;
GLuint mVertexBuffer;
GLuint mIndexBuffer;
GLint mCenterUniform;
GLint mWindowSizeUniform;
GLint mBorderSizeUniform;
GLint mDepthUniform;
} // namespace rx