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

Commit 016c8cbc authored by Daniel Lam's avatar Daniel Lam
Browse files

Enabled cropping support in SurfaceTexture

SurfaceTexture will modify the crop rect so it matches
the desired output aspect ratio when the scaling
mode is NATIVE_WINDOW_SCALING_MODE_CROP.  Added a test
for this new scaling mode.

Change-Id: I60f24dcbc294b65cd10a393d9e27d40f07d27bb6
parent 3bc59682
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -283,6 +283,8 @@ private:
    // gets set each time updateTexImage is called.
    int64_t mCurrentTimestamp;

    uint32_t mDefaultWidth, mDefaultHeight;

    // 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
    // and can be changed with a call to attachToContext.
+3 −1
Original line number Diff line number Diff line
@@ -531,7 +531,8 @@ status_t BufferQueue::queueBuffer(int buf,
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(buf);

    ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
    ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d]", buf, timestamp,
        crop.left, crop.top, crop.right, crop.bottom);

    sp<ConsumerListener> listener;

@@ -592,6 +593,7 @@ status_t BufferQueue::queueBuffer(int buf,
        switch (scalingMode) {
            case NATIVE_WINDOW_SCALING_MODE_FREEZE:
            case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
            case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
                break;
            default:
                ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
+36 −1
Original line number Diff line number Diff line
@@ -168,6 +168,8 @@ status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
{
    Mutex::Autolock lock(mMutex);
    mDefaultWidth = w;
    mDefaultHeight = h;
    return mBufferQueue->setDefaultBufferSize(w, h);
}

@@ -621,7 +623,40 @@ sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {

Rect SurfaceTexture::getCurrentCrop() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentCrop;

    Rect outCrop = mCurrentCrop;
    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
        int32_t newWidth = mCurrentCrop.width();
        int32_t newHeight = mCurrentCrop.height();

        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
            ST_LOGV("too wide: newWidth = %d", newWidth);
        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
            ST_LOGV("too tall: newHeight = %d", newHeight);
        }

        // The crop is too wide
        if (newWidth < mCurrentCrop.width()) {
            int32_t dw = (newWidth - mCurrentCrop.width())/2;
            outCrop.left -=dw;
            outCrop.right += dw;
        // The crop is too tall
        } else if (newHeight < mCurrentCrop.height()) {
            int32_t dh = (newHeight - mCurrentCrop.height())/2;
            outCrop.top -= dh;
            outCrop.bottom += dh;
        }

        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
            outCrop.left, outCrop.top,
            outCrop.right,outCrop.bottom);
    }



    return outCrop;
}

uint32_t SurfaceTexture::getCurrentTransform() const {
+1 −0
Original line number Diff line number Diff line
@@ -555,6 +555,7 @@ int SurfaceTextureClient::setScalingMode(int mode)
    switch (mode) {
        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
            break;
        default:
            ALOGE("unknown scaling mode: %d", mode);
+120 −0
Original line number Diff line number Diff line
@@ -236,6 +236,44 @@ protected:
        }
    }

    ::testing::AssertionResult assertRectEq(const Rect &r1,
        const Rect &r2, int tolerance=1) {

        String8 msg;

        if (abs(r1.left - r2.left) > tolerance) {
            msg += String8::format("left(%d isn't %d)", r1.left, r2.left);
        }
        if (abs(r1.top - r2.top) > tolerance) {
            if (!msg.isEmpty()) {
                msg += " ";
            }
            msg += String8::format("top(%d isn't %d)", r1.top, r2.top);
        }
        if (abs(r1.right - r2.right) > tolerance) {
            if (!msg.isEmpty()) {
                msg += " ";
            }
            msg += String8::format("right(%d isn't %d)", r1.right, r2.right);
        }
        if (abs(r1.bottom - r2.bottom) > tolerance) {
            if (!msg.isEmpty()) {
                msg += " ";
            }
            msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom);
        }
        if (!msg.isEmpty()) {
            msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]",
                r1.left, r1.top, r1.right, r1.bottom,
                r2.left, r2.top, r2.right, r2.bottom);
            fprintf(stderr, "assertRectEq: %s\n", msg.string());
            return ::testing::AssertionFailure(
                    ::testing::Message(msg.string()));
        } else {
            return ::testing::AssertionSuccess();
        }
    }

    int mDisplaySecs;
    sp<SurfaceComposerClient> mComposerClient;
    sp<SurfaceControl> mSurfaceControl;
@@ -1129,6 +1167,88 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
    EXPECT_EQ(OK,mST->updateTexImage());
}

TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
    ASSERT_EQ(OK, mST->setSynchronousMode(true));

    ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
        NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));

    // The producer image size
    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));

    // The consumer image size (16 x 9) ratio
    mST->setDefaultBufferSize(1280, 720);

    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU);

    ANativeWindowBuffer *anb;

    android_native_rect_t odd = {23, 78, 123, 477};
    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd));
    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
    EXPECT_EQ(OK,mST->updateTexImage());
    Rect r = mST->getCurrentCrop();
    assertRectEq(Rect(23, 78, 123, 477), r);

    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
}

// This test ensures the scaling mode does the right thing
// ie NATIVE_WINDOW_SCALING_MODE_CROP should crop
// the image such that it has the same aspect ratio as the
// default buffer size
TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
    ASSERT_EQ(OK, mST->setSynchronousMode(true));

    ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
        NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));

    // The producer image size
    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));

    // The consumer image size (16 x 9) ratio
    mST->setDefaultBufferSize(1280, 720);

    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU);

    ANativeWindowBuffer *anb;

    // The crop is in the shape of (320, 180) === 16 x 9
    android_native_rect_t standard = {10, 20, 330, 200};
    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard));
    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
    EXPECT_EQ(OK,mST->updateTexImage());
    Rect r = mST->getCurrentCrop();
    // crop should be the same as crop (same aspect ratio)
    assertRectEq(Rect(10, 20, 330, 200), r);

    // make this wider then desired aspect 239 x 100 (2.39:1)
    android_native_rect_t wide = {20, 30, 259, 130};
    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide));
    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
    EXPECT_EQ(OK,mST->updateTexImage());
    r = mST->getCurrentCrop();
    // crop should be the same height, but have cropped left and right borders
    // offset is 30.6 px L+, R-
    assertRectEq(Rect(51, 30, 228, 130), r);

    // This image is taller then desired aspect 400 x 300 (4:3)
    android_native_rect_t narrow = {0, 0, 400, 300};
    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow));
    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
    EXPECT_EQ(OK,mST->updateTexImage());
    r = mST->getCurrentCrop();
    // crop should be the same width, but have cropped top and bottom borders
    // offset is 37.5 px
    assertRectEq(Rect(0, 37, 400, 262), r);

    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
}

TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
    class ProducerThread : public Thread {
    public: