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