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
This commit is contained in:
parent
3bc59682cd
commit
016c8cbce4
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue