Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eadbaa68 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

surfaceflinger: add RenderEngine::BindNativeBufferAsFramebuffer

It replaces BindImageAsFramebuffer and makes EGLImage an
implementation detail of RenderEngine.

Test: SurfaceFlinger_test
Change-Id: I01be2d95fb9af9cbefa1a72131afb0975f1e0296
parent b0c041b6
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -337,21 +337,33 @@ void RenderEngine::dump(String8& result) {

// ---------------------------------------------------------------------------

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;
}

+6 −3
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@

#define EGL_NO_CONFIG ((EGLConfig)0)

struct ANativeWindowBuffer;

// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -90,13 +92,14 @@ public:
    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;
    };

+3 −36
Original line number Diff line number Diff line
@@ -4546,26 +4546,6 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
    });
}

// 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 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
        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 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
        delete [] pixels;
    }

    // destroy our image
    imageHolder.destroy();
    return NO_ERROR;
}