am 3127d80b: Merge "opengles emulator: handle window surface resize"
* commit '3127d80bd8edaeeaa53663ab92e1e09825635527': opengles emulator: handle window surface resize
This commit is contained in:
@@ -34,6 +34,8 @@ WindowSurface::WindowSurface() :
|
|||||||
m_drawContext(NULL),
|
m_drawContext(NULL),
|
||||||
m_width(0),
|
m_width(0),
|
||||||
m_height(0),
|
m_height(0),
|
||||||
|
m_pbufWidth(0),
|
||||||
|
m_pbufHeight(0),
|
||||||
m_useEGLImage(false),
|
m_useEGLImage(false),
|
||||||
m_useBindToTexture(false)
|
m_useBindToTexture(false)
|
||||||
{
|
{
|
||||||
@@ -56,6 +58,7 @@ WindowSurface *WindowSurface::create(int p_config, int p_width, int p_height)
|
|||||||
if (!win) {
|
if (!win) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
win->m_fbconf = fbconf;
|
||||||
|
|
||||||
FrameBuffer *fb = FrameBuffer::getFB();
|
FrameBuffer *fb = FrameBuffer::getFB();
|
||||||
const FrameBufferCaps &caps = fb->getCaps();
|
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) {
|
if (win->m_useEGLImage) {
|
||||||
}
|
}
|
||||||
else if (0 != (fbconf->getSurfaceType() & EGL_PBUFFER_BIT)) {
|
else if (0 != (fbconf->getSurfaceType() & EGL_PBUFFER_BIT)) {
|
||||||
|
if (!win->resizePbuffer(p_width, p_height)) {
|
||||||
//
|
|
||||||
// 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) {
|
|
||||||
delete win;
|
delete win;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -156,6 +132,24 @@ void WindowSurface::flushColorBuffer()
|
|||||||
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer)
|
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer)
|
||||||
{
|
{
|
||||||
m_attachedColorBuffer = 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);
|
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 "ColorBuffer.h"
|
||||||
#include "RenderContext.h"
|
#include "RenderContext.h"
|
||||||
|
#include "FBConfig.h"
|
||||||
#include "SmartPtr.h"
|
#include "SmartPtr.h"
|
||||||
#include "FixedBuffer.h"
|
#include "FixedBuffer.h"
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
@@ -44,6 +45,7 @@ private:
|
|||||||
WindowSurface();
|
WindowSurface();
|
||||||
|
|
||||||
void copyToColorBuffer(); // copy pbuffer content with readback+download
|
void copyToColorBuffer(); // copy pbuffer content with readback+download
|
||||||
|
bool resizePbuffer(unsigned int p_width, unsigned int p_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_fbObj; // GLES Framebuffer object (when EGLimage is used)
|
GLuint m_fbObj; // GLES Framebuffer object (when EGLimage is used)
|
||||||
@@ -55,10 +57,13 @@ private:
|
|||||||
RenderContextPtr m_drawContext;
|
RenderContextPtr m_drawContext;
|
||||||
GLuint m_width;
|
GLuint m_width;
|
||||||
GLuint m_height;
|
GLuint m_height;
|
||||||
|
GLuint m_pbufWidth;
|
||||||
|
GLuint m_pbufHeight;
|
||||||
bool m_useEGLImage;
|
bool m_useEGLImage;
|
||||||
bool m_useBindToTexture;
|
bool m_useBindToTexture;
|
||||||
FixedBuffer m_xferBuffer;
|
FixedBuffer m_xferBuffer;
|
||||||
FixedBuffer m_xUpdateBuf;
|
FixedBuffer m_xUpdateBuf;
|
||||||
|
const FBConfig *m_fbconf;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SmartPtr<WindowSurface> WindowSurfacePtr;
|
typedef SmartPtr<WindowSurface> WindowSurfacePtr;
|
||||||
|
|||||||
Reference in New Issue
Block a user