From: John Reck Date: Thu, 28 Apr 2016 20:18:15 +0000 (-0700) Subject: Return the transform to apply in getLastQueuedBuffer X-Git-Tag: android-x86-7.1-r1~145^2~84^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=1a61da5e28fa16ad556a58193c8bbeb32a5f636d;p=android-x86%2Fframeworks-native.git Return the transform to apply in getLastQueuedBuffer Bug: 28428955 Change-Id: Id48f7d3bf3f5deb074cf0a6a52a41caac875db41 --- diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 7256f73fb3..a75ed98b57 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -184,7 +184,7 @@ public: // See IGraphicBufferProducer::getLastQueuedBuffer virtual status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence) override; + sp* outFence, float outTransformMatrix[16]) override; private: // This is required by the IBinder::DeathRecipient interface @@ -227,6 +227,9 @@ private: // since the previous buffer might have already been acquired. sp mLastQueueBufferFence; + Rect mLastQueuedCrop; + uint32_t mLastQueuedTransform; + // Take-a-ticket system for ensuring that onFrame* callbacks are called in // the order that frames are queued. While the BufferQueue lock // (mCore->mMutex) is held, a ticket is retained by the producer. After diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h index 8de3302401..6267625e96 100644 --- a/include/gui/GLConsumer.h +++ b/include/gui/GLConsumer.h @@ -132,6 +132,12 @@ public: // functions. void getTransformMatrix(float mtx[16]); + // Computes the transform matrix documented by getTransformMatrix + // from the BufferItem sub parts. + static void computeTransformMatrix(float outTransform[16], + const sp& buf, const Rect& cropRect, + uint32_t transform, bool filtering); + // getTimestamp retrieves the timestamp associated with the texture image // set by the most recent call to updateTexImage. // diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 049406ca59..37ae6df39e 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -563,9 +563,11 @@ public: // the queue, outBuffer will be populated with nullptr and outFence will be // populated with Fence::NO_FENCE // + // outTransformMatrix is not modified if outBuffer is null. + // // Returns NO_ERROR or the status of the Binder transaction virtual status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence) = 0; + sp* outFence, float outTransformMatrix[16]) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/Surface.h b/include/gui/Surface.h index bbf427dc07..646203bd9a 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -130,8 +130,9 @@ public: bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout); // See IGraphicBufferProducer::getLastQueuedBuffer + // See GLConsumer::getTransformMatrix for outTransformMatrix format status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence); + sp* outFence, float outTransformMatrix[16]); protected: virtual ~Surface(); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 73f61c5e98..3e26e058fb 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -923,6 +924,8 @@ status_t BufferQueueProducer::queueBuffer(int slot, mLastQueueBufferFence->waitForever("Throttling EGL Production"); } mLastQueueBufferFence = fence; + mLastQueuedCrop = item.mCrop; + mLastQueuedTransform = item.mTransform; return NO_ERROR; } @@ -1372,7 +1375,7 @@ status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) { } status_t BufferQueueProducer::getLastQueuedBuffer(sp* outBuffer, - sp* outFence) { + sp* outFence, float outTransformMatrix[16]) { ATRACE_CALL(); BQ_LOGV("getLastQueuedBuffer"); @@ -1386,6 +1389,14 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp* outBuffer, *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer; *outFence = mLastQueueBufferFence; + // Currently only SurfaceFlinger internally ever changes + // GLConsumer's filtering mode, so we just use 'true' here as + // this is slightly specialized for the current client of this API, + // which does want filtering. + GLConsumer::computeTransformMatrix(outTransformMatrix, + mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop, + mLastQueuedTransform, true /* filter */); + return NO_ERROR; } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 3acd3ab802..9937399a87 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -787,26 +787,40 @@ void GLConsumer::setFilteringEnabled(bool enabled) { void GLConsumer::computeCurrentTransformMatrixLocked() { GLC_LOGV("computeCurrentTransformMatrixLocked"); + sp buf = (mCurrentTextureImage == nullptr) ? + nullptr : mCurrentTextureImage->graphicBuffer(); + if (buf == nullptr) { + GLC_LOGD("computeCurrentTransformMatrixLocked: " + "mCurrentTextureImage is NULL"); + } + computeTransformMatrix(mCurrentTransformMatrix, buf, + isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop, + mCurrentTransform, mFilteringEnabled); +} + +void GLConsumer::computeTransformMatrix(float outTransform[16], + const sp& buf, const Rect& cropRect, uint32_t transform, + bool filtering) { float xform[16]; for (int i = 0; i < 16; i++) { xform[i] = mtxIdentity[i]; } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { float result[16]; mtxMul(result, xform, mtxFlipH); for (int i = 0; i < 16; i++) { xform[i] = result[i]; } } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { float result[16]; mtxMul(result, xform, mtxFlipV); for (int i = 0; i < 16; i++) { xform[i] = result[i]; } } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { float result[16]; mtxMul(result, xform, mtxRot90); for (int i = 0; i < 16; i++) { @@ -814,59 +828,49 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { } } - sp buf = (mCurrentTextureImage == NULL) ? - NULL : mCurrentTextureImage->graphicBuffer(); - - if (buf == NULL) { - GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL"); - } - float mtxBeforeFlipV[16]; - if (!isEglImageCroppable(mCurrentCrop)) { - Rect cropRect = mCurrentCrop; + if (!cropRect.isEmpty()) { float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f; float bufferWidth = buf->getWidth(); float bufferHeight = buf->getHeight(); - if (!cropRect.isEmpty()) { - float shrinkAmount = 0.0f; - if (mFilteringEnabled) { - // In order to prevent bilinear sampling beyond the edge of the - // crop rectangle we may need to shrink it by 2 texels in each - // dimension. Normally this would just need to take 1/2 a texel - // off each end, but because the chroma channels of YUV420 images - // are subsampled we may need to shrink the crop region by a whole - // texel on each side. - switch (buf->getPixelFormat()) { - case PIXEL_FORMAT_RGBA_8888: - case PIXEL_FORMAT_RGBX_8888: - case PIXEL_FORMAT_RGB_888: - case PIXEL_FORMAT_RGB_565: - case PIXEL_FORMAT_BGRA_8888: - // We know there's no subsampling of any channels, so we - // only need to shrink by a half a pixel. - shrinkAmount = 0.5; - break; - - default: - // If we don't recognize the format, we must assume the - // worst case (that we care about), which is YUV420. - shrinkAmount = 1.0; - break; - } + float shrinkAmount = 0.0f; + if (filtering) { + // In order to prevent bilinear sampling beyond the edge of the + // crop rectangle we may need to shrink it by 2 texels in each + // dimension. Normally this would just need to take 1/2 a texel + // off each end, but because the chroma channels of YUV420 images + // are subsampled we may need to shrink the crop region by a whole + // texel on each side. + switch (buf->getPixelFormat()) { + case PIXEL_FORMAT_RGBA_8888: + case PIXEL_FORMAT_RGBX_8888: + case PIXEL_FORMAT_RGB_888: + case PIXEL_FORMAT_RGB_565: + case PIXEL_FORMAT_BGRA_8888: + // We know there's no subsampling of any channels, so we + // only need to shrink by a half a pixel. + shrinkAmount = 0.5; + break; + + default: + // If we don't recognize the format, we must assume the + // worst case (that we care about), which is YUV420. + shrinkAmount = 1.0; + break; } + } - // Only shrink the dimensions that are not the size of the buffer. - if (cropRect.width() < bufferWidth) { - tx = (float(cropRect.left) + shrinkAmount) / bufferWidth; - sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / - bufferWidth; - } - if (cropRect.height() < bufferHeight) { - ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / - bufferHeight; - sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / - bufferHeight; - } + // Only shrink the dimensions that are not the size of the buffer. + if (cropRect.width() < bufferWidth) { + tx = (float(cropRect.left) + shrinkAmount) / bufferWidth; + sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / + bufferWidth; + } + if (cropRect.height() < bufferHeight) { + ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / + bufferHeight; + sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / + bufferHeight; } float crop[16] = { sx, 0, 0, 0, @@ -886,7 +890,7 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { // coordinate of 0, so GLConsumer must behave the same way. We don't // want to expose this to applications, however, so we must add an // additional vertical flip to the transform after all the other transforms. - mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV); + mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV); } nsecs_t GLConsumer::getTimestamp() { diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 137a54bcfb..2c48d83d96 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -382,7 +382,7 @@ public: } virtual status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence) override { + sp* outFence, float outTransformMatrix[16]) override { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data, @@ -400,6 +400,9 @@ public: if (hasBuffer) { buffer = new GraphicBuffer(); result = reply.read(*buffer); + if (result == NO_ERROR) { + result = reply.read(outTransformMatrix, sizeof(float) * 16); + } } if (result != NO_ERROR) { ALOGE("getLastQueuedBuffer failed to read buffer: %d", result); @@ -630,7 +633,8 @@ status_t BnGraphicBufferProducer::onTransact( CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp buffer(nullptr); sp fence(Fence::NO_FENCE); - status_t result = getLastQueuedBuffer(&buffer, &fence); + float transform[16] = {}; + status_t result = getLastQueuedBuffer(&buffer, &fence, transform); reply->writeInt32(result); if (result != NO_ERROR) { return result; @@ -640,6 +644,9 @@ status_t BnGraphicBufferProducer::onTransact( } else { reply->writeBool(true); result = reply->write(*buffer); + if (result == NO_ERROR) { + reply->write(transform, sizeof(float) * 16); + } } if (result != NO_ERROR) { ALOGE("getLastQueuedBuffer failed to write buffer: %d", result); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index b3046337b7..6811269a39 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -128,8 +128,9 @@ status_t Surface::setDequeueTimeout(nsecs_t timeout) { } status_t Surface::getLastQueuedBuffer(sp* outBuffer, - sp* outFence) { - return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence); + sp* outFence, float outTransformMatrix[16]) { + return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence, + outTransformMatrix); } int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 9876d9465a..85d63b4ba2 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -842,8 +842,10 @@ TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) { // Make sure we got the second buffer back sp returnedBuffer; sp returnedFence; + float transform[16]; ASSERT_EQ(OK, - mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence)); + mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence, + transform)); ASSERT_EQ(secondBuffer->getNativeBuffer()->handle, returnedBuffer->getNativeBuffer()->handle); } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 7e4e797429..bc8dfbb5b6 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -606,7 +606,8 @@ status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t /* timeout */) { } status_t VirtualDisplaySurface::getLastQueuedBuffer( - sp* /*outBuffer*/, sp* /*outFence*/) { + sp* /*outBuffer*/, sp* /*outFence*/, + float[16] /* outTransformMatrix*/) { ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface"); return INVALID_OPERATION; } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index bd1cfb1de3..29563b6a06 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -127,7 +127,7 @@ private: virtual status_t setAutoRefresh(bool autoRefresh) override; virtual status_t setDequeueTimeout(nsecs_t timeout) override; virtual status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence) override; + sp* outFence, float outTransformMatrix[16]) override; // // Utility methods @@ -254,4 +254,3 @@ private: // --------------------------------------------------------------------------- #endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H - diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index e6891271d1..faab62cb4e 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -144,8 +144,9 @@ status_t MonitoredProducer::setDequeueTimeout(nsecs_t timeout) { } status_t MonitoredProducer::getLastQueuedBuffer(sp* outBuffer, - sp* outFence) { - return mProducer->getLastQueuedBuffer(outBuffer, outFence); + sp* outFence, float outTransformMatrix[16]) { + return mProducer->getLastQueuedBuffer(outBuffer, outFence, + outTransformMatrix); } IBinder* MonitoredProducer::onAsBinder() { diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index d2b4b4346e..ce756dc822 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -60,7 +60,7 @@ public: virtual uint64_t getNextFrameNumber() const override; virtual status_t setDequeueTimeout(nsecs_t timeout) override; virtual status_t getLastQueuedBuffer(sp* outBuffer, - sp* outFence) override; + sp* outFence, float outTransformMatrix[16]) override; virtual IBinder* onAsBinder(); virtual status_t setSharedBufferMode(bool sharedBufferMode) override; virtual status_t setAutoRefresh(bool autoRefresh) override;