widget/gonk/nativewindow/GonkBufferQueueKK.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1269 @@
     1.4 +/*
     1.5 + * Copyright (C) 2012 The Android Open Source Project
     1.6 + * Copyright (C) 2013 Mozilla Foundation
     1.7 + *
     1.8 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.9 + * you may not use this file except in compliance with the License.
    1.10 + * You may obtain a copy of the License at
    1.11 + *
    1.12 + *      http://www.apache.org/licenses/LICENSE-2.0
    1.13 + *
    1.14 + * Unless required by applicable law or agreed to in writing, software
    1.15 + * distributed under the License is distributed on an "AS IS" BASIS,
    1.16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1.17 + * See the License for the specific language governing permissions and
    1.18 + * limitations under the License.
    1.19 + */
    1.20 +
    1.21 +#define LOG_TAG "GonkBufferQueue"
    1.22 +#define ATRACE_TAG ATRACE_TAG_GRAPHICS
    1.23 +#define LOG_NDEBUG 0
    1.24 +
    1.25 +#define GL_GLEXT_PROTOTYPES
    1.26 +#define EGL_EGLEXT_PROTOTYPES
    1.27 +
    1.28 +#include <utils/Log.h>
    1.29 +#include <utils/Trace.h>
    1.30 +#include <utils/CallStack.h>
    1.31 +#include <cutils/compiler.h>
    1.32 +
    1.33 +#include "mozilla/layers/GrallocTextureClient.h"
    1.34 +#include "mozilla/layers/ImageBridgeChild.h"
    1.35 +#include "GonkBufferQueueKK.h"
    1.36 +
    1.37 +// Macros for including the GonkBufferQueue name in log messages
    1.38 +#define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
    1.39 +#define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    1.40 +#define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    1.41 +#define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
    1.42 +#define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
    1.43 +
    1.44 +#define ATRACE_BUFFER_INDEX(index)
    1.45 +
    1.46 +using namespace mozilla;
    1.47 +using namespace mozilla::gfx;
    1.48 +using namespace mozilla::layers;
    1.49 +
    1.50 +namespace android {
    1.51 +
    1.52 +// Get an ID that's unique within this process.
    1.53 +static int32_t createProcessUniqueId() {
    1.54 +    static volatile int32_t globalCounter = 0;
    1.55 +    return android_atomic_inc(&globalCounter);
    1.56 +}
    1.57 +
    1.58 +static const char* scalingModeName(int scalingMode) {
    1.59 +    switch (scalingMode) {
    1.60 +        case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
    1.61 +        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
    1.62 +        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
    1.63 +        default: return "Unknown";
    1.64 +    }
    1.65 +}
    1.66 +
    1.67 +class nsProxyReleaseTask : public Task
    1.68 +{
    1.69 +public:
    1.70 +    nsProxyReleaseTask(TextureClient* aClient)
    1.71 +        : mTextureClient(aClient) {
    1.72 +    }
    1.73 +
    1.74 +    virtual void Run() MOZ_OVERRIDE
    1.75 +    {
    1.76 +        mTextureClient = nullptr;
    1.77 +    }
    1.78 +
    1.79 +private:
    1.80 +    mozilla::RefPtr<TextureClient> mTextureClient;
    1.81 +};
    1.82 +
    1.83 +GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
    1.84 +        const sp<IGraphicBufferAlloc>& allocator) :
    1.85 +    mDefaultWidth(1),
    1.86 +    mDefaultHeight(1),
    1.87 +    mMaxAcquiredBufferCount(1),
    1.88 +    mDefaultMaxBufferCount(2),
    1.89 +    mOverrideMaxBufferCount(0),
    1.90 +//    mSynchronousMode(true), // GonkBufferQueue always works in sync mode.
    1.91 +    mConsumerControlledByApp(false),
    1.92 +    mDequeueBufferCannotBlock(false),
    1.93 +    mUseAsyncBuffer(true),
    1.94 +    mConnectedApi(NO_CONNECTED_API),
    1.95 +    mAbandoned(false),
    1.96 +    mFrameCounter(0),
    1.97 +    mBufferHasBeenQueued(false),
    1.98 +    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
    1.99 +    mConsumerUsageBits(0),
   1.100 +    mTransformHint(0)
   1.101 +{
   1.102 +    // Choose a name using the PID and a process-unique ID.
   1.103 +    mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
   1.104 +
   1.105 +    ST_LOGV("GonkBufferQueue");
   1.106 +}
   1.107 +
   1.108 +GonkBufferQueue::~GonkBufferQueue() {
   1.109 +    ST_LOGV("~GonkBufferQueue");
   1.110 +}
   1.111 +
   1.112 +status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
   1.113 +    if (count < 2 || count > NUM_BUFFER_SLOTS)
   1.114 +        return BAD_VALUE;
   1.115 +
   1.116 +    mDefaultMaxBufferCount = count;
   1.117 +    mDequeueCondition.broadcast();
   1.118 +
   1.119 +    return NO_ERROR;
   1.120 +}
   1.121 +
   1.122 +void GonkBufferQueue::setConsumerName(const String8& name) {
   1.123 +    Mutex::Autolock lock(mMutex);
   1.124 +    mConsumerName = name;
   1.125 +}
   1.126 +
   1.127 +status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
   1.128 +    Mutex::Autolock lock(mMutex);
   1.129 +    mDefaultBufferFormat = defaultFormat;
   1.130 +    return NO_ERROR;
   1.131 +}
   1.132 +
   1.133 +status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
   1.134 +    Mutex::Autolock lock(mMutex);
   1.135 +    mConsumerUsageBits = usage;
   1.136 +    return NO_ERROR;
   1.137 +}
   1.138 +
   1.139 +status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
   1.140 +    ST_LOGV("setTransformHint: %02x", hint);
   1.141 +    Mutex::Autolock lock(mMutex);
   1.142 +    mTransformHint = hint;
   1.143 +    return NO_ERROR;
   1.144 +}
   1.145 +
   1.146 +TemporaryRef<TextureClient>
   1.147 +GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
   1.148 +{
   1.149 +    Mutex::Autolock _l(mMutex);
   1.150 +    if (buffer == NULL) {
   1.151 +        ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
   1.152 +        return nullptr;
   1.153 +    }
   1.154 +
   1.155 +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   1.156 +        if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
   1.157 +            return mSlots[i].mTextureClient;
   1.158 +        }
   1.159 +    }
   1.160 +    ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
   1.161 +    return nullptr;
   1.162 +}
   1.163 +
   1.164 +int GonkBufferQueue::getSlotFromTextureClientLocked(
   1.165 +        TextureClient* client) const
   1.166 +{
   1.167 +    if (client == NULL) {
   1.168 +        ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
   1.169 +        return BAD_VALUE;
   1.170 +    }
   1.171 +
   1.172 +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   1.173 +        if (mSlots[i].mTextureClient == client) {
   1.174 +            return i;
   1.175 +        }
   1.176 +    }
   1.177 +    ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
   1.178 +    return BAD_VALUE;
   1.179 +}
   1.180 +
   1.181 +status_t GonkBufferQueue::setBufferCount(int bufferCount) {
   1.182 +    ST_LOGV("setBufferCount: count=%d", bufferCount);
   1.183 +
   1.184 +    sp<IConsumerListener> listener;
   1.185 +    {
   1.186 +        Mutex::Autolock lock(mMutex);
   1.187 +
   1.188 +        if (mAbandoned) {
   1.189 +            ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!");
   1.190 +            return NO_INIT;
   1.191 +        }
   1.192 +        if (bufferCount > NUM_BUFFER_SLOTS) {
   1.193 +            ST_LOGE("setBufferCount: bufferCount too large (max %d)",
   1.194 +                    NUM_BUFFER_SLOTS);
   1.195 +            return BAD_VALUE;
   1.196 +        }
   1.197 +
   1.198 +        // Error out if the user has dequeued buffers
   1.199 +        for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
   1.200 +            if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
   1.201 +                ST_LOGE("setBufferCount: client owns some buffers");
   1.202 +                return -EINVAL;
   1.203 +            }
   1.204 +        }
   1.205 +
   1.206 +        if (bufferCount == 0) {
   1.207 +            mOverrideMaxBufferCount = 0;
   1.208 +            mDequeueCondition.broadcast();
   1.209 +            return NO_ERROR;
   1.210 +        }
   1.211 +
   1.212 +        // fine to assume async to false before we're setting the buffer count
   1.213 +        const int minBufferSlots = getMinMaxBufferCountLocked(false);
   1.214 +        if (bufferCount < minBufferSlots) {
   1.215 +            ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
   1.216 +                    "minimum (%d)", bufferCount, minBufferSlots);
   1.217 +            return BAD_VALUE;
   1.218 +        }
   1.219 +
   1.220 +        // here we're guaranteed that the client doesn't have dequeued buffers
   1.221 +        // and will release all of its buffer references.  We don't clear the
   1.222 +        // queue, however, so currently queued buffers still get displayed.
   1.223 +        // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
   1.224 +        freeAllBuffersLocked();
   1.225 +        mOverrideMaxBufferCount = bufferCount;
   1.226 +        mDequeueCondition.broadcast();
   1.227 +        listener = mConsumerListener;
   1.228 +    } // scope for lock
   1.229 +
   1.230 +    if (listener != NULL) {
   1.231 +        listener->onBuffersReleased();
   1.232 +    }
   1.233 +
   1.234 +    return NO_ERROR;
   1.235 +}
   1.236 +
   1.237 +int GonkBufferQueue::query(int what, int* outValue)
   1.238 +{
   1.239 +    ATRACE_CALL();
   1.240 +    Mutex::Autolock lock(mMutex);
   1.241 +
   1.242 +    if (mAbandoned) {
   1.243 +        ST_LOGE("query: GonkBufferQueue has been abandoned!");
   1.244 +        return NO_INIT;
   1.245 +    }
   1.246 +
   1.247 +    int value;
   1.248 +    switch (what) {
   1.249 +    case NATIVE_WINDOW_WIDTH:
   1.250 +        value = mDefaultWidth;
   1.251 +        break;
   1.252 +    case NATIVE_WINDOW_HEIGHT:
   1.253 +        value = mDefaultHeight;
   1.254 +        break;
   1.255 +    case NATIVE_WINDOW_FORMAT:
   1.256 +        value = mDefaultBufferFormat;
   1.257 +        break;
   1.258 +    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
   1.259 +        value = getMinUndequeuedBufferCount(false);
   1.260 +        break;
   1.261 +    case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
   1.262 +        value = (mQueue.size() >= 2);
   1.263 +        break;
   1.264 +    case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
   1.265 +        value = mConsumerUsageBits;
   1.266 +        break;
   1.267 +    default:
   1.268 +        return BAD_VALUE;
   1.269 +    }
   1.270 +    outValue[0] = value;
   1.271 +    return NO_ERROR;
   1.272 +}
   1.273 +
   1.274 +status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
   1.275 +    ATRACE_CALL();
   1.276 +    ST_LOGV("requestBuffer: slot=%d", slot);
   1.277 +    Mutex::Autolock lock(mMutex);
   1.278 +    if (mAbandoned) {
   1.279 +        ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!");
   1.280 +        return NO_INIT;
   1.281 +    }
   1.282 +    if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
   1.283 +        ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
   1.284 +                NUM_BUFFER_SLOTS, slot);
   1.285 +        return BAD_VALUE;
   1.286 +    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
   1.287 +        ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
   1.288 +                slot, mSlots[slot].mBufferState);
   1.289 +        return BAD_VALUE;
   1.290 +    }
   1.291 +    mSlots[slot].mRequestBufferCalled = true;
   1.292 +    *buf = mSlots[slot].mGraphicBuffer;
   1.293 +    return NO_ERROR;
   1.294 +}
   1.295 +
   1.296 +status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
   1.297 +            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
   1.298 +    ATRACE_CALL();
   1.299 +    ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
   1.300 +
   1.301 +    if ((w && !h) || (!w && h)) {
   1.302 +        ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
   1.303 +        return BAD_VALUE;
   1.304 +    }
   1.305 +
   1.306 +    status_t returnFlags(OK);
   1.307 +    int buf = INVALID_BUFFER_SLOT;
   1.308 +
   1.309 +    { // Scope for the lock
   1.310 +        Mutex::Autolock lock(mMutex);
   1.311 +
   1.312 +        if (format == 0) {
   1.313 +            format = mDefaultBufferFormat;
   1.314 +        }
   1.315 +        // turn on usage bits the consumer requested
   1.316 +        usage |= mConsumerUsageBits;
   1.317 +
   1.318 +        int found = -1;
   1.319 +        bool tryAgain = true;
   1.320 +        while (tryAgain) {
   1.321 +            if (mAbandoned) {
   1.322 +                ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
   1.323 +                return NO_INIT;
   1.324 +            }
   1.325 +
   1.326 +            const int maxBufferCount = getMaxBufferCountLocked(async);
   1.327 +            if (async && mOverrideMaxBufferCount) {
   1.328 +                // FIXME: some drivers are manually setting the buffer-count (which they
   1.329 +                // shouldn't), so we do this extra test here to handle that case.
   1.330 +                // This is TEMPORARY, until we get this fixed.
   1.331 +                if (mOverrideMaxBufferCount < maxBufferCount) {
   1.332 +                    ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
   1.333 +                    return BAD_VALUE;
   1.334 +                }
   1.335 +            }
   1.336 +
   1.337 +            // Free up any buffers that are in slots beyond the max buffer
   1.338 +            // count.
   1.339 +            //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
   1.340 +            //    assert(mSlots[i].mBufferState == BufferSlot::FREE);
   1.341 +            //    if (mSlots[i].mGraphicBuffer != NULL) {
   1.342 +            //        freeBufferLocked(i);
   1.343 +            //        returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
   1.344 +            //    }
   1.345 +            //}
   1.346 +
   1.347 +            // look for a free buffer to give to the client
   1.348 +            found = INVALID_BUFFER_SLOT;
   1.349 +            int dequeuedCount = 0;
   1.350 +            int acquiredCount = 0;
   1.351 +            for (int i = 0; i < maxBufferCount; i++) {
   1.352 +                const int state = mSlots[i].mBufferState;
   1.353 +                switch (state) {
   1.354 +                    case BufferSlot::DEQUEUED:
   1.355 +                    dequeuedCount++;
   1.356 +                        break;
   1.357 +                    case BufferSlot::ACQUIRED:
   1.358 +                        acquiredCount++;
   1.359 +                        break;
   1.360 +                    case BufferSlot::FREE:
   1.361 +                    /* We return the oldest of the free buffers to avoid
   1.362 +                     * stalling the producer if possible.  This is because
   1.363 +                     * the consumer may still have pending reads of the
   1.364 +                     * buffers in flight.
   1.365 +                     */
   1.366 +                    if ((found < 0) ||
   1.367 +                            mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
   1.368 +                        found = i;
   1.369 +                    }
   1.370 +                        break;
   1.371 +                }
   1.372 +            }
   1.373 +
   1.374 +            // clients are not allowed to dequeue more than one buffer
   1.375 +            // if they didn't set a buffer count.
   1.376 +            if (!mOverrideMaxBufferCount && dequeuedCount) {
   1.377 +                ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
   1.378 +                        "setting the buffer count");
   1.379 +                return -EINVAL;
   1.380 +            }
   1.381 +
   1.382 +            // See whether a buffer has been queued since the last
   1.383 +            // setBufferCount so we know whether to perform the min undequeued
   1.384 +            // buffers check below.
   1.385 +            if (mBufferHasBeenQueued) {
   1.386 +                // make sure the client is not trying to dequeue more buffers
   1.387 +                // than allowed.
   1.388 +                const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
   1.389 +                const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
   1.390 +                if (newUndequeuedCount < minUndequeuedCount) {
   1.391 +                    ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
   1.392 +                            "exceeded (dequeued=%d undequeudCount=%d)",
   1.393 +                            minUndequeuedCount, dequeuedCount,
   1.394 +                            newUndequeuedCount);
   1.395 +                    return -EBUSY;
   1.396 +                }
   1.397 +            }
   1.398 +
   1.399 +            // If no buffer is found, wait for a buffer to be released or for
   1.400 +            // the max buffer count to change.
   1.401 +            tryAgain = found == INVALID_BUFFER_SLOT;
   1.402 +            if (tryAgain) {
   1.403 +                // return an error if we're in "cannot block" mode (producer and consumer
   1.404 +                // are controlled by the application) -- however, the consumer is allowed
   1.405 +                // to acquire briefly an extra buffer (which could cause us to have to wait here)
   1.406 +                // and that's okay because we know the wait will be brief (it happens
   1.407 +                // if we dequeue a buffer while the consumer has acquired one but not released
   1.408 +                // the old one yet -- for e.g.: see GLConsumer::updateTexImage()).
   1.409 +                if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) {
   1.410 +                    ST_LOGE("dequeueBuffer: would block! returning an error instead.");
   1.411 +                    return WOULD_BLOCK;
   1.412 +                }
   1.413 +                mDequeueCondition.wait(mMutex);
   1.414 +            }
   1.415 +        }
   1.416 +
   1.417 +
   1.418 +        if (found == INVALID_BUFFER_SLOT) {
   1.419 +            // This should not happen.
   1.420 +            ST_LOGE("dequeueBuffer: no available buffer slots");
   1.421 +            return -EBUSY;
   1.422 +        }
   1.423 +
   1.424 +        buf = found;
   1.425 +        *outBuf = found;
   1.426 +
   1.427 +        const bool useDefaultSize = !w && !h;
   1.428 +        if (useDefaultSize) {
   1.429 +            // use the default size
   1.430 +            w = mDefaultWidth;
   1.431 +            h = mDefaultHeight;
   1.432 +        }
   1.433 +
   1.434 +        mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
   1.435 +
   1.436 +        const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
   1.437 +        if ((buffer == NULL) ||
   1.438 +            (uint32_t(buffer->width)  != w) ||
   1.439 +            (uint32_t(buffer->height) != h) ||
   1.440 +            (uint32_t(buffer->format) != format) ||
   1.441 +            ((uint32_t(buffer->usage) & usage) != usage))
   1.442 +        {
   1.443 +            mSlots[buf].mAcquireCalled = false;
   1.444 +            mSlots[buf].mGraphicBuffer = NULL;
   1.445 +            mSlots[buf].mRequestBufferCalled = false;
   1.446 +            mSlots[buf].mFence = Fence::NO_FENCE;
   1.447 +            if (mSlots[buf].mTextureClient) {
   1.448 +              mSlots[buf].mTextureClient->ClearRecycleCallback();
   1.449 +              // release TextureClient in ImageBridge thread
   1.450 +              nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[buf].mTextureClient);
   1.451 +              mSlots[buf].mTextureClient = NULL;
   1.452 +              ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
   1.453 +            }
   1.454 +            returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
   1.455 +        }
   1.456 +
   1.457 +
   1.458 +        if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {
   1.459 +            ST_LOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
   1.460 +                    "buf=%d, w=%d, h=%d, format=%d",
   1.461 +                    buf, buffer->width, buffer->height, buffer->format);
   1.462 +        }
   1.463 +        *outFence = mSlots[buf].mFence;
   1.464 +        mSlots[buf].mFence = Fence::NO_FENCE;
   1.465 +    }  // end lock scope
   1.466 +
   1.467 +    sp<GraphicBuffer> graphicBuffer;
   1.468 +    if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
   1.469 +        RefPtr<GrallocTextureClientOGL> textureClient =
   1.470 +            new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
   1.471 +                                        gfx::SurfaceFormat::UNKNOWN,
   1.472 +                                        gfx::BackendType::NONE,
   1.473 +                                        TEXTURE_DEALLOCATE_CLIENT);
   1.474 +        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
   1.475 +        bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
   1.476 +        sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
   1.477 +        if (!result || !graphicBuffer.get()) {
   1.478 +            ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
   1.479 +            return -ENOMEM;
   1.480 +        }
   1.481 +
   1.482 +        { // Scope for the lock
   1.483 +            Mutex::Autolock lock(mMutex);
   1.484 +
   1.485 +            if (mAbandoned) {
   1.486 +                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
   1.487 +                return NO_INIT;
   1.488 +            }
   1.489 +
   1.490 +            mSlots[buf].mGraphicBuffer = graphicBuffer;
   1.491 +            mSlots[buf].mTextureClient = textureClient;
   1.492 +            ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
   1.493 +                    mSlots[buf].mGraphicBuffer->handle);
   1.494 +
   1.495 +        }
   1.496 +
   1.497 +    }
   1.498 +
   1.499 +    ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
   1.500 +            mSlots[*outBuf].mFrameNumber,
   1.501 +            mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
   1.502 +
   1.503 +    return returnFlags;
   1.504 +}
   1.505 +
   1.506 +status_t GonkBufferQueue::queueBuffer(int buf,
   1.507 +        const QueueBufferInput& input, QueueBufferOutput* output) {
   1.508 +    ATRACE_CALL();
   1.509 +
   1.510 +    Rect crop;
   1.511 +    uint32_t transform;
   1.512 +    int scalingMode;
   1.513 +    int64_t timestamp;
   1.514 +    bool isAutoTimestamp;
   1.515 +    bool async;
   1.516 +    sp<Fence> fence;
   1.517 +
   1.518 +    input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
   1.519 +             &async, &fence);
   1.520 +
   1.521 +    if (fence == NULL) {
   1.522 +        ST_LOGE("queueBuffer: fence is NULL");
   1.523 +        return BAD_VALUE;
   1.524 +    }
   1.525 +
   1.526 +    ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
   1.527 +            "scale=%s",
   1.528 +            buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
   1.529 +            transform, scalingModeName(scalingMode));
   1.530 +
   1.531 +    switch (scalingMode) {
   1.532 +        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
   1.533 +        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
   1.534 +        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
   1.535 +        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
   1.536 +            break;
   1.537 +        default:
   1.538 +            ST_LOGE("unknown scaling mode: %d", scalingMode);
   1.539 +            return -EINVAL;
   1.540 +    }
   1.541 +
   1.542 +    sp<IConsumerListener> listener;
   1.543 +
   1.544 +    { // scope for the lock
   1.545 +        Mutex::Autolock lock(mMutex);
   1.546 +
   1.547 +        if (mAbandoned) {
   1.548 +            ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!");
   1.549 +            return NO_INIT;
   1.550 +        }
   1.551 +
   1.552 +        const int maxBufferCount = getMaxBufferCountLocked(async);
   1.553 +        if (async && mOverrideMaxBufferCount) {
   1.554 +            // FIXME: some drivers are manually setting the buffer-count (which they
   1.555 +            // shouldn't), so we do this extra test here to handle that case.
   1.556 +            // This is TEMPORARY, until we get this fixed.
   1.557 +            if (mOverrideMaxBufferCount < maxBufferCount) {
   1.558 +                ST_LOGE("queueBuffer: async mode is invalid with buffercount override");
   1.559 +                return BAD_VALUE;
   1.560 +            }
   1.561 +        }
   1.562 +        if (buf < 0 || buf >= maxBufferCount) {
   1.563 +            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
   1.564 +                    maxBufferCount, buf);
   1.565 +            return -EINVAL;
   1.566 +        } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
   1.567 +            ST_LOGE("queueBuffer: slot %d is not owned by the client "
   1.568 +                    "(state=%d)", buf, mSlots[buf].mBufferState);
   1.569 +            return -EINVAL;
   1.570 +        } else if (!mSlots[buf].mRequestBufferCalled) {
   1.571 +            ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
   1.572 +                    "buffer", buf);
   1.573 +            return -EINVAL;
   1.574 +        }
   1.575 +
   1.576 +        ST_LOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] "
   1.577 +                "tr=%#x scale=%s",
   1.578 +                buf, mFrameCounter + 1, timestamp,
   1.579 +                crop.left, crop.top, crop.right, crop.bottom,
   1.580 +                transform, scalingModeName(scalingMode));
   1.581 +
   1.582 +        const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
   1.583 +        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
   1.584 +        Rect croppedCrop;
   1.585 +        crop.intersect(bufferRect, &croppedCrop);
   1.586 +        if (croppedCrop != crop) {
   1.587 +            ST_LOGE("queueBuffer: crop rect is not contained within the "
   1.588 +                    "buffer in slot %d", buf);
   1.589 +            return -EINVAL;
   1.590 +        }
   1.591 +
   1.592 +        mSlots[buf].mFence = fence;
   1.593 +        mSlots[buf].mBufferState = BufferSlot::QUEUED;
   1.594 +        mFrameCounter++;
   1.595 +        mSlots[buf].mFrameNumber = mFrameCounter;
   1.596 +
   1.597 +        BufferItem item;
   1.598 +        item.mAcquireCalled = mSlots[buf].mAcquireCalled;
   1.599 +        item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
   1.600 +        item.mCrop = crop;
   1.601 +        item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
   1.602 +        item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
   1.603 +        item.mScalingMode = scalingMode;
   1.604 +        item.mTimestamp = timestamp;
   1.605 +        item.mIsAutoTimestamp = isAutoTimestamp;
   1.606 +        item.mFrameNumber = mFrameCounter;
   1.607 +        item.mBuf = buf;
   1.608 +        item.mFence = fence;
   1.609 +        item.mIsDroppable = mDequeueBufferCannotBlock || async;
   1.610 +
   1.611 +        if (mQueue.empty()) {
   1.612 +            // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
   1.613 +            // simply queue this buffer.
   1.614 +            mQueue.push_back(item);
   1.615 +            listener = mConsumerListener;
   1.616 +        } else {
   1.617 +            // when the queue is not empty, we need to look at the front buffer
   1.618 +            // state and see if we need to replace it.
   1.619 +            Fifo::iterator front(mQueue.begin());
   1.620 +            if (front->mIsDroppable) {
   1.621 +                // buffer slot currently queued is marked free if still tracked
   1.622 +                if (stillTracking(front)) {
   1.623 +                    mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
   1.624 +                    // reset the frame number of the freed buffer so that it is the first in
   1.625 +                    // line to be dequeued again.
   1.626 +                    mSlots[front->mBuf].mFrameNumber = 0;
   1.627 +                }
   1.628 +                // and we record the new buffer in the queued list
   1.629 +                *front = item;
   1.630 +            } else {
   1.631 +                mQueue.push_back(item);
   1.632 +                listener = mConsumerListener;
   1.633 +            }
   1.634 +        }
   1.635 +
   1.636 +        mBufferHasBeenQueued = true;
   1.637 +        mDequeueCondition.broadcast();
   1.638 +
   1.639 +        output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
   1.640 +                mQueue.size());
   1.641 +
   1.642 +    } // scope for the lock
   1.643 +
   1.644 +    // call back without lock held
   1.645 +    if (listener != 0) {
   1.646 +        listener->onFrameAvailable();
   1.647 +    }
   1.648 +    return NO_ERROR;
   1.649 +}
   1.650 +
   1.651 +void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
   1.652 +    ATRACE_CALL();
   1.653 +    ST_LOGV("cancelBuffer: slot=%d", buf);
   1.654 +    Mutex::Autolock lock(mMutex);
   1.655 +
   1.656 +    if (mAbandoned) {
   1.657 +        ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
   1.658 +        return;
   1.659 +    }
   1.660 +
   1.661 +    if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
   1.662 +        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
   1.663 +                NUM_BUFFER_SLOTS, buf);
   1.664 +        return;
   1.665 +    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
   1.666 +        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
   1.667 +                buf, mSlots[buf].mBufferState);
   1.668 +        return;
   1.669 +    } else if (fence == NULL) {
   1.670 +        ST_LOGE("cancelBuffer: fence is NULL");
   1.671 +        return;
   1.672 +    }
   1.673 +    mSlots[buf].mBufferState = BufferSlot::FREE;
   1.674 +    mSlots[buf].mFrameNumber = 0;
   1.675 +    mSlots[buf].mFence = fence;
   1.676 +    mDequeueCondition.broadcast();
   1.677 +}
   1.678 +
   1.679 +
   1.680 +status_t GonkBufferQueue::connect(const sp<IBinder>& token,
   1.681 +        int api, bool producerControlledByApp, QueueBufferOutput* output) {
   1.682 +    ATRACE_CALL();
   1.683 +    ST_LOGV("connect: api=%d producerControlledByApp=%s", api,
   1.684 +            producerControlledByApp ? "true" : "false");
   1.685 +    Mutex::Autolock lock(mMutex);
   1.686 +
   1.687 +retry:
   1.688 +    if (mAbandoned) {
   1.689 +        ST_LOGE("connect: GonkBufferQueue has been abandoned!");
   1.690 +        return NO_INIT;
   1.691 +    }
   1.692 +
   1.693 +    if (mConsumerListener == NULL) {
   1.694 +        ST_LOGE("connect: GonkBufferQueue has no consumer!");
   1.695 +        return NO_INIT;
   1.696 +    }
   1.697 +
   1.698 +    if (mConnectedApi != NO_CONNECTED_API) {
   1.699 +        ST_LOGE("connect: already connected (cur=%d, req=%d)",
   1.700 +                mConnectedApi, api);
   1.701 +        return -EINVAL;
   1.702 +    }
   1.703 +
   1.704 +    // If we disconnect and reconnect quickly, we can be in a state where our slots are
   1.705 +    // empty but we have many buffers in the queue.  This can cause us to run out of
   1.706 +    // memory if we outrun the consumer.  Wait here if it looks like we have too many
   1.707 +    // buffers queued up.
   1.708 +    int maxBufferCount = getMaxBufferCountLocked(false);    // worst-case, i.e. largest value
   1.709 +    if (mQueue.size() > (size_t) maxBufferCount) {
   1.710 +        // TODO: make this bound tighter?
   1.711 +        ST_LOGV("queue size is %d, waiting", mQueue.size());
   1.712 +        mDequeueCondition.wait(mMutex);
   1.713 +        goto retry;
   1.714 +    }
   1.715 +
   1.716 +    int err = NO_ERROR;
   1.717 +    switch (api) {
   1.718 +        case NATIVE_WINDOW_API_EGL:
   1.719 +        case NATIVE_WINDOW_API_CPU:
   1.720 +        case NATIVE_WINDOW_API_MEDIA:
   1.721 +        case NATIVE_WINDOW_API_CAMERA:
   1.722 +            mConnectedApi = api;
   1.723 +            output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
   1.724 +
   1.725 +            // set-up a death notification so that we can disconnect
   1.726 +            // automatically when/if the remote producer dies.
   1.727 +            if (token != NULL && token->remoteBinder() != NULL) {
   1.728 +                status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
   1.729 +                if (err == NO_ERROR) {
   1.730 +                    mConnectedProducerToken = token;
   1.731 +                } else {
   1.732 +                    ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
   1.733 +                }
   1.734 +            }
   1.735 +            break;
   1.736 +        default:
   1.737 +            err = -EINVAL;
   1.738 +            break;
   1.739 +    }
   1.740 +
   1.741 +    mBufferHasBeenQueued = false;
   1.742 +    mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
   1.743 +
   1.744 +    return err;
   1.745 +}
   1.746 +
   1.747 +void GonkBufferQueue::binderDied(const wp<IBinder>& who) {
   1.748 +    // If we're here, it means that a producer we were connected to died.
   1.749 +    // We're GUARANTEED that we still are connected to it because it has no other way
   1.750 +    // to get disconnected -- or -- we wouldn't be here because we're removing this
   1.751 +    // callback upon disconnect. Therefore, it's okay to read mConnectedApi without
   1.752 +    // synchronization here.
   1.753 +    int api = mConnectedApi;
   1.754 +    this->disconnect(api);
   1.755 +}
   1.756 +
   1.757 +status_t GonkBufferQueue::disconnect(int api) {
   1.758 +    ATRACE_CALL();
   1.759 +    ST_LOGV("disconnect: api=%d", api);
   1.760 +
   1.761 +    int err = NO_ERROR;
   1.762 +    sp<IConsumerListener> listener;
   1.763 +
   1.764 +    { // Scope for the lock
   1.765 +        Mutex::Autolock lock(mMutex);
   1.766 +
   1.767 +        if (mAbandoned) {
   1.768 +            // it is not really an error to disconnect after the surface
   1.769 +            // has been abandoned, it should just be a no-op.
   1.770 +            return NO_ERROR;
   1.771 +        }
   1.772 +
   1.773 +        switch (api) {
   1.774 +            case NATIVE_WINDOW_API_EGL:
   1.775 +            case NATIVE_WINDOW_API_CPU:
   1.776 +            case NATIVE_WINDOW_API_MEDIA:
   1.777 +            case NATIVE_WINDOW_API_CAMERA:
   1.778 +                if (mConnectedApi == api) {
   1.779 +                    freeAllBuffersLocked();
   1.780 +                    mConnectedApi = NO_CONNECTED_API;
   1.781 +                    mDequeueCondition.broadcast();
   1.782 +                    listener = mConsumerListener;
   1.783 +                } else {
   1.784 +                    ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
   1.785 +                            mConnectedApi, api);
   1.786 +                    err = -EINVAL;
   1.787 +                }
   1.788 +                break;
   1.789 +            default:
   1.790 +                ST_LOGE("disconnect: unknown API %d", api);
   1.791 +                err = -EINVAL;
   1.792 +                break;
   1.793 +        }
   1.794 +    }
   1.795 +
   1.796 +    if (listener != NULL) {
   1.797 +        listener->onBuffersReleased();
   1.798 +    }
   1.799 +
   1.800 +    return err;
   1.801 +}
   1.802 +
   1.803 +void GonkBufferQueue::dump(String8& result, const char* prefix) const {
   1.804 +    Mutex::Autolock _l(mMutex);
   1.805 +
   1.806 +    String8 fifo;
   1.807 +    int fifoSize = 0;
   1.808 +    Fifo::const_iterator i(mQueue.begin());
   1.809 +    while (i != mQueue.end()) {
   1.810 +        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
   1.811 +                "xform=0x%02x, time=%#llx, scale=%s\n",
   1.812 +                i->mBuf, i->mGraphicBuffer.get(),
   1.813 +                i->mCrop.left, i->mCrop.top, i->mCrop.right,
   1.814 +                i->mCrop.bottom, i->mTransform, i->mTimestamp,
   1.815 +                scalingModeName(i->mScalingMode)
   1.816 +                );
   1.817 +        i++;
   1.818 +        fifoSize++;
   1.819 +    }
   1.820 +
   1.821 +
   1.822 +    result.appendFormat(
   1.823 +            "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
   1.824 +            "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
   1.825 +            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
   1.826 +            mDefaultHeight, mDefaultBufferFormat, mTransformHint,
   1.827 +            fifoSize, fifo.string());
   1.828 +
   1.829 +    struct {
   1.830 +        const char * operator()(int state) const {
   1.831 +            switch (state) {
   1.832 +                case BufferSlot::DEQUEUED: return "DEQUEUED";
   1.833 +                case BufferSlot::QUEUED: return "QUEUED";
   1.834 +                case BufferSlot::FREE: return "FREE";
   1.835 +                case BufferSlot::ACQUIRED: return "ACQUIRED";
   1.836 +                default: return "Unknown";
   1.837 +            }
   1.838 +        }
   1.839 +    } stateName;
   1.840 +
   1.841 +    // just trim the free buffers to not spam the dump
   1.842 +    int maxBufferCount = 0;
   1.843 +    for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
   1.844 +        const BufferSlot& slot(mSlots[i]);
   1.845 +        if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
   1.846 +            maxBufferCount = i+1;
   1.847 +            break;
   1.848 +        }
   1.849 +    }
   1.850 +
   1.851 +    for (int i=0 ; i<maxBufferCount ; i++) {
   1.852 +        const BufferSlot& slot(mSlots[i]);
   1.853 +        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
   1.854 +        result.appendFormat(
   1.855 +            "%s%s[%02d:%p] state=%-8s",
   1.856 +                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
   1.857 +                stateName(slot.mBufferState)
   1.858 +        );
   1.859 +
   1.860 +        if (buf != NULL) {
   1.861 +            result.appendFormat(
   1.862 +                    ", %p [%4ux%4u:%4u,%3X]",
   1.863 +                    buf->handle, buf->width, buf->height, buf->stride,
   1.864 +                    buf->format);
   1.865 +        }
   1.866 +        result.append("\n");
   1.867 +    }
   1.868 +}
   1.869 +
   1.870 +void GonkBufferQueue::freeAllBuffersLocked()
   1.871 +{
   1.872 +    ALOGW_IF(!mQueue.isEmpty(),
   1.873 +            "freeAllBuffersLocked called but mQueue is not empty");
   1.874 +    mQueue.clear();
   1.875 +    mBufferHasBeenQueued = false;
   1.876 +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   1.877 +        mSlots[i].mGraphicBuffer = 0;
   1.878 +        if (mSlots[i].mTextureClient) {
   1.879 +          mSlots[i].mTextureClient->ClearRecycleCallback();
   1.880 +          // release TextureClient in ImageBridge thread
   1.881 +          nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[i].mTextureClient);
   1.882 +          mSlots[i].mTextureClient = NULL;
   1.883 +          ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
   1.884 +        }
   1.885 +        if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
   1.886 +            mSlots[i].mNeedsCleanupOnRelease = true;
   1.887 +        }
   1.888 +        mSlots[i].mBufferState = BufferSlot::FREE;
   1.889 +        mSlots[i].mFrameNumber = 0;
   1.890 +        mSlots[i].mAcquireCalled = false;
   1.891 +        // destroy fence as GonkBufferQueue now takes ownership
   1.892 +        mSlots[i].mFence = Fence::NO_FENCE;
   1.893 +    }
   1.894 +}
   1.895 +
   1.896 +status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) {
   1.897 +    ATRACE_CALL();
   1.898 +    Mutex::Autolock _l(mMutex);
   1.899 +
   1.900 +    // Check that the consumer doesn't currently have the maximum number of
   1.901 +    // buffers acquired.  We allow the max buffer count to be exceeded by one
   1.902 +    // buffer, so that the consumer can successfully set up the newly acquired
   1.903 +    // buffer before releasing the old one.
   1.904 +    int numAcquiredBuffers = 0;
   1.905 +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   1.906 +        if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
   1.907 +            numAcquiredBuffers++;
   1.908 +        }
   1.909 +    }
   1.910 +    if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
   1.911 +        ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
   1.912 +                numAcquiredBuffers, mMaxAcquiredBufferCount);
   1.913 +        return INVALID_OPERATION;
   1.914 +    }
   1.915 +
   1.916 +    // check if queue is empty
   1.917 +    // In asynchronous mode the list is guaranteed to be one buffer
   1.918 +    // deep, while in synchronous mode we use the oldest buffer.
   1.919 +    if (mQueue.empty()) {
   1.920 +        return NO_BUFFER_AVAILABLE;
   1.921 +    }
   1.922 +
   1.923 +    Fifo::iterator front(mQueue.begin());
   1.924 +
   1.925 +    // If expectedPresent is specified, we may not want to return a buffer yet.
   1.926 +    // If it's specified and there's more than one buffer queued, we may
   1.927 +    // want to drop a buffer.
   1.928 +    if (expectedPresent != 0) {
   1.929 +        const int MAX_REASONABLE_NSEC = 1000000000ULL;  // 1 second
   1.930 +
   1.931 +        // The "expectedPresent" argument indicates when the buffer is expected
   1.932 +        // to be presented on-screen.  If the buffer's desired-present time
   1.933 +        // is earlier (less) than expectedPresent, meaning it'll be displayed
   1.934 +        // on time or possibly late if we show it ASAP, we acquire and return
   1.935 +        // it.  If we don't want to display it until after the expectedPresent
   1.936 +        // time, we return PRESENT_LATER without acquiring it.
   1.937 +        //
   1.938 +        // To be safe, we don't defer acquisition if expectedPresent is
   1.939 +        // more than one second in the future beyond the desired present time
   1.940 +        // (i.e. we'd be holding the buffer for a long time).
   1.941 +        //
   1.942 +        // NOTE: code assumes monotonic time values from the system clock are
   1.943 +        // positive.
   1.944 +
   1.945 +        // Start by checking to see if we can drop frames.  We skip this check
   1.946 +        // if the timestamps are being auto-generated by Surface -- if the
   1.947 +        // app isn't generating timestamps explicitly, they probably don't
   1.948 +        // want frames to be discarded based on them.
   1.949 +        while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) {
   1.950 +            // If entry[1] is timely, drop entry[0] (and repeat).  We apply
   1.951 +            // an additional criteria here: we only drop the earlier buffer if
   1.952 +            // our desiredPresent falls within +/- 1 second of the expected
   1.953 +            // present.  Otherwise, bogus desiredPresent times (e.g. 0 or
   1.954 +            // a small relative timestamp), which normally mean "ignore the
   1.955 +            // timestamp and acquire immediately", would cause us to drop
   1.956 +            // frames.
   1.957 +            //
   1.958 +            // We may want to add an additional criteria: don't drop the
   1.959 +            // earlier buffer if entry[1]'s fence hasn't signaled yet.
   1.960 +            //
   1.961 +            // (Vector front is [0], back is [size()-1])
   1.962 +            const BufferItem& bi(mQueue[1]);
   1.963 +            nsecs_t desiredPresent = bi.mTimestamp;
   1.964 +            if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
   1.965 +                    desiredPresent > expectedPresent) {
   1.966 +                // This buffer is set to display in the near future, or
   1.967 +                // desiredPresent is garbage.  Either way we don't want to
   1.968 +                // drop the previous buffer just to get this on screen sooner.
   1.969 +                ST_LOGV("pts nodrop: des=%lld expect=%lld (%lld) now=%lld",
   1.970 +                        desiredPresent, expectedPresent, desiredPresent - expectedPresent,
   1.971 +                        systemTime(CLOCK_MONOTONIC));
   1.972 +                break;
   1.973 +            }
   1.974 +            ST_LOGV("pts drop: queue1des=%lld expect=%lld size=%d",
   1.975 +                    desiredPresent, expectedPresent, mQueue.size());
   1.976 +            if (stillTracking(front)) {
   1.977 +                // front buffer is still in mSlots, so mark the slot as free
   1.978 +                mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
   1.979 +            }
   1.980 +            mQueue.erase(front);
   1.981 +            front = mQueue.begin();
   1.982 +        }
   1.983 +
   1.984 +        // See if the front buffer is due.
   1.985 +        nsecs_t desiredPresent = front->mTimestamp;
   1.986 +        if (desiredPresent > expectedPresent &&
   1.987 +                desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
   1.988 +            ST_LOGV("pts defer: des=%lld expect=%lld (%lld) now=%lld",
   1.989 +                    desiredPresent, expectedPresent, desiredPresent - expectedPresent,
   1.990 +                    systemTime(CLOCK_MONOTONIC));
   1.991 +            return PRESENT_LATER;
   1.992 +        }
   1.993 +
   1.994 +        ST_LOGV("pts accept: des=%lld expect=%lld (%lld) now=%lld",
   1.995 +                desiredPresent, expectedPresent, desiredPresent - expectedPresent,
   1.996 +                systemTime(CLOCK_MONOTONIC));
   1.997 +    }
   1.998 +
   1.999 +    int buf = front->mBuf;
  1.1000 +    buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
  1.1001 +    buffer->mFrameNumber = mSlots[buf].mFrameNumber;
  1.1002 +    buffer->mBuf = buf;
  1.1003 +    buffer->mFence = mSlots[buf].mFence;
  1.1004 +    ATRACE_BUFFER_INDEX(buf);
  1.1005 +
  1.1006 +    ST_LOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
  1.1007 +            front->mBuf, front->mFrameNumber,
  1.1008 +            front->mGraphicBuffer->handle);
  1.1009 +    // if front buffer still being tracked update slot state
  1.1010 +    if (stillTracking(front)) {
  1.1011 +        mSlots[buf].mAcquireCalled = true;
  1.1012 +        mSlots[buf].mNeedsCleanupOnRelease = false;
  1.1013 +        mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
  1.1014 +        mSlots[buf].mFence = Fence::NO_FENCE;
  1.1015 +    }
  1.1016 +
  1.1017 +    // If the buffer has previously been acquired by the consumer, set
  1.1018 +    // mGraphicBuffer to NULL to avoid unnecessarily remapping this
  1.1019 +    // buffer on the consumer side.
  1.1020 +    //if (buffer->mAcquireCalled) {
  1.1021 +    //    buffer->mGraphicBuffer = NULL;
  1.1022 +    //}
  1.1023 +
  1.1024 +    mQueue.erase(front);
  1.1025 +    mDequeueCondition.broadcast();
  1.1026 +
  1.1027 +    return NO_ERROR;
  1.1028 +}
  1.1029 +
  1.1030 +status_t GonkBufferQueue::releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& fence) {
  1.1031 +    ATRACE_CALL();
  1.1032 +
  1.1033 +    if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
  1.1034 +        return BAD_VALUE;
  1.1035 +    }
  1.1036 +
  1.1037 +    Mutex::Autolock _l(mMutex);
  1.1038 +
  1.1039 +    // If the frame number has changed because buffer has been reallocated,
  1.1040 +    // we can ignore this releaseBuffer for the old buffer.
  1.1041 +    //if (frameNumber != mSlots[buf].mFrameNumber) {
  1.1042 +    //    return STALE_BUFFER_SLOT;
  1.1043 +    //}
  1.1044 +
  1.1045 +
  1.1046 +    // Internal state consistency checks:
  1.1047 +    // Make sure this buffers hasn't been queued while we were owning it (acquired)
  1.1048 +    Fifo::iterator front(mQueue.begin());
  1.1049 +    Fifo::const_iterator const end(mQueue.end());
  1.1050 +    while (front != end) {
  1.1051 +        if (front->mBuf == buf) {
  1.1052 +            LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been "
  1.1053 +                    "acquired", mConsumerName.string(), frameNumber, buf);
  1.1054 +            break; // never reached
  1.1055 +        }
  1.1056 +        front++;
  1.1057 +    }
  1.1058 +
  1.1059 +    // The buffer can now only be released if its in the acquired state
  1.1060 +    if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
  1.1061 +        mSlots[buf].mFence = fence;
  1.1062 +        mSlots[buf].mBufferState = BufferSlot::FREE;
  1.1063 +    } else if (mSlots[buf].mNeedsCleanupOnRelease) {
  1.1064 +        ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
  1.1065 +        mSlots[buf].mNeedsCleanupOnRelease = false;
  1.1066 +        return STALE_BUFFER_SLOT;
  1.1067 +    } else {
  1.1068 +        ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
  1.1069 +        return -EINVAL;
  1.1070 +    }
  1.1071 +
  1.1072 +    mDequeueCondition.broadcast();
  1.1073 +    return NO_ERROR;
  1.1074 +}
  1.1075 +
  1.1076 +status_t GonkBufferQueue::consumerConnect(const sp<IConsumerListener>& consumerListener,
  1.1077 +        bool controlledByApp) {
  1.1078 +    ST_LOGV("consumerConnect controlledByApp=%s",
  1.1079 +            controlledByApp ? "true" : "false");
  1.1080 +    Mutex::Autolock lock(mMutex);
  1.1081 +
  1.1082 +    if (mAbandoned) {
  1.1083 +        ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!");
  1.1084 +        return NO_INIT;
  1.1085 +    }
  1.1086 +    if (consumerListener == NULL) {
  1.1087 +        ST_LOGE("consumerConnect: consumerListener may not be NULL");
  1.1088 +        return BAD_VALUE;
  1.1089 +    }
  1.1090 +
  1.1091 +    mConsumerListener = consumerListener;
  1.1092 +    mConsumerControlledByApp = controlledByApp;
  1.1093 +
  1.1094 +    return NO_ERROR;
  1.1095 +}
  1.1096 +
  1.1097 +status_t GonkBufferQueue::consumerDisconnect() {
  1.1098 +    ST_LOGV("consumerDisconnect");
  1.1099 +    Mutex::Autolock lock(mMutex);
  1.1100 +
  1.1101 +    if (mConsumerListener == NULL) {
  1.1102 +        ST_LOGE("consumerDisconnect: No consumer is connected!");
  1.1103 +        return -EINVAL;
  1.1104 +    }
  1.1105 +
  1.1106 +    mAbandoned = true;
  1.1107 +    mConsumerListener = NULL;
  1.1108 +    mQueue.clear();
  1.1109 +    freeAllBuffersLocked();
  1.1110 +    mDequeueCondition.broadcast();
  1.1111 +    return NO_ERROR;
  1.1112 +}
  1.1113 +
  1.1114 +status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
  1.1115 +    ST_LOGV("getReleasedBuffers");
  1.1116 +    Mutex::Autolock lock(mMutex);
  1.1117 +
  1.1118 +    if (mAbandoned) {
  1.1119 +        ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
  1.1120 +        return NO_INIT;
  1.1121 +    }
  1.1122 +
  1.1123 +    uint32_t mask = 0;
  1.1124 +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
  1.1125 +        if (!mSlots[i].mAcquireCalled) {
  1.1126 +            mask |= 1 << i;
  1.1127 +        }
  1.1128 +    }
  1.1129 +
  1.1130 +    // Remove buffers in flight (on the queue) from the mask where acquire has
  1.1131 +    // been called, as the consumer will not receive the buffer address, so
  1.1132 +    // it should not free these slots.
  1.1133 +    Fifo::iterator front(mQueue.begin());
  1.1134 +    while (front != mQueue.end()) {
  1.1135 +        if (front->mAcquireCalled)
  1.1136 +            mask &= ~(1 << front->mBuf);
  1.1137 +        front++;
  1.1138 +    }
  1.1139 +
  1.1140 +    *slotMask = mask;
  1.1141 +
  1.1142 +    ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
  1.1143 +    return NO_ERROR;
  1.1144 +}
  1.1145 +
  1.1146 +status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) {
  1.1147 +    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
  1.1148 +    if (!w || !h) {
  1.1149 +        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
  1.1150 +                w, h);
  1.1151 +        return BAD_VALUE;
  1.1152 +    }
  1.1153 +
  1.1154 +    Mutex::Autolock lock(mMutex);
  1.1155 +    mDefaultWidth = w;
  1.1156 +    mDefaultHeight = h;
  1.1157 +    return NO_ERROR;
  1.1158 +}
  1.1159 +
  1.1160 +status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
  1.1161 +    ATRACE_CALL();
  1.1162 +    Mutex::Autolock lock(mMutex);
  1.1163 +    return setDefaultMaxBufferCountLocked(bufferCount);
  1.1164 +}
  1.1165 +
  1.1166 +status_t GonkBufferQueue::disableAsyncBuffer() {
  1.1167 +    ATRACE_CALL();
  1.1168 +    Mutex::Autolock lock(mMutex);
  1.1169 +    if (mConsumerListener != NULL) {
  1.1170 +        ST_LOGE("disableAsyncBuffer: consumer already connected!");
  1.1171 +        return INVALID_OPERATION;
  1.1172 +    }
  1.1173 +    mUseAsyncBuffer = false;
  1.1174 +    return NO_ERROR;
  1.1175 +}
  1.1176 +
  1.1177 +status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
  1.1178 +    ATRACE_CALL();
  1.1179 +    Mutex::Autolock lock(mMutex);
  1.1180 +    if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
  1.1181 +        ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
  1.1182 +                maxAcquiredBuffers);
  1.1183 +        return BAD_VALUE;
  1.1184 +    }
  1.1185 +    if (mConnectedApi != NO_CONNECTED_API) {
  1.1186 +        return INVALID_OPERATION;
  1.1187 +    }
  1.1188 +    mMaxAcquiredBufferCount = maxAcquiredBuffers;
  1.1189 +    return NO_ERROR;
  1.1190 +}
  1.1191 +
  1.1192 +int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const {
  1.1193 +    // if dequeueBuffer is allowed to error out, we don't have to
  1.1194 +    // add an extra buffer.
  1.1195 +    if (!mUseAsyncBuffer)
  1.1196 +        return mMaxAcquiredBufferCount;
  1.1197 +
  1.1198 +    // we're in async mode, or we want to prevent the app to
  1.1199 +    // deadlock itself, we throw-in an extra buffer to guarantee it.
  1.1200 +    if (mDequeueBufferCannotBlock || async)
  1.1201 +        return mMaxAcquiredBufferCount + 1;
  1.1202 +
  1.1203 +    return mMaxAcquiredBufferCount;
  1.1204 +}
  1.1205 +
  1.1206 +int GonkBufferQueue::getMinMaxBufferCountLocked(bool async) const {
  1.1207 +    return getMinUndequeuedBufferCount(async) + 1;
  1.1208 +}
  1.1209 +
  1.1210 +int GonkBufferQueue::getMaxBufferCountLocked(bool async) const {
  1.1211 +    int minMaxBufferCount = getMinMaxBufferCountLocked(async);
  1.1212 +
  1.1213 +    int maxBufferCount = mDefaultMaxBufferCount;
  1.1214 +    if (maxBufferCount < minMaxBufferCount) {
  1.1215 +        maxBufferCount = minMaxBufferCount;
  1.1216 +    }
  1.1217 +    if (mOverrideMaxBufferCount != 0) {
  1.1218 +        assert(mOverrideMaxBufferCount >= minMaxBufferCount);
  1.1219 +        maxBufferCount = mOverrideMaxBufferCount;
  1.1220 +    }
  1.1221 +
  1.1222 +    // Any buffers that are dequeued by the producer or sitting in the queue
  1.1223 +    // waiting to be consumed need to have their slots preserved.  Such
  1.1224 +    // buffers will temporarily keep the max buffer count up until the slots
  1.1225 +    // no longer need to be preserved.
  1.1226 +    for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
  1.1227 +        BufferSlot::BufferState state = mSlots[i].mBufferState;
  1.1228 +        if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
  1.1229 +            maxBufferCount = i + 1;
  1.1230 +        }
  1.1231 +    }
  1.1232 +
  1.1233 +    return maxBufferCount;
  1.1234 +}
  1.1235 +
  1.1236 +bool GonkBufferQueue::stillTracking(const BufferItem *item) const {
  1.1237 +    const BufferSlot &slot = mSlots[item->mBuf];
  1.1238 +
  1.1239 +    ST_LOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, "
  1.1240 +            "slot: { slot=%d/%llu, buffer=%p }",
  1.1241 +            item->mBuf, item->mFrameNumber,
  1.1242 +            (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
  1.1243 +            item->mBuf, slot.mFrameNumber,
  1.1244 +            (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
  1.1245 +
  1.1246 +    // Compare item with its original buffer slot.  We can check the slot
  1.1247 +    // as the buffer would not be moved to a different slot by the producer.
  1.1248 +    return (slot.mGraphicBuffer != NULL &&
  1.1249 +            item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
  1.1250 +}
  1.1251 +
  1.1252 +GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
  1.1253 +        const wp<ConsumerListener>& consumerListener):
  1.1254 +        mConsumerListener(consumerListener) {}
  1.1255 +
  1.1256 +GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
  1.1257 +
  1.1258 +void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
  1.1259 +    sp<ConsumerListener> listener(mConsumerListener.promote());
  1.1260 +    if (listener != NULL) {
  1.1261 +        listener->onFrameAvailable();
  1.1262 +    }
  1.1263 +}
  1.1264 +
  1.1265 +void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
  1.1266 +    sp<ConsumerListener> listener(mConsumerListener.promote());
  1.1267 +    if (listener != NULL) {
  1.1268 +        listener->onBuffersReleased();
  1.1269 +    }
  1.1270 +}
  1.1271 +
  1.1272 +}; // namespace android

mercurial