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:
committed by
David 'Digit' Turner
parent
af8fb702d5
commit
62c6532937
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user