EmuGL: don't [de]queue buffers in eglMakeCurrent
Whenever a surface was attached to a context, it was dequeing a new
buffer, and enqueing it when detached. This has the effect of doing a
SwapBuffers on detach/attach cycle, which is just wrong and
occasionally caused visible glitches (e.g. animations going backwards
for one frame). It also broke some SurfaceTexture tests which
(validly) depend on specific buffer production/consumption counts.
Change-Id: Ibd4761e8842871b79fd9edf52272900193cb672d
diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp
index e949b96..49223a0 100644
--- a/tools/emulator/opengl/system/egl/egl.cpp
+++ b/tools/emulator/opengl/system/egl/egl.cpp
@@ -124,8 +124,6 @@
#define VALIDATE_SURFACE_RETURN(surface, ret) \
if (surface != EGL_NO_SURFACE) { \
egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
- if (!s->isValid()) \
- setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); \
if (s->dpy != (EGLDisplay)&s_display) \
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
}
@@ -175,49 +173,39 @@
egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
virtual ~egl_surface_t();
- virtual EGLBoolean rcCreate() = 0;
- virtual EGLBoolean rcDestroy() = 0;
-
- virtual EGLBoolean connect() { return EGL_TRUE; }
- virtual void disconnect() {}
virtual void setSwapInterval(int interval) = 0;
- virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
- virtual EGLint getSwapBehavior() const;
+ virtual EGLBoolean swapBuffers() = 0;
- void setRcSurface(uint32_t handle){ rcSurface = handle; }
- uint32_t getRcSurface(){ return rcSurface; }
+ EGLint getSwapBehavior() const;
+ uint32_t getRcSurface() { return rcSurface; }
+ EGLint getSurfaceType() { return surfaceType; }
- virtual EGLBoolean isValid(){ return valid; }
- EGLint getSurfaceType(){ return surfaceType; }
-
- void setWidth(EGLint w){ width = w; }
EGLint getWidth(){ return width; }
- void setHeight(EGLint h){ height = h; }
EGLint getHeight(){ return height; }
- void setTextureFormat(EGLint _texFormat){ texFormat = _texFormat; }
- EGLint getTextureFormat(){ return texFormat; }
- void setTextureTarget(EGLint _texTarget){ texTarget = _texTarget; }
- EGLint getTextureTarget(){ return texTarget; }
+ void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
+ EGLint getTextureFormat() { return texFormat; }
+ void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
+ EGLint getTextureTarget() { return texTarget; }
private:
//
//Surface attributes
//
- EGLint width;
- EGLint height;
- EGLint texFormat;
- EGLint texTarget;
+ EGLint width;
+ EGLint height;
+ EGLint texFormat;
+ EGLint texTarget;
protected:
- EGLint surfaceType;
- EGLBoolean valid;
- uint32_t rcSurface; //handle to surface created via remote control
+ void setWidth(EGLint w) { width = w; }
+ void setHeight(EGLint h) { height = h; }
-
+ EGLint surfaceType;
+ uint32_t rcSurface; //handle to surface created via remote control
};
egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
- : dpy(dpy), config(config), surfaceType(surfaceType), valid(EGL_FALSE), rcSurface(0)
+ : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
{
width = 0;
height = 0;
@@ -226,7 +214,7 @@
}
EGLint egl_surface_t::getSwapBehavior() const {
- return EGL_BUFFER_PRESERVED;
+ return EGL_BUFFER_PRESERVED;
}
egl_surface_t::~egl_surface_t()
@@ -237,32 +225,29 @@
// egl_window_surface_t
struct egl_window_surface_t : public egl_surface_t {
-
- egl_window_surface_t(
+ static egl_window_surface_t* create(
EGLDisplay dpy, EGLConfig config, EGLint surfType,
ANativeWindow* window);
- ~egl_window_surface_t();
+ virtual ~egl_window_surface_t();
- virtual EGLBoolean rcCreate();
- virtual EGLBoolean rcDestroy();
-
- virtual EGLBoolean connect();
- virtual void disconnect();
- virtual void setSwapInterval(int interval);
- virtual EGLBoolean swapBuffers();
+ virtual void setSwapInterval(int interval);
+ virtual EGLBoolean swapBuffers();
private:
- ANativeWindow* nativeWindow;
- android_native_buffer_t* buffer;
+ egl_window_surface_t(
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window);
+ EGLBoolean init();
+ ANativeWindow* nativeWindow;
+ android_native_buffer_t* buffer;
};
-
egl_window_surface_t::egl_window_surface_t (
- EGLDisplay dpy, EGLConfig config, EGLint surfType,
- ANativeWindow* window)
- : egl_surface_t(dpy, config, surfType),
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window)
+: egl_surface_t(dpy, config, surfType),
nativeWindow(window),
buffer(NULL)
{
@@ -275,58 +260,48 @@
setHeight(h);
}
-egl_window_surface_t::~egl_window_surface_t() {
- nativeWindow->common.decRef(&nativeWindow->common);
-}
-
-EGLBoolean egl_window_surface_t::rcCreate()
+EGLBoolean egl_window_surface_t::init()
{
+ if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+ setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
- rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, getWidth(), getHeight());
+ rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
+ getWidth(), getHeight());
if (!rcSurface) {
LOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
- valid = EGL_TRUE;
+ rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
+ ((cb_handle_t*)(buffer->handle))->hostHandle);
+
return EGL_TRUE;
}
-EGLBoolean egl_window_surface_t::rcDestroy()
+egl_window_surface_t* egl_window_surface_t::create(
+ EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ ANativeWindow* window)
{
- if (!rcSurface) {
- LOGE("rcDestroy called on invalid rcSurface");
- return EGL_FALSE;
+ egl_window_surface_t* wnd = new egl_window_surface_t(
+ dpy, config, surfType, window);
+ if (wnd && !wnd->init()) {
+ delete wnd;
+ wnd = NULL;
}
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
- rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
- rcSurface = 0;
-
- return EGL_TRUE;
+ return wnd;
}
-EGLBoolean egl_window_surface_t::connect()
-{
- // dequeue a buffer
- if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
- setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
+egl_window_surface_t::~egl_window_surface_t() {
+ DEFINE_HOST_CONNECTION;
+ if (rcSurface && rcEnc) {
+ rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
}
-
- // lock the buffer
- nativeWindow->lockBuffer(nativeWindow, buffer);
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
- rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, ((cb_handle_t *)(buffer->handle))->hostHandle);
-
- return EGL_TRUE;
-}
-
-void egl_window_surface_t::disconnect()
-{
if (buffer) {
- nativeWindow->queueBuffer(nativeWindow, buffer);
- buffer = 0;
+ nativeWindow->cancelBuffer(nativeWindow, buffer);
}
+ nativeWindow->common.decRef(&nativeWindow->common);
}
void egl_window_surface_t::setSwapInterval(int interval)
@@ -336,26 +311,19 @@
EGLBoolean egl_window_surface_t::swapBuffers()
{
- if (!buffer) {
- setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
- }
-
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
- //post the back buffer
nativeWindow->queueBuffer(nativeWindow, buffer);
-
- // dequeue a new buffer
if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
+ buffer = NULL;
setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
}
-
- // lock the buffer
nativeWindow->lockBuffer(nativeWindow, buffer);
- rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, ((cb_handle_t *)(buffer->handle))->hostHandle);
+ rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
+ ((cb_handle_t *)(buffer->handle))->hostHandle);
return EGL_TRUE;
}
@@ -364,30 +332,28 @@
//egl_pbuffer_surface_t
struct egl_pbuffer_surface_t : public egl_surface_t {
-
- GLenum format;
-
- egl_pbuffer_surface_t(
- EGLDisplay dpy, EGLConfig config, EGLint surfType,
- int32_t w, int32_t h, GLenum format);
+ static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
+ EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
virtual ~egl_pbuffer_surface_t();
- virtual EGLBoolean rcCreate();
- virtual EGLBoolean rcDestroy();
- virtual EGLBoolean connect();
- virtual void setSwapInterval(int interval) {}
+ virtual void setSwapInterval(int interval) {}
+ virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
- uint32_t getRcColorBuffer(){ return rcColorBuffer; }
- void setRcColorBuffer(uint32_t colorBuffer){ rcColorBuffer = colorBuffer; }
+ uint32_t getRcColorBuffer() { return rcColorBuffer; }
+
private:
+ egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
+ int32_t w, int32_t h);
+ EGLBoolean init(GLenum format);
+
uint32_t rcColorBuffer;
};
-egl_pbuffer_surface_t::egl_pbuffer_surface_t(
- EGLDisplay dpy, EGLConfig config, EGLint surfType,
- int32_t w, int32_t h, GLenum pixelFormat)
- : egl_surface_t(dpy, config, surfType), format(pixelFormat)
+egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
+ EGLint surfType, int32_t w, int32_t h)
+: egl_surface_t(dpy, config, surfType),
+ rcColorBuffer(0)
{
setWidth(w);
setHeight(h);
@@ -395,50 +361,49 @@
egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
{
- rcColorBuffer = 0;
+ DEFINE_HOST_CONNECTION;
+ if (rcEnc) {
+ if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
+ if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
+ }
}
-EGLBoolean egl_pbuffer_surface_t::rcCreate()
+EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
- rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, getWidth(), getHeight());
+
+ rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
+ getWidth(), getHeight());
if (!rcSurface) {
LOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
- rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), format);
+
+ rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
+ pixelFormat);
if (!rcColorBuffer) {
LOGE("rcCreateColorBuffer returned 0");
return EGL_FALSE;
}
- valid = EGL_TRUE;
- return EGL_TRUE;
-}
-
-EGLBoolean egl_pbuffer_surface_t::rcDestroy()
-{
- if ((!rcSurface)||(!rcColorBuffer)) {
- LOGE("destroyRc called on invalid rcSurface");
- return EGL_FALSE;
- }
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
- rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
- rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
- rcSurface = 0;
-
- return EGL_TRUE;
-}
-
-EGLBoolean egl_pbuffer_surface_t::connect()
-{
- DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
return EGL_TRUE;
}
+egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
+ EGLConfig config, EGLint surfType, int32_t w, int32_t h,
+ GLenum pixelFormat)
+{
+ egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
+ w, h);
+ if (pb && !pb->init(pixelFormat)) {
+ delete pb;
+ pb = NULL;
+ }
+ return pb;
+}
+
static const char *getGLString(int glEnum)
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
@@ -661,12 +626,9 @@
setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
- egl_surface_t* surface;
- surface = new egl_window_surface_t(&s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
- if (!surface)
- setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
- if (!surface->rcCreate()) {
- delete surface;
+ egl_surface_t* surface = egl_window_surface_t::create(
+ &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
+ if (!surface) {
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
@@ -718,11 +680,9 @@
if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
- egl_surface_t* surface = new egl_pbuffer_surface_t(dpy, config, surfaceType, w, h, pixelFormat);
- if (!surface)
- setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
- if (!surface->rcCreate()) {
- delete surface;
+ egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
+ surfaceType, w, h, pixelFormat);
+ if (!surface) {
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
@@ -748,10 +708,7 @@
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
- egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
-
- surface->disconnect();
- surface->rcDestroy();
+ egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
delete surface;
return EGL_TRUE;
@@ -995,14 +952,6 @@
setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
}
- //
- // Disconnect from the previous drawable
- //
- if (tInfo->currentContext && tInfo->currentContext->draw) {
- egl_surface_t * prevDrawSurf = static_cast<egl_surface_t *>(tInfo->currentContext->draw);
- prevDrawSurf->disconnect();
- }
-
//Now make the local bind
if (context) {
context->draw = draw;
@@ -1055,10 +1004,6 @@
}
}
- //connect the color buffer
- if (drawSurf)
- drawSurf->connect();
-
return EGL_TRUE;
}
@@ -1156,8 +1101,6 @@
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
- if (!d->isValid())
- setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
if (d->dpy != dpy)
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);