blob: 37e4f15cbaa110028836123692cf7b80cab8eb40 [file] [log] [blame]
/*
* 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