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:
@@ -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.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
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_width = p_width;
|
||||||
cb->m_height = p_height;
|
cb->m_height = p_height;
|
||||||
|
cb->m_internalFormat = texInternalFormat;
|
||||||
|
|
||||||
if (fb->getCaps().has_eglimage_texture_2d) {
|
if (fb->getCaps().has_eglimage_texture_2d) {
|
||||||
cb->m_eglImage = s_egl.eglCreateImageKHR(fb->getDisplay(),
|
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,
|
EGL_GL_TEXTURE_2D_KHR,
|
||||||
(EGLClientBuffer)cb->m_tex,
|
(EGLClientBuffer)cb->m_tex,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
cb->m_blitEGLImage = s_egl.eglCreateImageKHR(fb->getDisplay(),
|
||||||
|
fb->getContext(),
|
||||||
|
EGL_GL_TEXTURE_2D_KHR,
|
||||||
|
(EGLClientBuffer)cb->m_blitTex,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
fb->unbind_locked();
|
fb->unbind_locked();
|
||||||
@@ -90,7 +112,8 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height,
|
|||||||
ColorBuffer::ColorBuffer() :
|
ColorBuffer::ColorBuffer() :
|
||||||
m_tex(0),
|
m_tex(0),
|
||||||
m_eglImage(NULL),
|
m_eglImage(NULL),
|
||||||
m_fbo(0)
|
m_fbo(0),
|
||||||
|
m_internalFormat(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +199,90 @@ bool ColorBuffer::blitFromPbuffer(EGLSurface p_pbufSurface)
|
|||||||
return true;
|
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()
|
bool ColorBuffer::bindToTexture()
|
||||||
{
|
{
|
||||||
if (m_eglImage) {
|
if (m_eglImage) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
bool post();
|
bool post();
|
||||||
bool bindToTexture();
|
bool bindToTexture();
|
||||||
bool bindToRenderbuffer();
|
bool bindToRenderbuffer();
|
||||||
|
bool blitFromCurrentReadBuffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ColorBuffer();
|
ColorBuffer();
|
||||||
@@ -46,10 +47,13 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_tex;
|
GLuint m_tex;
|
||||||
|
GLuint m_blitTex;
|
||||||
EGLImageKHR m_eglImage;
|
EGLImageKHR m_eglImage;
|
||||||
|
EGLImageKHR m_blitEGLImage;
|
||||||
GLuint m_width;
|
GLuint m_width;
|
||||||
GLuint m_height;
|
GLuint m_height;
|
||||||
GLuint m_fbo;
|
GLuint m_fbo;
|
||||||
|
GLenum m_internalFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SmartPtr<ColorBuffer> ColorBufferPtr;
|
typedef SmartPtr<ColorBuffer> ColorBufferPtr;
|
||||||
|
|||||||
@@ -115,7 +115,8 @@ void WindowSurface::flushColorBuffer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!copied) {
|
if (!copied) {
|
||||||
copyToColorBuffer();
|
//copyToColorBuffer();
|
||||||
|
blitToColorBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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)
|
bool WindowSurface::resizePbuffer(unsigned int p_width, unsigned int p_height)
|
||||||
{
|
{
|
||||||
if (m_eglSurface &&
|
if (m_eglSurface &&
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ private:
|
|||||||
WindowSurface();
|
WindowSurface();
|
||||||
|
|
||||||
void copyToColorBuffer(); // copy pbuffer content with readback+download
|
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);
|
bool resizePbuffer(unsigned int p_width, unsigned int p_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user