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