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

Commit a9b1aa0b authored by Dan Stoza's avatar Dan Stoza
Browse files

SF: Add WindowDisconnector for screenshot code

Adds a simple WindowDisconnector class that holds an ANativeWindow* and
disconnects from it when it goes out of scope. This allows us to
drastically reduce the nesting of the captureScreenImplLocked method
of SurfaceFlinger.

Bug: 62257775
Test: SurfaceFlinger_test and manually verified that screenshots still
      work
Change-Id: I55123a7a6b2036158d0959328b0e6f8b206cce5d
parent 5ebcaf1b
Loading
Loading
Loading
Loading
+116 −101
Original line number Diff line number Diff line
@@ -4335,6 +4335,16 @@ void SurfaceFlinger::renderScreenImplLocked(
    hw->setViewportAndProjection();
}

// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
    WindowDisconnector(ANativeWindow* window, int api) : mWindow(window), mApi(api) {}
    ~WindowDisconnector() { native_window_api_disconnect(mWindow, mApi); }

private:
    ANativeWindow* const mWindow;
    const int mApi;
};

status_t SurfaceFlinger::captureScreenImplLocked(
        const sp<const DisplayDevice>& hw,
@@ -4395,7 +4405,13 @@ status_t SurfaceFlinger::captureScreenImplLocked(
    ANativeWindow* window = sur.get();

    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
    if (result == NO_ERROR) {
    if (result != NO_ERROR) {
        return result;
    }

    // This will disconnect from the window whenever we leave this method
    WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);

    uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
                    GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;

@@ -4405,19 +4421,28 @@ status_t SurfaceFlinger::captureScreenImplLocked(
    err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
    err |= native_window_set_usage(window, usage);

        if (err == NO_ERROR) {
    if (err != NO_ERROR) {
        return BAD_VALUE;
    }

    ANativeWindowBuffer* buffer;
    /* TODO: Once we have the sync framework everywhere this can use
     * server-side waits on the fence that dequeueBuffer returns.
     */
    result = native_window_dequeue_buffer_and_wait(window,  &buffer);
            if (result == NO_ERROR) {
    if (result != NO_ERROR) {
        return result;
    }

    int syncFd = -1;
    // 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) {
    if (image == EGL_NO_IMAGE_KHR) {
        return BAD_VALUE;
    }

    // this binds the given EGLImage as a framebuffer for the
    // duration of this scope.
    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
@@ -4430,13 +4455,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(
            hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
            useIdentityTransform, rotation);

#ifdef USE_HWC2
        if (hasWideColorDisplay) {
            native_window_set_buffers_data_space(window,
                getRenderEngine().usesWideColor() ?
                    HAL_DATASPACE_DISPLAY_P3 : HAL_DATASPACE_V0_SRGB);
        }
#endif

        // Attempt to create a sync khr object that can produce a sync point. If that
        // isn't available, create a non-dupable sync object in the fallback path and
@@ -4491,19 +4514,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(
    }
    // destroy our image
    eglDestroyImageKHR(mEGLDisplay, image);
                } else {
                    result = BAD_VALUE;
                }

    if (buffer) {
        // queueBuffer takes ownership of syncFd
        result = window->queueBuffer(window, buffer, syncFd);
    }
            }
        } else {
            result = BAD_VALUE;
        }
        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
    }

    return result;
}