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