surfaceflinger: add RenderEngine::BindNativeBufferAsFramebuffer
It replaces BindImageAsFramebuffer and makes EGLImage an
implementation detail of RenderEngine.
Test: SurfaceFlinger_test
Change-Id: I01be2d95fb9af9cbefa1a72131afb0975f1e0296
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 560f74e..dfd9856 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -337,21 +337,33 @@
// ---------------------------------------------------------------------------
-RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
- RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
+RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer(
+ RenderEngine& engine, ANativeWindowBuffer* buffer) : mEngine(engine)
{
- mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
+ mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
+ if (mImage == EGL_NO_IMAGE_KHR) {
+ mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return;
+ }
+
+ mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus);
ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
"glCheckFramebufferStatusOES error %d", mStatus);
}
-RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
+RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() {
+ if (mImage == EGL_NO_IMAGE_KHR) {
+ return;
+ }
+
// back to main framebuffer
mEngine.unbindFramebuffer(mTexName, mFbName);
+ eglDestroyImageKHR(mEngine.mEGLDisplay, mImage);
}
-status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
+status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const {
return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 074e97c..2d5bfa3 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -31,6 +31,8 @@
#define EGL_NO_CONFIG ((EGLConfig)0)
+struct ANativeWindowBuffer;
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -90,13 +92,14 @@
void deleteTextures(size_t count, uint32_t const* names);
void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels);
- class BindImageAsFramebuffer {
+ class BindNativeBufferAsFramebuffer {
RenderEngine& mEngine;
+ EGLImageKHR mImage;
uint32_t mTexName, mFbName;
uint32_t mStatus;
public:
- BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
- ~BindImageAsFramebuffer();
+ BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer);
+ ~BindNativeBufferAsFramebuffer();
int getStatus() const;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c34854b..f139683 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4546,26 +4546,6 @@
});
}
-// A simple RAII class that holds an EGLImage and destroys it either:
-// a) When the destroy() method is called
-// b) When the object goes out of scope
-class ImageHolder {
-public:
- ImageHolder(EGLDisplay display, EGLImageKHR image) : mDisplay(display), mImage(image) {}
- ~ImageHolder() { destroy(); }
-
- void destroy() {
- if (mImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mDisplay, mImage);
- mImage = EGL_NO_IMAGE_KHR;
- }
- }
-
-private:
- const EGLDisplay mDisplay;
- EGLImageKHR mImage;
-};
-
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer,
@@ -4584,22 +4564,11 @@
return PERMISSION_DENIED;
}
- // create an EGLImage from the buffer so we can later
- // turn it into a texture
- EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
- if (image == EGL_NO_IMAGE_KHR) {
- return BAD_VALUE;
- }
-
- // This will automatically destroy the image if we return before calling its destroy method
- ImageHolder imageHolder(mEGLDisplay, image);
-
// this binds the given EGLImage as a framebuffer for the
// duration of this scope.
- RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
- if (imageBond.getStatus() != NO_ERROR) {
- ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+ RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+ if (bufferBond.getStatus() != NO_ERROR) {
+ ALOGE("got ANWB binding error while taking screenshot");
return INVALID_OPERATION;
}
@@ -4621,8 +4590,6 @@
delete [] pixels;
}
- // destroy our image
- imageHolder.destroy();
return NO_ERROR;
}