• 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 
17 #pragma once
18 
19 #include <EGL/egl.h>
20 #include <EGL/eglext.h>
21 #include <GLES/gl.h>
22 #include <GLES3/gl3.h>
23 
24 #include <memory>
25 #include <unordered_map>
26 #include <unordered_set>
27 
28 #include "BorrowedImage.h"
29 #include "ContextHelper.h"
30 #include "FrameworkFormats.h"
31 #include "Handle.h"
32 #include "Hwc2.h"
33 #include "aemu/base/ManagedDescriptor.hpp"
34 #include "aemu/base/files/Stream.h"
35 #include "render-utils/Renderer.h"
36 
37 // From ANGLE "src/common/angleutils.h"
38 #define GL_BGR10_A2_ANGLEX 0x6AF9
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 ColorBufferGl instance. When gralloc_lock() is called,
45 //    the guest will use ColorBufferGl::readPixels() to read the current content
46 //    of the buffer. When gralloc_unlock() is later called, it will call
47 //    ColorBufferGl::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 ColorBufferGl 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 ColorBufferGl. The latter can then be displayed
54 //    in the client's UI sub-window with ColorBufferGl::post().
55 //
56 //  - Guest EGLImages are implemented as native gralloc buffers too.
57 //    The guest glEGLImageTargetTexture2DOES() implementations will end up
58 //    calling ColorBufferGl::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 //    ColorBufferGl::bindToRenderbuffer().
62 //
63 // This forces the implementation to use a host EGLImage to implement each
64 // ColorBufferGl.
65 //
66 // As an additional twist.
67 
68 namespace gfxstream {
69 namespace gl {
70 
71 class TextureDraw;
72 class TextureResize;
73 class YUVConverter;
74 
75 class ColorBufferGl {
76    public:
77     // Create a new ColorBufferGl instance.
78     // |display| is the host EGLDisplay handle.
79     // |width| and |height| are the buffer's dimensions in pixels.
80     // |internalFormat| is the internal OpenGL pixel format to use, valid
81     // values
82     // are: GL_RGB, GL_RGB565, GL_RGBA, GL_RGB5_A1_OES and GL_RGBA4_OES.
83     // Implementation is free to use something else though.
84     // |frameworkFormat| specifies the original format of the guest
85     // color buffer so that we know how to convert to |internalFormat|,
86     // if necessary (otherwise, frameworkFormat ==
87     // FRAMEWORK_FORMAT_GL_COMPATIBLE).
88     // It is assumed underlying EGL has EGL_KHR_gl_texture_2D_image.
89     // Returns NULL on failure.
90     // |fastBlitSupported|: whether or not this ColorBufferGl can be
91     // blitted and posted to swapchain without context switches.
92     static std::unique_ptr<ColorBufferGl> create(EGLDisplay display, int width, int height,
93                                                  GLint internalFormat,
94                                                  FrameworkFormat frameworkFormat, HandleType handle,
95                                                  ContextHelper* helper, TextureDraw* textureDraw,
96                                                  bool fastBlitSupported);
97 
98     // Sometimes things happen and we need to reformat the GL texture
99     // used. This function replaces the format of the underlying texture
100     // with the internalformat specified.
101     void reformat(GLint internalformat, GLenum type);
102 
103     // Destructor.
104     ~ColorBufferGl();
105 
106     // Return ColorBufferGl width and height in pixels
getWidth()107     GLuint getWidth() const { return m_width; }
getHeight()108     GLuint getHeight() const { return m_height; }
getInternalFormat()109     GLint getInternalFormat() const { return m_internalFormat; }
110 
111     // Read the ColorBufferGl instance's pixel values into host memory.
112     void readPixels(int x,
113                     int y,
114                     int width,
115                     int height,
116                     GLenum p_format,
117                     GLenum p_type,
118                     void* pixels);
119     // Read the ColorBuffer instance's pixel values by first scaling
120     // to the size of width x height, then clipping a |rect| from the
121     // screen defined by width x height.
122     void readPixelsScaled(int width, int height, GLenum p_format, GLenum p_type, int skinRotation,
123                           Rect rect, void* pixels);
124 
125     // Read cached YUV pixel values into host memory.
126     void readPixelsYUVCached(int x,
127                              int y,
128                              int width,
129                              int height,
130                              void* pixels,
131                              uint32_t pixels_size);
132 
133     void swapYUVTextures(FrameworkFormat texture_type, GLuint* textures);
134 
135     // Update the ColorBufferGl instance's pixel values from host memory.
136     // |p_format / p_type| are the desired OpenGL color buffer format
137     // and data type.
138     // Otherwise, subUpdate() will explicitly convert |pixels|
139     // to be in |p_format|.
140     bool subUpdate(int x, int y, int width, int height, GLenum p_format, GLenum p_type,
141                    const void* pixels);
142     bool subUpdateFromFrameworkFormat(int x, int y, int width, int height,
143                                       FrameworkFormat fwkFormat, GLenum p_format, GLenum p_type,
144                                       const void* pixels);
145 
146     // Completely replaces contents, assuming that |pixels| is a buffer
147     // that is allocated and filled with the same format.
148     bool replaceContents(const void* pixels, size_t numBytes);
149 
150     // Reads back entire contents, tightly packed rows.
151     // If the framework format is YUV, it will read back as raw YUV data.
152     bool readContents(size_t* numBytes, void* pixels);
153 
154     // Draw a ColorBufferGl instance, i.e. blit it to the current guest
155     // framebuffer object / window surface. This doesn't display anything.
156     bool draw();
157 
158     // Returns the texture name of a texture containing the contents of this
159     // ColorBuffer but that is scaled to match the current viewport. This
160     // ColorBuffer retains ownership of the returned texture.
161     GLuint getViewportScaledTexture();
162     // Post this ColorBuffer to the host native sub-window.
163     // |rotation| is the rotation angle in degrees, clockwise in the GL
164     // coordinate space.
165     bool post(GLuint tex, float rotation, float dx, float dy);
166     // Post this ColorBufferGl to the host native sub-window and apply
167     // the device screen overlay (if there is one).
168     // |rotation| is the rotation angle in degrees, clockwise in the GL
169     // coordinate space.
170     bool postViewportScaledWithOverlay(float rotation, float dx, float dy);
171 
172     // Bind the current context's EGL_TEXTURE_2D texture to this ColorBufferGl's
173     // EGLImage. This is intended to implement glEGLImageTargetTexture2DOES()
174     // for all GLES versions.
175     bool bindToTexture();
176     bool bindToTexture2();
177 
178     // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this
179     // ColorBufferGl's EGLImage. This is intended to implement
180     // glEGLImageTargetRenderbufferStorageOES() for all GLES versions.
181     bool bindToRenderbuffer();
182 
183     // Copy the content of the current context's read surface to this
184     // ColorBufferGl. This is used from WindowSurface::flushColorBuffer().
185     // Return true on success, false on failure (e.g. no current context).
186     bool blitFromCurrentReadBuffer();
187 
188     // Read the content of the whole ColorBufferGl as 32-bit RGBA pixels.
189     // |img| must be a buffer large enough (i.e. width * height * 4).
190     void readback(unsigned char* img, bool readbackBgra = false);
191     // readback() but async (to the specified |buffer|)
192     void readbackAsync(GLuint buffer, bool readbackBgra = false);
193 
194     void onSave(android::base::Stream* stream);
195     static std::unique_ptr<ColorBufferGl> onLoad(android::base::Stream* stream,
196                                                  EGLDisplay p_display, ContextHelper* helper,
197                                                  TextureDraw* textureDraw, bool fastBlitSupported);
198 
199     HandleType getHndl() const;
200 
isFastBlitSupported()201     bool isFastBlitSupported() const { return m_fastBlitSupported; }
202     void postLayer(const ComposeLayer& l, int frameWidth, int frameHeight);
203     GLuint getTexture();
204 
205     std::unique_ptr<BorrowedImageInfo> getBorrowedImageInfo();
206 
207     // ColorBufferGl backing change methods
208     //
209     // Change to opaque fd or opaque win32 handle-backed VkDeviceMemory
210     // via GL_EXT_memory_objects
211     bool importMemory(android::base::ManagedDescriptor externalDescriptor, uint64_t size,
212                       bool dedicated, bool linearTiling);
213     // Change to EGL native pixmap
214     bool importEglNativePixmap(void* pixmap, bool preserveContent);
215     // Change to some other native EGL image.  nativeEglImage must not have
216     // been created from our s_egl.eglCreateImage.
217     bool importEglImage(void* nativeEglImage, bool preserveContent);
218 
219     void setSync(bool debug = false);
220     void waitSync(bool debug = false);
setDisplay(uint32_t displayId)221     void setDisplay(uint32_t displayId) { m_displayId = displayId; }
getDisplay()222     uint32_t getDisplay() { return m_displayId; }
getFrameworkFormat()223     FrameworkFormat getFrameworkFormat() { return m_frameworkFormat; }
224 
225  public:
226     void restore();
227 
228 private:
229  ColorBufferGl(EGLDisplay display, HandleType hndl, GLuint width, GLuint height,
230                ContextHelper* helper, TextureDraw* textureDraw);
231  // Helper function to get contents.
232  std::vector<uint8_t> getContents();
233  // Helper function to clear current EGL image.
234  void clearStorage();
235  // Helper function to bind EGL image as texture. Assumes storage cleared.
236  void restoreEglImage(EGLImageKHR image);
237  // Helper function that does the above two operations in one go.
238  void rebindEglImage(EGLImageKHR image, bool preserveContent);
239 
240 private:
241     GLuint m_tex = 0;
242     GLuint m_blitTex = 0;
243     EGLImageKHR m_eglImage = nullptr;
244     EGLImageKHR m_blitEGLImage = nullptr;
245     const GLuint m_width = 0;
246     const GLuint m_height = 0;
247     GLuint m_fbo = 0;
248     GLint m_internalFormat = 0;
249     GLint m_sizedInternalFormat = 0;
250 
251     // This is helpful for bindFbo which may skip too many steps after the egl
252     // image is replaced.
253     bool m_needFboReattach = false;
254 
255     // |m_format| and |m_type| are for reformatting purposes only
256     // to work around bugs in the guest. No need to snapshot those.
257     bool m_needFormatCheck = true;
258     GLenum m_format = 0; // TODO: Currently we treat m_internalFormat same as
259                          // m_format, but if underlying drivers can take it,
260                          // it may be a better idea to distinguish them, with
261                          // m_internalFormat as an explicitly sized format; then
262                          // guest can specify everything in terms of explicitly
263                          // sized internal formats and things will get less
264                          // ambiguous.
265     GLenum m_type = 0;
266 
267     EGLDisplay m_display = nullptr;
268     ContextHelper* m_helper = nullptr;
269     TextureDraw* m_textureDraw = nullptr;
270     TextureResize* m_resizer = nullptr;
271     FrameworkFormat m_frameworkFormat;
272     GLuint m_yuv_conversion_fbo = 0;  // FBO to offscreen-convert YUV to RGB
273     GLuint m_scaleRotationFbo = 0;  // FBO to read scaled rotation pixels
274     std::unique_ptr<YUVConverter> m_yuv_converter;
275     HandleType mHndl;
276 
277     GLsync m_sync = nullptr;
278     bool m_fastBlitSupported = false;
279     bool m_vulkanOnly = false;
280 
281     GLenum m_asyncReadbackType = GL_UNSIGNED_BYTE;
282     size_t m_numBytes = 0;
283 
284     bool m_importedMemory = false;
285     GLuint m_memoryObject = 0;
286     bool m_inUse = false;
287     bool m_isBuffer = false;
288     GLuint m_buf = 0;
289     uint32_t m_displayId = 0;
290     bool m_BRSwizzle = false;
291 };
292 
293 typedef std::shared_ptr<ColorBufferGl> ColorBufferGlPtr;
294 
295 }  // namespace gl
296 }  // namespace gfxstream
297