opengles emulator: handle window surface resize

resize the internal pbuffer we use for a WindowSurface
when a color buffer of different size is attached to the "window".
That fixes "Glyder 2 by glu" application view while loading.

Change-Id: I8f235f428e93077d57bd200f10b45b9a92f1a9d3
This commit is contained in:
Guy Zadickario
2011-08-03 12:56:49 +03:00
committed by David 'Digit' Turner
parent af8fb702d5
commit 62c6532937
2 changed files with 105 additions and 28 deletions

View File

@@ -34,6 +34,8 @@ WindowSurface::WindowSurface() :
m_drawContext(NULL),
m_width(0),
m_height(0),
m_pbufWidth(0),
m_pbufHeight(0),
m_useEGLImage(false),
m_useBindToTexture(false)
{
@@ -56,6 +58,7 @@ WindowSurface *WindowSurface::create(int p_config, int p_width, int p_height)
if (!win) {
return NULL;
}
win->m_fbconf = fbconf;
FrameBuffer *fb = FrameBuffer::getFB();
const FrameBufferCaps &caps = fb->getCaps();
@@ -79,34 +82,7 @@ WindowSurface *WindowSurface::create(int p_config, int p_width, int p_height)
if (win->m_useEGLImage) {
}
else if (0 != (fbconf->getSurfaceType() & EGL_PBUFFER_BIT)) {
//
// Use Pbuffer for the rendering surface, if possible
// set it such that it will be able to be bound to a texture
// later to prevent readback.
//
EGLint pbufAttribs[12];
pbufAttribs[0] = EGL_WIDTH;
pbufAttribs[1] = p_width;
pbufAttribs[2] = EGL_HEIGHT;
pbufAttribs[3] = p_height;
if (caps.has_BindToTexture) {
pbufAttribs[4] = EGL_TEXTURE_FORMAT;
pbufAttribs[5] = EGL_TEXTURE_RGBA;
pbufAttribs[6] = EGL_TEXTURE_TARGET;
pbufAttribs[7] = EGL_TEXTURE_2D;
pbufAttribs[8] = EGL_NONE;
win->m_useBindToTexture = true;
}
else {
pbufAttribs[4] = EGL_NONE;
}
win->m_eglSurface = s_egl.eglCreatePbufferSurface(fb->getDisplay(),
fbconf->getEGLConfig(),
pbufAttribs);
if (win->m_eglSurface == EGL_NO_SURFACE) {
if (!win->resizePbuffer(p_width, p_height)) {
delete win;
return NULL;
}
@@ -156,6 +132,24 @@ void WindowSurface::flushColorBuffer()
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer)
{
m_attachedColorBuffer = p_colorBuffer;
//
// resize the window if the attached color buffer is of different
// size
//
unsigned int cbWidth = m_attachedColorBuffer->getWidth();
unsigned int cbHeight = m_attachedColorBuffer->getHeight();
if (cbWidth != m_width || cbHeight != m_height) {
if (m_pbufWidth && m_pbufHeight) {
// if we use pbuffer, need to resize it
resizePbuffer(cbWidth, cbHeight);
}
m_width = cbWidth;
m_height = cbHeight;
}
}
//
@@ -262,3 +256,81 @@ void WindowSurface::copyToColorBuffer()
prevReadSurf, prevContext);
}
bool WindowSurface::resizePbuffer(unsigned int p_width, unsigned int p_height)
{
if (m_eglSurface &&
m_pbufWidth == p_width &&
m_pbufHeight == p_height) {
// no need to resize
return true;
}
FrameBuffer *fb = FrameBuffer::getFB();
EGLContext prevContext = s_egl.eglGetCurrentContext();
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
EGLSurface prevPbuf = m_eglSurface;
bool needRebindContext = m_eglSurface &&
(prevReadSurf == m_eglSurface ||
prevDrawSurf == m_eglSurface);
if (needRebindContext) {
s_egl.eglMakeCurrent(fb->getDisplay(), EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
//
// Destroy previous surface
//
if (m_eglSurface) {
s_egl.eglDestroySurface(fb->getDisplay(), m_eglSurface);
m_eglSurface = NULL;
}
const FrameBufferCaps &caps = fb->getCaps();
//
// Create pbuffer surface, if possible
// set it such that it will be able to be bound to a texture
// later to prevent readback.
//
EGLint pbufAttribs[12];
pbufAttribs[0] = EGL_WIDTH;
pbufAttribs[1] = p_width;
pbufAttribs[2] = EGL_HEIGHT;
pbufAttribs[3] = p_height;
if (caps.has_BindToTexture) {
pbufAttribs[4] = EGL_TEXTURE_FORMAT;
pbufAttribs[5] = EGL_TEXTURE_RGBA;
pbufAttribs[6] = EGL_TEXTURE_TARGET;
pbufAttribs[7] = EGL_TEXTURE_2D;
pbufAttribs[8] = EGL_NONE;
m_useBindToTexture = true;
}
else {
pbufAttribs[4] = EGL_NONE;
}
m_eglSurface = s_egl.eglCreatePbufferSurface(fb->getDisplay(),
m_fbconf->getEGLConfig(),
pbufAttribs);
if (m_eglSurface == EGL_NO_SURFACE) {
fprintf(stderr, "Renderer error: failed to create/resize pbuffer!!\n");
return false;
}
m_pbufWidth = p_width;
m_pbufHeight = p_height;
if (needRebindContext) {
s_egl.eglMakeCurrent(fb->getDisplay(),
(prevDrawSurf==prevPbuf) ? m_eglSurface : prevDrawSurf,
(prevReadSurf==prevPbuf) ? m_eglSurface : prevReadSurf,
prevContext);
}
return true;
}