* commit 'ca84c2cf37597603f6502c9ba51ca8dbdccaa76d': opengles emulator: replace the readback at end of frame with blit
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user