OSDN Git Service

Return the transform to apply in getLastQueuedBuffer
authorJohn Reck <jreck@google.com>
Thu, 28 Apr 2016 20:18:15 +0000 (13:18 -0700)
committerJohn Reck <jreck@google.com>
Thu, 28 Apr 2016 21:02:42 +0000 (14:02 -0700)
Bug: 28428955
Change-Id: Id48f7d3bf3f5deb074cf0a6a52a41caac875db41

13 files changed:
include/gui/BufferQueueProducer.h
include/gui/GLConsumer.h
include/gui/IGraphicBufferProducer.h
include/gui/Surface.h
libs/gui/BufferQueueProducer.cpp
libs/gui/GLConsumer.cpp
libs/gui/IGraphicBufferProducer.cpp
libs/gui/Surface.cpp
libs/gui/tests/BufferQueue_test.cpp
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
services/surfaceflinger/MonitoredProducer.cpp
services/surfaceflinger/MonitoredProducer.h

index 7256f73..a75ed98 100644 (file)
@@ -184,7 +184,7 @@ public:
 
     // See IGraphicBufferProducer::getLastQueuedBuffer
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* 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<Fence> 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
index 8de3302..6267625 100644 (file)
@@ -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<GraphicBuffer>& 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.
     //
index 049406c..37ae6df 100644 (file)
@@ -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<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) = 0;
+            sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
 };
 
 // ----------------------------------------------------------------------------
index bbf427d..646203b 100644 (file)
@@ -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<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence);
+            sp<Fence>* outFence, float outTransformMatrix[16]);
 
 protected:
     virtual ~Surface();
index 73f61c5..3e26e05 100644 (file)
@@ -31,6 +31,7 @@
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
 #include <gui/BufferQueueProducer.h>
+#include <gui/GLConsumer.h>
 #include <gui/IConsumerListener.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
@@ -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<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
     ATRACE_CALL();
     BQ_LOGV("getLastQueuedBuffer");
 
@@ -1386,6 +1389,14 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* 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;
 }
 
index 3acd3ab..9937399 100644 (file)
@@ -787,26 +787,40 @@ void GLConsumer::setFilteringEnabled(bool enabled) {
 
 void GLConsumer::computeCurrentTransformMatrixLocked() {
     GLC_LOGV("computeCurrentTransformMatrixLocked");
+    sp<GraphicBuffer> 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<GraphicBuffer>& 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<GraphicBuffer> 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() {
index 137a54b..2c48d83 100644 (file)
@@ -382,7 +382,7 @@ public:
     }
 
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override {
+            sp<Fence>* 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<GraphicBuffer> buffer(nullptr);
             sp<Fence> 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);
index b304633..6811269 100644 (file)
@@ -128,8 +128,9 @@ status_t Surface::setDequeueTimeout(nsecs_t timeout) {
 }
 
 status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
-    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence);
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
 }
 
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
index 9876d94..85d63b4 100644 (file)
@@ -842,8 +842,10 @@ TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
     // Make sure we got the second buffer back
     sp<GraphicBuffer> returnedBuffer;
     sp<Fence> returnedFence;
+    float transform[16];
     ASSERT_EQ(OK,
-            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence));
+            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
+            transform));
     ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
             returnedBuffer->getNativeBuffer()->handle);
 }
index 7e4e797..bc8dfbb 100644 (file)
@@ -606,7 +606,8 @@ status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t /* timeout */) {
 }
 
 status_t VirtualDisplaySurface::getLastQueuedBuffer(
-        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/) {
+        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/,
+        float[16] /* outTransformMatrix*/) {
     ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
     return INVALID_OPERATION;
 }
index bd1cfb1..29563b6 100644 (file)
@@ -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<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
 
     //
     // Utility methods
@@ -254,4 +254,3 @@ private:
 // ---------------------------------------------------------------------------
 
 #endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
index e689127..faab62c 100644 (file)
@@ -144,8 +144,9 @@ status_t MonitoredProducer::setDequeueTimeout(nsecs_t timeout) {
 }
 
 status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-        sp<Fence>* outFence) {
-    return mProducer->getLastQueuedBuffer(outBuffer, outFence);
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
 }
 
 IBinder* MonitoredProducer::onAsBinder() {
index d2b4b43..ce756dc 100644 (file)
@@ -60,7 +60,7 @@ public:
     virtual uint64_t getNextFrameNumber() const override;
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
-            sp<Fence>* outFence) override;
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual IBinder* onAsBinder();
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     virtual status_t setAutoRefresh(bool autoRefresh) override;