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