* commit '2257c1fd9f7f9d057bdc811208e342483c59c935': opengles emulator: handle window surface resize
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "ColorBuffer.h"
|
||||
#include "RenderContext.h"
|
||||
#include "FBConfig.h"
|
||||
#include "SmartPtr.h"
|
||||
#include "FixedBuffer.h"
|
||||
#include <EGL/egl.h>
|
||||
@@ -44,6 +45,7 @@ private:
|
||||
WindowSurface();
|
||||
|
||||
void copyToColorBuffer(); // copy pbuffer content with readback+download
|
||||
bool resizePbuffer(unsigned int p_width, unsigned int p_height);
|
||||
|
||||
private:
|
||||
GLuint m_fbObj; // GLES Framebuffer object (when EGLimage is used)
|
||||
@@ -55,10 +57,13 @@ private:
|
||||
RenderContextPtr m_drawContext;
|
||||
GLuint m_width;
|
||||
GLuint m_height;
|
||||
GLuint m_pbufWidth;
|
||||
GLuint m_pbufHeight;
|
||||
bool m_useEGLImage;
|
||||
bool m_useBindToTexture;
|
||||
FixedBuffer m_xferBuffer;
|
||||
FixedBuffer m_xUpdateBuf;
|
||||
const FBConfig *m_fbconf;
|
||||
};
|
||||
|
||||
typedef SmartPtr<WindowSurface> WindowSurfacePtr;
|
||||
|
||||
Reference in New Issue
Block a user