surfaceflinger: pass RenderEngine into BufferLayerConsumer
Add RenderEngine::isCurrent to replace
BufferLayerConsumer::checkAndUpdateEglStateLocked. Remove a
duplicated check in updateAndReleaseLocked. Use
RenderEngine::checkErrors.
Test: SurfaceFlinger_test
Change-Id: I6b97534a41a855d101965b498cb1afa72404227e
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index b52bef3..1cc37c7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -660,7 +660,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- mSurfaceFlingerConsumer = new BufferLayerConsumer(consumer, mTextureName, this);
+ mSurfaceFlingerConsumer = new BufferLayerConsumer(consumer,
+ mFlinger->getRenderEngine(), mTextureName, this);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceFlingerConsumer->setContentsChangedListener(this);
mSurfaceFlingerConsumer->setName(mName);
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 5569dfa..b86e542 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -23,6 +23,7 @@
#include "DispSync.h"
#include "Layer.h"
+#include "RenderEngine/RenderEngine.h"
#include <inttypes.h>
@@ -108,8 +109,8 @@
return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
}
-BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
- Layer* layer)
+BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine,
+ uint32_t tex, Layer* layer)
: ConsumerBase(bq, false),
mCurrentCrop(Rect::EMPTY_RECT),
mCurrentTransform(0),
@@ -123,10 +124,10 @@
mDefaultWidth(1),
mDefaultHeight(1),
mFilteringEnabled(true),
+ mRE(engine),
+ mEglDisplay(mRE.getEGLDisplay()),
mTexName(tex),
mLayer(layer),
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
BLC_LOGV("BufferLayerConsumer");
@@ -211,10 +212,10 @@
return NO_INIT;
}
- // Make sure the EGL state is the same as in previous calls.
- status_t err = checkAndUpdateEglStateLocked();
- if (err != NO_ERROR) {
- return err;
+ // Make sure RenderEngine is current
+ if (!mRE.isCurrent()) {
+ BLC_LOGE("updateTexImage: RenderEngine is not current");
+ return INVALID_OPERATION;
}
BufferItem item;
@@ -222,7 +223,7 @@
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
- err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
+ status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
@@ -338,13 +339,6 @@
int slot = item.mSlot;
- // Confirm state.
- err = checkAndUpdateEglStateLocked();
- if (err != NO_ERROR) {
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
- return err;
- }
-
// Ensure we have a valid EglImageKHR for the slot, creating an EglImage
// if nessessary, for the gralloc buffer currently in the slot in
// ConsumerBase.
@@ -418,15 +412,7 @@
}
status_t BufferLayerConsumer::bindTextureImageLocked() {
- if (mEglDisplay == EGL_NO_DISPLAY) {
- ALOGE("bindTextureImage: invalid display");
- return INVALID_OPERATION;
- }
-
- GLenum error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- BLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
- }
+ mRE.checkErrors();
glBindTexture(sTexTarget, mTexName);
if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) {
@@ -446,32 +432,6 @@
return doGLFenceWaitLocked();
}
-status_t BufferLayerConsumer::checkAndUpdateEglStateLocked() {
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- // if this is the first time we're called, mEglDisplay/mEglContext have
- // never been set, so don't error out (below).
- if (mEglDisplay == EGL_NO_DISPLAY) {
- mEglDisplay = dpy;
- }
- if (mEglContext == EGL_NO_CONTEXT) {
- mEglContext = ctx;
- }
-
- if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
- BLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
- BLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- return NO_ERROR;
-}
-
status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
BLC_LOGV("syncForReleaseLocked");
@@ -608,16 +568,8 @@
}
status_t BufferLayerConsumer::doGLFenceWaitLocked() const {
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
- BLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
- BLC_LOGE("doGLFenceWait: invalid current EGLContext");
+ if (!mRE.isCurrent()) {
+ BLC_LOGE("doGLFenceWait: RenderEngine is not current");
return INVALID_OPERATION;
}
@@ -630,7 +582,7 @@
return -errno;
}
EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
- EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+ EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (sync == EGL_NO_SYNC_KHR) {
close(fenceFd);
BLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
@@ -640,9 +592,9 @@
// XXX: The spec draft is inconsistent as to whether this should
// return an EGLint or void. Ignore the return value for now, as
// it's not strictly needed.
- eglWaitSyncKHR(dpy, sync, 0);
+ eglWaitSyncKHR(mEglDisplay, sync, 0);
EGLint eglErr = eglGetError();
- eglDestroySyncKHR(dpy, sync);
+ eglDestroySyncKHR(mEglDisplay, sync);
if (eglErr != EGL_SUCCESS) {
BLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
return UNKNOWN_ERROR;
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index cc35a66..a08f15b 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -36,6 +36,7 @@
class DispSync;
class Layer;
+class RenderEngine;
class String8;
/*
@@ -73,7 +74,8 @@
// BufferLayerConsumer constructs a new BufferLayerConsumer object.
// The tex parameter indicates the name of the OpenGL ES
// texture to which images are to be streamed.
- BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, Layer* layer);
+ BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine, uint32_t tex,
+ Layer* layer);
// Sets the contents changed listener. This should be used instead of
// ConsumerBase::setFrameAvailableListener().
@@ -230,12 +232,6 @@
// bind succeeds, this calls doGLFenceWait.
status_t bindTextureImageLocked();
- // Gets the current EGLDisplay and EGLContext values, and compares them
- // to mEglDisplay and mEglContext. If the fields have been previously
- // set, the values must match; if not, the fields are set to the current
- // values.
- status_t checkAndUpdateEglStateLocked();
-
private:
// EglImage is a utility class for tracking and creating EGLImageKHRs. There
// is primarily just one image per slot, but there is also special cases:
@@ -381,6 +377,11 @@
// setFilteringEnabled().
bool mFilteringEnabled;
+ RenderEngine& mRE;
+
+ // mEglDisplay is initialized to RenderEngine's EGLDisplay.
+ const EGLDisplay mEglDisplay;
+
// mTexName is the name of the OpenGL texture to which streamed images will
// be bound when updateTexImage is called. It is set at construction time.
const uint32_t mTexName;
@@ -397,17 +398,6 @@
sp<EglImage> mEglImage;
};
- // mEglDisplay is the EGLDisplay with which this BufferLayerConsumer is currently
- // associated. It is intialized to EGL_NO_DISPLAY and gets set to the
- // current display when updateTexImage is called for the first time.
- EGLDisplay mEglDisplay;
-
- // mEglContext is the OpenGL ES context with which this BufferLayerConsumer is
- // currently associated. It is initialized to EGL_NO_CONTEXT and gets set
- // to the current GL context when updateTexImage is called for the first
- // time.
- EGLContext mEglContext;
-
// mEGLSlots stores the buffers that have been allocated by the BufferQueue
// for each buffer slot. It is initialized to null pointers, and gets
// filled in with the result of BufferQueue::acquire when the
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index f1415c9..314333f 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -157,6 +157,10 @@
return GLExtensions::getInstance().hasImageCrop();
}
+bool RenderEngine::isCurrent() const {
+ return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
+}
+
bool RenderEngine::setCurrentSurface(const RE::Surface& surface) {
bool success = true;
EGLSurface eglSurface = surface.getEGLSurface();
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 57662a4..f886919 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -86,6 +86,10 @@
bool supportsImageCrop() const;
+ bool isCurrent() const;
+ bool setCurrentSurface(const RE::Surface& surface);
+ void resetCurrentSurface();
+
// synchronization
// flush submits RenderEngine command stream for execution and returns a
@@ -124,9 +128,6 @@
int getStatus() const;
};
- bool setCurrentSurface(const RE::Surface& surface);
- void resetCurrentSurface();
-
// set-up
virtual void checkErrors() const;
virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,