| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #ifndef _LIBRENDER_COLORBUFFER_H |
| #define _LIBRENDER_COLORBUFFER_H |
| |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| #include <GLES/gl.h> |
| #include "emugl/common/smart_ptr.h" |
| |
| #include <memory> |
| |
| |
| class TextureDraw; |
| class TextureResize; |
| |
| // A class used to model a guest color buffer, and used to implement several |
| // related things: |
| // |
| // - Every gralloc native buffer with HW read or write requirements will |
| // allocate a host ColorBuffer instance. When gralloc_lock() is called, |
| // the guest will use ColorBuffer::readPixels() to read the current content |
| // of the buffer. When gralloc_unlock() is later called, it will call |
| // ColorBuffer::subUpdate() to send the updated pixels. |
| // |
| // - Every guest window EGLSurface is implemented by a host PBuffer |
| // (see WindowSurface.h) that can have a ColorBuffer instance attached to |
| // it (through WindowSurface::attachColorBuffer()). When such an attachment |
| // exists, WindowSurface::flushColorBuffer() will copy the PBuffer's |
| // pixel data into the ColorBuffer. The latter can then be displayed |
| // in the client's UI sub-window with ColorBuffer::post(). |
| // |
| // - Guest EGLImages are implemented as native gralloc buffers too. |
| // The guest glEGLImageTargetTexture2DOES() implementations will end up |
| // calling ColorBuffer::bindToTexture() to bind the current context's |
| // GL_TEXTURE_2D to the buffer. Similarly, the guest versions of |
| // glEGLImageTargetRenderbufferStorageOES() will end up calling |
| // ColorBuffer::bindToRenderbuffer(). |
| // |
| // This forces the implementation to use a host EGLImage to implement each |
| // ColorBuffer. |
| // |
| // As an additional twist. |
| |
| class ColorBuffer { |
| public: |
| // Helper interface class used during ColorBuffer operations. This is |
| // introduced to remove coupling from the FrameBuffer class implementation. |
| class Helper { |
| public: |
| Helper() {} |
| virtual ~Helper() {} |
| virtual bool setupContext() = 0; |
| virtual void teardownContext() = 0; |
| virtual TextureDraw* getTextureDraw() const = 0; |
| }; |
| |
| // Create a new ColorBuffer instance. |
| // |p_display| is the host EGLDisplay handle. |
| // |p_width| and |p_height| are the buffer's dimensions in pixels. |
| // |p_internalFormat| is the internal pixel format to use, valid values |
| // are: GL_RGB, GL_RGB565, GL_RGBA, GL_RGB5_A1_OES and GL_RGBA4_OES. |
| // Implementation is free to use something else though. |
| // |has_eglimage_texture_2d| should be true iff the display supports |
| // the EGL_KHR_gl_texture_2D_image extension. |
| // Returns NULL on failure. |
| static ColorBuffer* create(EGLDisplay p_display, |
| int p_width, |
| int p_height, |
| GLenum p_internalFormat, |
| bool has_eglimage_texture_2d, |
| Helper* helper); |
| |
| // Destructor. |
| ~ColorBuffer(); |
| |
| // Return ColorBuffer width and height in pixels |
| GLuint getWidth() const { return m_width; } |
| GLuint getHeight() const { return m_height; } |
| |
| // Read the ColorBuffer instance's pixel values into host memory. |
| void readPixels(int x, |
| int y, |
| int width, |
| int height, |
| GLenum p_format, |
| GLenum p_type, |
| void *pixels); |
| |
| // Update the ColorBuffer instance's pixel values from host memory. |
| void subUpdate(int x, |
| int y, |
| int width, |
| int height, |
| GLenum p_format, |
| GLenum p_type, |
| void *pixels); |
| |
| // Draw a ColorBuffer instance, i.e. blit it to the current guest |
| // framebuffer object / window surface. This doesn't display anything. |
| bool draw(); |
| |
| // Post this ColorBuffer to the host native sub-window. |
| // |rotation| is the rotation angle in degrees, clockwise in the GL |
| // coordinate space. |
| bool post(float rotation, float dx, float dy); |
| |
| // Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's |
| // EGLImage. This is intended to implement glEGLImageTargetTexture2DOES() |
| // for all GLES versions. |
| bool bindToTexture(); |
| |
| // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this |
| // ColorBuffer's EGLImage. This is intended to implement |
| // glEGLImageTargetRenderbufferStorageOES() for all GLES versions. |
| bool bindToRenderbuffer(); |
| |
| // Copy the content of the current context's read surface to this |
| // ColorBuffer. This is used from WindowSurface::flushColorBuffer(). |
| // Return true on success, false on failure (e.g. no current context). |
| bool blitFromCurrentReadBuffer(); |
| |
| // Read the content of the whole ColorBuffer as 32-bit RGBA pixels. |
| // |img| must be a buffer large enough (i.e. width * height * 4). |
| void readback(unsigned char* img); |
| |
| private: |
| ColorBuffer(EGLDisplay display, Helper* helper); |
| |
| private: |
| GLuint m_tex = 0; |
| GLuint m_blitTex = 0; |
| EGLImageKHR m_eglImage = nullptr; |
| EGLImageKHR m_blitEGLImage = nullptr; |
| GLuint m_width = 0; |
| GLuint m_height = 0; |
| GLuint m_fbo = 0; |
| GLenum m_internalFormat = 0; |
| EGLDisplay m_display = nullptr; |
| Helper* m_helper = nullptr; |
| TextureResize* m_resizer = nullptr; |
| }; |
| |
| typedef emugl::SmartPtr<ColorBuffer> ColorBufferPtr; |
| |
| #endif |