1 //
2 // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // DisplayOzone.h: Ozone implementation of egl::Display
8 
9 #ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
10 #define LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
11 
12 #include <xf86drm.h>
13 #include <xf86drmMode.h>
14 
15 #include <string>
16 
17 #include "libANGLE/renderer/gl/egl/DisplayEGL.h"
18 
19 struct gbm_device;
20 struct gbm_bo;
21 
22 namespace gl
23 {
24 class FramebufferState;
25 }
26 
27 namespace rx
28 {
29 
30 class FramebufferGL;
31 
32 // TODO(fjhenigman) Implement swap control.  The following struct will be used for that.
33 // State-tracking data for the swap control to allow DisplayOzone to remember per
34 // drawable information for swap control.
35 struct SwapControlData final
36 {
37     SwapControlData();
38 
39     // Set by the drawable
40     int targetSwapInterval;
41 
42     // DisplayOzone-side state-tracking
43     int maxSwapInterval;
44     int currentSwapInterval;
45 };
46 
47 class DisplayOzone final : public DisplayEGL
48 {
49   public:
50     struct NativeWindow
51     {
52         int32_t x;
53         int32_t y;
54         int32_t width;
55         int32_t height;
56         int32_t borderWidth;
57         int32_t borderHeight;
58         int32_t visible;
59         int32_t depth;
60     };
61 
62     class Buffer final : angle::NonCopyable
63     {
64       public:
65         Buffer(DisplayOzone *display,
66                uint32_t useFlags,
67                uint32_t gbmFormat,
68                uint32_t drmFormat,
69                uint32_t drmFormatFB,
70                int depthBits,
71                int stencilBits);
72 
73         ~Buffer();
74         bool initialize(const NativeWindow *window);
75         bool initialize(int32_t width, int32_t height);
76         void reset();
77         bool resize(int32_t width, int32_t height);
78         FramebufferGL *framebufferGL(const gl::FramebufferState &state);
79         void present();
80         uint32_t getDRMFB();
81         void bindTexImage();
82         GLuint getTexture();
getWidth()83         int32_t getWidth() const { return mWidth; }
getHeight()84         int32_t getHeight() const { return mHeight; }
getGLFB()85         GLuint getGLFB() const { return mGLFB; }
getNative()86         const NativeWindow *getNative() const { return mNative; }
87 
88       private:
89         DisplayOzone *mDisplay;
90         const NativeWindow *mNative;
91         int mWidth;
92         int mHeight;
93         const int mDepthBits;
94         const int mStencilBits;
95         const uint32_t mUseFlags;
96         const uint32_t mGBMFormat;
97         const uint32_t mDRMFormat;
98         const uint32_t mDRMFormatFB;
99         gbm_bo *mBO;
100         int mDMABuf;
101         bool mHasDRMFB;
102         uint32_t mDRMFB;
103         EGLImageKHR mImage;
104         GLuint mColorBuffer;
105         GLuint mDSBuffer;
106         GLuint mGLFB;
107         GLuint mTexture;
108     };
109 
110     DisplayOzone();
111     ~DisplayOzone() override;
112 
113     egl::Error initialize(egl::Display *display) override;
114     void terminate() override;
115 
116     SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
117                                      const egl::Config *configuration,
118                                      EGLNativeWindowType window,
119                                      const egl::AttributeMap &attribs) override;
120     SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
121                                       const egl::Config *configuration,
122                                       const egl::AttributeMap &attribs) override;
123     SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
124                                                const egl::Config *configuration,
125                                                EGLenum buftype,
126                                                EGLClientBuffer clientBuffer,
127                                                const egl::AttributeMap &attribs) override;
128     SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
129                                      const egl::Config *configuration,
130                                      NativePixmapType nativePixmap,
131                                      const egl::AttributeMap &attribs) override;
132 
133     egl::ConfigSet generateConfigs() override;
134 
135     bool testDeviceLost() override;
136     egl::Error restoreLostDevice() override;
137 
138     bool isValidNativeWindow(EGLNativeWindowType window) const override;
139 
140     egl::Error getDevice(DeviceImpl **device) override;
141 
142     egl::Error waitClient() const override;
143     egl::Error waitNative(EGLint engine,
144                           egl::Surface *drawSurface,
145                           egl::Surface *readSurface) const override;
146 
147     // TODO(fjhenigman) Implement this.
148     // Swap interval can be set globally or per drawable.
149     // This function will make sure the drawable's swap interval is the
150     // one required so that the subsequent swapBuffers acts as expected.
151     void setSwapInterval(EGLSurface drawable, SwapControlData *data);
152 
153     egl::Error getDriverVersion(std::string *version) const override;
154 
155   private:
156     GLuint makeShader(GLuint type, const char *src);
157     void drawBuffer(Buffer *buffer);
158     void drawWithBlit(Buffer *buffer);
159     void drawWithTexture(Buffer *buffer);
160     void flushGL();
161     void presentScreen();
162     static void pageFlipHandler(int fd,
163                                 unsigned int sequence,
164                                 unsigned int tv_sec,
165                                 unsigned int tv_usec,
166                                 void *data);
167     void pageFlipHandler(unsigned int sequence, uint64_t tv);
168 
169     // TODO(fjhenigman) Implement swap control.  The following stuff will be used for that.
170     enum class SwapControl
171     {
172         ABSENT,
173         EXT,
174         MESA,
175         SGI,
176     };
177     SwapControl mSwapControl;
178     int mMinSwapInterval;
179     int mMaxSwapInterval;
180     int mCurrentSwapInterval;
181 
182     gbm_device *mGBM;
183     drmModeConnectorPtr mConnector;
184     drmModeModeInfoPtr mMode;
185     drmModeCrtcPtr mCRTC;
186     bool mSetCRTC;
187 
188     int32_t mWidth;
189     int32_t mHeight;
190 
191     // Three scanout buffers cycle through four states.  The state of a buffer
192     // is indicated by which of these pointers points to it.
193     // TODO(fjhenigman) It might be simpler/clearer to use a ring buffer.
194     Buffer *mScanning;
195     Buffer *mPending;
196     Buffer *mDrawing;
197     Buffer *mUnused;
198 
199     GLuint mProgram;
200     GLuint mVertexShader;
201     GLuint mFragmentShader;
202     GLuint mVertexBuffer;
203     GLuint mIndexBuffer;
204     GLint mCenterUniform;
205     GLint mWindowSizeUniform;
206     GLint mBorderSizeUniform;
207     GLint mDepthUniform;
208 };
209 }  // namespace rx
210 
211 #endif  // LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
212