• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef _LIBRENDER_COLORBUFFER_H
17 #define _LIBRENDER_COLORBUFFER_H
18 
19 #include <EGL/egl.h>
20 #include <EGL/eglext.h>
21 #include <GLES/gl.h>
22 #include <GLES3/gl3.h>
23 #include "base/Stream.h"
24 // #include "android/skin/rect.h"
25 #include <memory>
26 
27 #include "DisplayVk.h"
28 #include "FrameworkFormats.h"
29 #include "Hwc2.h"
30 #include "RenderContext.h"
31 #include "snapshot/LazySnapshotObj.h"
32 
33 // From ANGLE "src/common/angleutils.h"
34 #define GL_BGR10_A2_ANGLEX 0x6AF9
35 
36 class TextureDraw;
37 class TextureResize;
38 class YUVConverter;
39 
40 // A class used to model a guest color buffer, and used to implement several
41 // related things:
42 //
43 //  - Every gralloc native buffer with HW read or write requirements will
44 //    allocate a host ColorBuffer instance. When gralloc_lock() is called,
45 //    the guest will use ColorBuffer::readPixels() to read the current content
46 //    of the buffer. When gralloc_unlock() is later called, it will call
47 //    ColorBuffer::subUpdate() to send the updated pixels.
48 //
49 //  - Every guest window EGLSurface is implemented by a host PBuffer
50 //    (see WindowSurface.h) that can have a ColorBuffer instance attached to
51 //    it (through WindowSurface::attachColorBuffer()). When such an attachment
52 //    exists, WindowSurface::flushColorBuffer() will copy the PBuffer's
53 //    pixel data into the ColorBuffer. The latter can then be displayed
54 //    in the client's UI sub-window with ColorBuffer::post().
55 //
56 //  - Guest EGLImages are implemented as native gralloc buffers too.
57 //    The guest glEGLImageTargetTexture2DOES() implementations will end up
58 //    calling ColorBuffer::bindToTexture() to bind the current context's
59 //    GL_TEXTURE_2D to the buffer. Similarly, the guest versions of
60 //    glEGLImageTargetRenderbufferStorageOES() will end up calling
61 //    ColorBuffer::bindToRenderbuffer().
62 //
63 // This forces the implementation to use a host EGLImage to implement each
64 // ColorBuffer.
65 //
66 // As an additional twist.
67 
68 class ColorBuffer :
69         public android::snapshot::LazySnapshotObj<ColorBuffer> {
70 public:
71     // Helper interface class used during ColorBuffer operations. This is
72     // introduced to remove coupling from the FrameBuffer class implementation.
73     class Helper {
74     public:
75         Helper() = default;
76         virtual ~Helper();
77         virtual bool setupContext() = 0;
78         virtual void teardownContext() = 0;
79         virtual TextureDraw* getTextureDraw() const = 0;
80         virtual bool isBound() const = 0;
81     };
82 
83     // Helper class to use a ColorBuffer::Helper context.
84     // Usage is pretty simple:
85     //
86     //     {
87     //        RecursiveScopedHelperContext context(m_helper);
88     //        if (!context.isOk()) {
89     //            return false;   // something bad happened.
90     //        }
91     //        .... do something ....
92     //     }   // automatically calls m_helper->teardownContext();
93     //
94     class RecursiveScopedHelperContext {
95     public:
RecursiveScopedHelperContext(ColorBuffer::Helper * helper)96         RecursiveScopedHelperContext(ColorBuffer::Helper* helper) : mHelper(helper) {
97             if (helper->isBound()) return;
98             if (!helper->setupContext()) {
99                 mHelper = NULL;
100                 return;
101             }
102             mNeedUnbind = true;
103         }
104 
isOk()105         bool isOk() const { return mHelper != NULL; }
106 
~RecursiveScopedHelperContext()107         ~RecursiveScopedHelperContext() { release(); }
108 
release()109         void release() {
110             if (mNeedUnbind) {
111                 mHelper->teardownContext();
112                 mNeedUnbind = false;
113             }
114             mHelper = NULL;
115         }
116 
117     private:
118         ColorBuffer::Helper* mHelper;
119         bool mNeedUnbind = false;
120     };
121 
122     // Create a new ColorBuffer instance.
123     // |p_display| is the host EGLDisplay handle.
124     // |p_width| and |p_height| are the buffer's dimensions in pixels.
125     // |p_internalFormat| is the internal OpenGL pixel format to use, valid
126     // values
127     // are: GL_RGB, GL_RGB565, GL_RGBA, GL_RGB5_A1_OES and GL_RGBA4_OES.
128     // Implementation is free to use something else though.
129     // |p_frameworkFormat| specifies the original format of the guest
130     // color buffer so that we know how to convert to |p_internalFormat|,
131     // if necessary (otherwise, p_frameworkFormat ==
132     // FRAMEWORK_FORMAT_GL_COMPATIBLE).
133     // It is assumed underlying EGL has EGL_KHR_gl_texture_2D_image.
134     // Returns NULL on failure.
135     // |fastBlitSupported|: whether or not this ColorBuffer can be
136     // blitted and posted to swapchain without context switches.
137     static ColorBuffer* create(EGLDisplay p_display,
138                                int p_width,
139                                int p_height,
140                                GLint p_internalFormat,
141                                FrameworkFormat p_frameworkFormat,
142                                HandleType hndl,
143                                Helper* helper,
144                                bool fastBlitSupported);
145 
146     // Sometimes things happen and we need to reformat the GL texture
147     // used. This function replaces the format of the underlying texture
148     // with the internalformat specified.
149     void reformat(GLint internalformat, GLenum type);
150 
151     // Destructor.
152     ~ColorBuffer();
153 
154     // Return ColorBuffer width and height in pixels
getWidth()155     GLuint getWidth() const { return m_width; }
getHeight()156     GLuint getHeight() const { return m_height; }
getInternalFormat()157     GLint getInternalFormat() const { return m_internalFormat; }
158 
159     // Read the ColorBuffer instance's pixel values into host memory.
160     void readPixels(int x,
161                     int y,
162                     int width,
163                     int height,
164                     GLenum p_format,
165                     GLenum p_type,
166                     void* pixels);
167 
168     void readPixelsScaled(int width,
169                           int height,
170                           GLenum p_format,
171                           GLenum p_type,
172                           int skinRotation,
173                           void* pixels);
174 
175     // Read cached YUV pixel values into host memory.
176     void readPixelsYUVCached(int x,
177                              int y,
178                              int width,
179                              int height,
180                              void* pixels,
181                              uint32_t pixels_size);
182 
183     void swapYUVTextures(uint32_t texture_type, uint32_t* textures);
184 
185     // Update the ColorBuffer instance's pixel values from host memory.
186     // |p_format / p_type| are the desired OpenGL color buffer format
187     // and data type.
188     // Otherwise, subUpdate() will explicitly convert |pixels|
189     // to be in |p_format|.
190     void subUpdate(int x,
191                    int y,
192                    int width,
193                    int height,
194                    GLenum p_format,
195                    GLenum p_type,
196                    void* pixels);
197 
198     // Completely replaces contents, assuming that |pixels| is a buffer
199     // that is allocated and filled with the same format.
200     bool replaceContents(const void* pixels, size_t numBytes);
201 
202     // Reads back entire contents, tightly packed rows.
203     // If the framework format is YUV, it will read back as raw YUV data.
204     bool readContents(size_t* numBytes, void* pixels);
205 
206     // Draw a ColorBuffer instance, i.e. blit it to the current guest
207     // framebuffer object / window surface. This doesn't display anything.
208     bool draw();
209 
210     // Scale the underlying texture of this ColorBuffer to match viewport size.
211     // It returns the texture name after scaling.
212     GLuint scale();
213     // Post this ColorBuffer to the host native sub-window.
214     // |rotation| is the rotation angle in degrees, clockwise in the GL
215     // coordinate space.
216     bool post(GLuint tex, float rotation, float dx, float dy);
217     // Post this ColorBuffer to the host native sub-window and apply
218     // the device screen overlay (if there is one).
219     // |rotation| is the rotation angle in degrees, clockwise in the GL
220     // coordinate space.
221     bool postWithOverlay(GLuint tex, float rotation, float dx, float dy);
222 
223     // Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's
224     // EGLImage. This is intended to implement glEGLImageTargetTexture2DOES()
225     // for all GLES versions.
226     bool bindToTexture();
227     bool bindToTexture2();
228 
229     // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this
230     // ColorBuffer's EGLImage. This is intended to implement
231     // glEGLImageTargetRenderbufferStorageOES() for all GLES versions.
232     bool bindToRenderbuffer();
233 
234     // Copy the content of the current context's read surface to this
235     // ColorBuffer. This is used from WindowSurface::flushColorBuffer().
236     // Return true on success, false on failure (e.g. no current context).
237     bool blitFromCurrentReadBuffer();
238 
239     // Read the content of the whole ColorBuffer as 32-bit RGBA pixels.
240     // |img| must be a buffer large enough (i.e. width * height * 4).
241     void readback(unsigned char* img, bool readbackBgra = false);
242     // readback() but async (to the specified |buffer|)
243     void readbackAsync(GLuint buffer, bool readbackBgra = false);
244 
245     void onSave(android::base::Stream* stream);
246     static ColorBuffer* onLoad(android::base::Stream* stream,
247                                EGLDisplay p_display,
248                                Helper* helper,
249                                bool fastBlitSupported);
250 
251     HandleType getHndl() const;
252 
isFastBlitSupported()253     bool isFastBlitSupported() const { return m_fastBlitSupported; }
254     void postLayer(ComposeLayer* l, int frameWidth, int frameHeight);
255     GLuint getTexture();
256 
getDisplayBufferVk()257     const std::shared_ptr<DisplayVk::DisplayBufferInfo>& getDisplayBufferVk()
258         const {
259         return m_displayBufferVk;
260     };
261 
262     bool importMemory(
263 #ifdef _WIN32
264         void* handle,
265 #else
266         int handle,
267 #endif
268         uint64_t size, bool dedicated, bool linearTiling, bool vulkanOnly,
269         std::shared_ptr<DisplayVk::DisplayBufferInfo> displayBufferVk);
270     void setInUse(bool inUse);
isInUse()271     bool isInUse() const { return m_inUse; }
272 
273     void setSync(bool debug = false);
274     void waitSync(bool debug = false);
setDisplay(uint32_t displayId)275     void setDisplay(uint32_t displayId) { m_displayId = displayId; }
getDisplay()276     uint32_t getDisplay() { return m_displayId; }
getFrameworkFormat()277     FrameworkFormat getFrameworkFormat() { return m_frameworkFormat; }
278 public:
279     void restore();
280 
281 private:
282     ColorBuffer(EGLDisplay display, HandleType hndl, Helper* helper);
283 
284 private:
285     GLuint m_tex = 0;
286     GLuint m_blitTex = 0;
287     EGLImageKHR m_eglImage = nullptr;
288     EGLImageKHR m_blitEGLImage = nullptr;
289     GLuint m_width = 0;
290     GLuint m_height = 0;
291     GLuint m_fbo = 0;
292     GLint m_internalFormat = 0;
293     GLint m_sizedInternalFormat = 0;
294 
295     // |m_format| and |m_type| are for reformatting purposes only
296     // to work around bugs in the guest. No need to snapshot those.
297     bool m_needFormatCheck = true;
298     GLenum m_format = 0; // TODO: Currently we treat m_internalFormat same as
299                          // m_format, but if underlying drivers can take it,
300                          // it may be a better idea to distinguish them, with
301                          // m_internalFormat as an explicitly sized format; then
302                          // guest can specify everything in terms of explicitly
303                          // sized internal formats and things will get less
304                          // ambiguous.
305     GLenum m_type = 0;
306 
307     EGLDisplay m_display = nullptr;
308     Helper* m_helper = nullptr;
309     TextureResize* m_resizer = nullptr;
310     FrameworkFormat m_frameworkFormat;
311     GLuint m_yuv_conversion_fbo = 0;  // FBO to offscreen-convert YUV to RGB
312     GLuint m_scaleRotationFbo = 0;  // FBO to read scaled rotation pixels
313     std::unique_ptr<YUVConverter> m_yuv_converter;
314     HandleType mHndl;
315 
316     GLsync m_sync = nullptr;
317     bool m_fastBlitSupported = false;
318 
319     GLenum m_asyncReadbackType = GL_UNSIGNED_BYTE;
320     size_t m_numBytes = 0;
321 
322     bool m_importedMemory = false;
323     GLuint m_memoryObject = 0;
324     bool m_inUse = false;
325     bool m_isBuffer = false;
326     GLuint m_buf = 0;
327     uint32_t m_displayId = 0;
328     bool m_BRSwizzle = false;
329     // Won't share with others so that m_displayBufferVk lives shorter than this
330     // ColorBuffer.
331     std::shared_ptr<DisplayVk::DisplayBufferInfo> m_displayBufferVk;
332 };
333 
334 typedef std::shared_ptr<ColorBuffer> ColorBufferPtr;
335 
336 class Buffer : public android::snapshot::LazySnapshotObj<Buffer> {
337 public:
create(size_t sizeBytes,HandleType hndl)338     static Buffer* create(size_t sizeBytes, HandleType hndl) {
339         return new Buffer(sizeBytes, hndl);
340     }
341 
342     ~Buffer() = default;
343 
getHndl()344     HandleType getHndl() const { return m_handle; }
getSize()345     size_t getSize() const { return m_sizeBytes; }
346 
347 protected:
Buffer(size_t sizeBytes,HandleType hndl)348     Buffer(size_t sizeBytes, HandleType hndl)
349         : m_handle(hndl), m_sizeBytes(sizeBytes) {}
350 
351 private:
352     HandleType m_handle;
353     size_t m_sizeBytes;
354 };
355 
356 typedef std::shared_ptr<Buffer> BufferPtr;
357 
358 #endif
359