am 2c68d0f3: Merge "opengles emulator: replace the readback at end of frame with blit"

* commit '2c68d0f347fa1c8a5bc51c34399173e4592dc831':
  opengles emulator: replace the readback at end of frame with blit
This commit is contained in:
David Turner
2011-08-16 03:35:39 -07:00
committed by Android Git Automerger
4 changed files with 145 additions and 2 deletions

View File

@@ -72,8 +72,24 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height,
s_gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//
// create another texture for that colorbuffer for blit
//
s_gl.glGenTextures(1, &cb->m_blitTex);
s_gl.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
s_gl.glTexImage2D(GL_TEXTURE_2D, 0, texInternalFormat,
p_width, p_height, 0,
texInternalFormat,
GL_UNSIGNED_BYTE, NULL);
s_gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
s_gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
s_gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
s_gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
cb->m_width = p_width;
cb->m_height = p_height;
cb->m_internalFormat = texInternalFormat;
if (fb->getCaps().has_eglimage_texture_2d) {
cb->m_eglImage = s_egl.eglCreateImageKHR(fb->getDisplay(),
@@ -81,6 +97,12 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height,
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)cb->m_tex,
NULL);
cb->m_blitEGLImage = s_egl.eglCreateImageKHR(fb->getDisplay(),
fb->getContext(),
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)cb->m_blitTex,
NULL);
}
fb->unbind_locked();
@@ -90,7 +112,8 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height,
ColorBuffer::ColorBuffer() :
m_tex(0),
m_eglImage(NULL),
m_fbo(0)
m_fbo(0),
m_internalFormat(0)
{
}
@@ -176,6 +199,90 @@ bool ColorBuffer::blitFromPbuffer(EGLSurface p_pbufSurface)
return true;
}
bool ColorBuffer::blitFromCurrentReadBuffer()
{
RenderThreadInfo *tInfo = getRenderThreadInfo();
if (!tInfo->currContext.Ptr()) {
// no Current context
return false;
}
//
// Create a temporary texture inside the current context
// from the blit_texture EGLImage and copy the pixels
// from the current read buffer to that texture
//
GLuint tmpTex;
GLint currTexBind;
if (tInfo->currContext->isGL2()) {
s_gl2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
s_gl2.glGenTextures(1,&tmpTex);
s_gl2.glBindTexture(GL_TEXTURE_2D, tmpTex);
s_gl2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
s_gl2.glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat,
0, 0, m_width, m_height, 0);
}
else {
s_gl.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
s_gl.glGenTextures(1,&tmpTex);
s_gl.glBindTexture(GL_TEXTURE_2D, tmpTex);
s_gl.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
s_gl.glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat,
0, 0, m_width, m_height, 0);
}
//
// Now bind the frame buffer context and blit from
// m_blitTex into m_tex
//
FrameBuffer *fb = FrameBuffer::getFB();
if (fb->bind_locked()) {
//
// bind FBO object which has this colorbuffer as render target
//
if (bind_fbo()) {
//
// save current viewport and match it to the current
// colorbuffer size
//
GLint vport[4];
s_gl.glGetIntegerv(GL_VIEWPORT, vport);
s_gl.glViewport(0, 0, m_width, m_height);
// render m_blitTex
s_gl.glBindTexture(GL_TEXTURE_2D, m_blitTex);
drawTexQuad(); // this will render the texture flipped
// unbind the fbo
s_gl.glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
// restrore previous viewport
s_gl.glViewport(vport[0], vport[1], vport[2], vport[3]);
}
// unbind from the FrameBuffer context
fb->unbind_locked();
}
//
// delete the temporary texture and restore the texture binding
// inside the current context
//
if (tInfo->currContext->isGL2()) {
s_gl2.glDeleteTextures(1, &tmpTex);
s_gl2.glBindTexture(GL_TEXTURE_2D, currTexBind);
}
else {
s_gl.glDeleteTextures(1, &tmpTex);
s_gl.glBindTexture(GL_TEXTURE_2D, currTexBind);
}
return true;
}
bool ColorBuffer::bindToTexture()
{
if (m_eglImage) {

View File

@@ -38,6 +38,7 @@ public:
bool post();
bool bindToTexture();
bool bindToRenderbuffer();
bool blitFromCurrentReadBuffer();
private:
ColorBuffer();
@@ -46,10 +47,13 @@ private:
private:
GLuint m_tex;
GLuint m_blitTex;
EGLImageKHR m_eglImage;
EGLImageKHR m_blitEGLImage;
GLuint m_width;
GLuint m_height;
GLuint m_fbo;
GLenum m_internalFormat;
};
typedef SmartPtr<ColorBuffer> ColorBufferPtr;

View File

@@ -115,7 +115,8 @@ void WindowSurface::flushColorBuffer()
}
if (!copied) {
copyToColorBuffer();
//copyToColorBuffer();
blitToColorBuffer();
}
}
else {
@@ -257,6 +258,36 @@ void WindowSurface::copyToColorBuffer()
}
void WindowSurface::blitToColorBuffer()
{
if (!m_width && !m_height) return;
if (m_attachedColorBuffer->getWidth() != m_width ||
m_attachedColorBuffer->getHeight() != m_height) {
// XXX: should never happen - how this needs to be handled?
return;
}
//
// Make the surface current
//
EGLContext prevContext = s_egl.eglGetCurrentContext();
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
FrameBuffer *fb = FrameBuffer::getFB();
if (!s_egl.eglMakeCurrent(fb->getDisplay(), m_eglSurface,
m_eglSurface, m_drawContext->getEGLContext())) {
return;
}
m_attachedColorBuffer->blitFromCurrentReadBuffer();
// restore current context/surface
s_egl.eglMakeCurrent(fb->getDisplay(), prevDrawSurf,
prevReadSurf, prevContext);
}
bool WindowSurface::resizePbuffer(unsigned int p_width, unsigned int p_height)
{
if (m_eglSurface &&

View File

@@ -45,6 +45,7 @@ private:
WindowSurface();
void copyToColorBuffer(); // copy pbuffer content with readback+download
void blitToColorBuffer(); // copy pbuffer content with texload and blit
bool resizePbuffer(unsigned int p_width, unsigned int p_height);
private: