OSDN Git Service

libgui: remove setPostTransformCrop
[android-x86/frameworks-native.git] / libs / gui / SurfaceTextureClient.cpp
index f88dcaf..36a81a6 100644 (file)
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
+#include <android/native_window.h>
+
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
+#include <gui/SurfaceTexture.h>
 #include <gui/SurfaceTextureClient.h>
 
 #include <private/gui/ComposerService.h>
@@ -36,6 +39,14 @@ SurfaceTextureClient::SurfaceTextureClient(
     SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
 }
 
+// see SurfaceTextureClient.h
+SurfaceTextureClient::SurfaceTextureClient(const
+         sp<SurfaceTexture>& surfaceTexture)
+{
+    SurfaceTextureClient::init();
+    SurfaceTextureClient::setISurfaceTexture(surfaceTexture->getBufferQueue());
+}
+
 SurfaceTextureClient::SurfaceTextureClient() {
     SurfaceTextureClient::init();
 }
@@ -64,9 +75,15 @@ void SurfaceTextureClient::init() {
     mReqFormat = 0;
     mReqUsage = 0;
     mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
+    mCrop.clear();
+    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+    mTransform = 0;
     mDefaultWidth = 0;
     mDefaultHeight = 0;
+    mUserWidth = 0;
+    mUserHeight = 0;
     mTransformHint = 0;
+    mConsumerRunningBehind = false;
     mConnectedToCpu = false;
 }
 
@@ -145,7 +162,9 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
     ALOGV("SurfaceTextureClient::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
     int buf = -1;
-    status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,
+    int reqW = mReqWidth ? mReqWidth : mUserWidth;
+    int reqH = mReqHeight ? mReqHeight : mUserHeight;
+    status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH,
             mReqFormat, mReqUsage);
     if (result < 0) {
         ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
@@ -153,7 +172,7 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
              result);
         return result;
     }
-    sp<GraphicBuffer>& gbuf(mSlots[buf]);
+    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
     if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
         freeAllBuffers();
     }
@@ -186,24 +205,8 @@ int SurfaceTextureClient::getSlotFromBufferLocked(
         android_native_buffer_t* buffer) const {
     bool dumpedState = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        // XXX: Dump the slots whenever we hit a NULL entry while searching for
-        // a buffer.
-        if (mSlots[i] == NULL) {
-            if (!dumpedState) {
-                ALOGD("getSlotFromBufferLocked: encountered NULL buffer in slot %d "
-                        "looking for buffer %p", i, buffer->handle);
-                for (int j = 0; j < NUM_BUFFER_SLOTS; j++) {
-                    if (mSlots[j] == NULL) {
-                        ALOGD("getSlotFromBufferLocked:   %02d: NULL", j);
-                    } else {
-                        ALOGD("getSlotFromBufferLocked:   %02d: %p", j, mSlots[j]->handle);
-                    }
-                }
-                dumpedState = true;
-            }
-        }
-
-        if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) {
+        if (mSlots[i].buffer != NULL &&
+                mSlots[i].buffer->handle == buffer->handle) {
             return i;
         }
     }
@@ -233,11 +236,24 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
     if (i < 0) {
         return i;
     }
-    status_t err = mSurfaceTexture->queueBuffer(i, timestamp,
-            &mDefaultWidth, &mDefaultHeight, &mTransformHint);
+
+    // Make sure the crop rectangle is entirely inside the buffer.
+    Rect crop;
+    mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
+
+    ISurfaceTexture::QueueBufferOutput output;
+    ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
+            mTransform);
+    status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
+    uint32_t numPendingBuffers = 0;
+    output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+            &numPendingBuffers);
+
+    mConsumerRunningBehind = (numPendingBuffers >= 2);
+
     return err;
 }
 
@@ -253,29 +269,40 @@ int SurfaceTextureClient::query(int what, int* value) const {
                     return NO_ERROR;
                 }
                 break;
-            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-                {
-                    sp<ISurfaceComposer> composer(
-                            ComposerService::getComposerService());
-                    if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
-                        *value = 1;
-                    } else {
-                        *value = 0;
-                    }
+            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
+                sp<ISurfaceComposer> composer(
+                        ComposerService::getComposerService());
+                if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
+                    *value = 1;
+                } else {
+                    *value = 0;
                 }
                 return NO_ERROR;
+            }
             case NATIVE_WINDOW_CONCRETE_TYPE:
                 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_WIDTH:
-                *value = mDefaultWidth;
+                *value = mUserWidth ? mUserWidth : mDefaultWidth;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_HEIGHT:
-                *value = mDefaultHeight;
+                *value = mUserHeight ? mUserHeight : mDefaultHeight;
                 return NO_ERROR;
             case NATIVE_WINDOW_TRANSFORM_HINT:
                 *value = mTransformHint;
                 return NO_ERROR;
+            case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
+                status_t err = NO_ERROR;
+                if (!mConsumerRunningBehind) {
+                    *value = 0;
+                } else {
+                    err = mSurfaceTexture->query(what, value);
+                    if (err == NO_ERROR) {
+                        mConsumerRunningBehind = *value;
+                    }
+                }
+                return err;
+            }
         }
     }
     return mSurfaceTexture->query(what, value);
@@ -312,6 +339,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
     case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
         res = dispatchSetBuffersDimensions(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
+        res = dispatchSetBuffersUserDimensions(args);
+        break;
     case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
         res = dispatchSetBuffersFormat(args);
         break;
@@ -379,6 +409,12 @@ int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) {
     return setBuffersDimensions(w, h);
 }
 
+int SurfaceTextureClient::dispatchSetBuffersUserDimensions(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    return setBuffersUserDimensions(w, h);
+}
+
 int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
     int f = va_arg(args, int);
     return setBuffersFormat(f);
@@ -414,8 +450,14 @@ int SurfaceTextureClient::connect(int api) {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::connect");
     Mutex::Autolock lock(mMutex);
-    int err = mSurfaceTexture->connect(api,
-            &mDefaultWidth, &mDefaultHeight, &mTransformHint);
+    ISurfaceTexture::QueueBufferOutput output;
+    int err = mSurfaceTexture->connect(api, &output);
+    if (err == NO_ERROR) {
+        uint32_t numPendingBuffers = 0;
+        output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+                &numPendingBuffers);
+        mConsumerRunningBehind = (numPendingBuffers >= 2);
+    }
     if (!err && api == NATIVE_WINDOW_API_CPU) {
         mConnectedToCpu = true;
     }
@@ -433,6 +475,9 @@ int SurfaceTextureClient::disconnect(int api) {
         mReqWidth = 0;
         mReqHeight = 0;
         mReqUsage = 0;
+        mCrop.clear();
+        mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+        mTransform = 0;
         if (api == NATIVE_WINDOW_API_CPU) {
             mConnectedToCpu = false;
         }
@@ -451,20 +496,20 @@ int SurfaceTextureClient::setUsage(uint32_t reqUsage)
 int SurfaceTextureClient::setCrop(Rect const* rect)
 {
     ATRACE_CALL();
-    ALOGV("SurfaceTextureClient::setCrop");
-    Mutex::Autolock lock(mMutex);
 
     Rect realRect;
     if (rect == NULL || rect->isEmpty()) {
-        realRect = Rect(0, 0);
+        realRect.clear();
     } else {
         realRect = *rect;
     }
 
-    status_t err = mSurfaceTexture->setCrop(*rect);
-    ALOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
+    ALOGV("SurfaceTextureClient::setCrop rect=[%d %d %d %d]",
+            realRect.left, realRect.top, realRect.right, realRect.bottom);
 
-    return err;
+    Mutex::Autolock lock(mMutex);
+    mCrop = realRect;
+    return NO_ERROR;
 }
 
 int SurfaceTextureClient::setBufferCount(int bufferCount)
@@ -488,7 +533,6 @@ int SurfaceTextureClient::setBuffersDimensions(int w, int h)
 {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::setBuffersDimensions");
-    Mutex::Autolock lock(mMutex);
 
     if (w<0 || h<0)
         return BAD_VALUE;
@@ -496,25 +540,38 @@ int SurfaceTextureClient::setBuffersDimensions(int w, int h)
     if ((w && !h) || (!w && h))
         return BAD_VALUE;
 
+    Mutex::Autolock lock(mMutex);
     mReqWidth = w;
     mReqHeight = h;
+    return NO_ERROR;
+}
 
-    status_t err = mSurfaceTexture->setCrop(Rect(0, 0));
-    ALOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
+int SurfaceTextureClient::setBuffersUserDimensions(int w, int h)
+{
+    ATRACE_CALL();
+    ALOGV("SurfaceTextureClient::setBuffersUserDimensions");
 
-    return err;
+    if (w<0 || h<0)
+        return BAD_VALUE;
+
+    if ((w && !h) || (!w && h))
+        return BAD_VALUE;
+
+    Mutex::Autolock lock(mMutex);
+    mUserWidth = w;
+    mUserHeight = h;
+    return NO_ERROR;
 }
 
 int SurfaceTextureClient::setBuffersFormat(int format)
 {
     ALOGV("SurfaceTextureClient::setBuffersFormat");
-    Mutex::Autolock lock(mMutex);
 
     if (format<0)
         return BAD_VALUE;
 
+    Mutex::Autolock lock(mMutex);
     mReqFormat = format;
-
     return NO_ERROR;
 }
 
@@ -522,13 +579,20 @@ int SurfaceTextureClient::setScalingMode(int mode)
 {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::setScalingMode(%d)", mode);
-    Mutex::Autolock lock(mMutex);
-    // mode is validated on the server
-    status_t err = mSurfaceTexture->setScalingMode(mode);
-    ALOGE_IF(err, "ISurfaceTexture::setScalingMode(%d) returned %s",
-            mode, strerror(-err));
 
-    return err;
+    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);
+            return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    mScalingMode = mode;
+    return NO_ERROR;
 }
 
 int SurfaceTextureClient::setBuffersTransform(int transform)
@@ -536,8 +600,8 @@ int SurfaceTextureClient::setBuffersTransform(int transform)
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::setBuffersTransform");
     Mutex::Autolock lock(mMutex);
-    status_t err = mSurfaceTexture->setTransform(transform);
-    return err;
+    mTransform = transform;
+    return NO_ERROR;
 }
 
 int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
@@ -550,7 +614,7 @@ int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
 
 void SurfaceTextureClient::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        mSlots[i] = 0;
+        mSlots[i].buffer = 0;
     }
 }
 
@@ -655,19 +719,32 @@ status_t SurfaceTextureClient::lock(
 
             if (canCopyBack) {
                 // copy the area that is invalid and not repainted this round
-                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+                const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
                 if (!copyback.isEmpty())
                     copyBlt(backBuffer, frontBuffer, copyback);
             } else {
                 // if we can't copy-back anything, modify the user's dirty
                 // region to make sure they redraw the whole buffer
                 newDirtyRegion.set(bounds);
+                mDirtyRegion.clear();
+                Mutex::Autolock lock(mMutex);
+                for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+                    mSlots[i].dirtyRegion.clear();
+                }
             }
 
-            // keep track of the are of the buffer that is "clean"
-            // (ie: that will be redrawn)
-            mOldDirtyRegion = newDirtyRegion;
 
+            { // scope for the lock
+                Mutex::Autolock lock(mMutex);
+                int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
+                if (backBufferSlot >= 0) {
+                    Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
+                    mDirtyRegion.subtract(dirtyRegion);
+                    dirtyRegion = newDirtyRegion;
+                }
+            }
+
+            mDirtyRegion.orSelf(newDirtyRegion);
             if (inOutDirtyBounds) {
                 *inOutDirtyBounds = newDirtyRegion.getBounds();
             }