diff options
Diffstat (limited to 'widget/gonk/nativewindow/GonkBufferQueueLL')
13 files changed, 0 insertions, 3012 deletions
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp deleted file mode 100644 index 7df72bf68..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GonkBufferItem.h" - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <system/window.h> - -namespace android { - -GonkBufferItem::GonkBufferItem() : - mTransform(0), - mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0), - mIsAutoTimestamp(false), - mFrameNumber(0), - mSlot(INVALID_BUFFER_SLOT), - mIsDroppable(false), - mAcquireCalled(false), - mTransformToDisplayInverse(false) { - mCrop.makeInvalid(); -} - -GonkBufferItem::operator IGonkGraphicBufferConsumer::BufferItem() const { - IGonkGraphicBufferConsumer::BufferItem bufferItem; - bufferItem.mGraphicBuffer = mGraphicBuffer; - bufferItem.mFence = mFence; - bufferItem.mCrop = mCrop; - bufferItem.mTransform = mTransform; - bufferItem.mScalingMode = mScalingMode; - bufferItem.mTimestamp = mTimestamp; - bufferItem.mIsAutoTimestamp = mIsAutoTimestamp; - bufferItem.mFrameNumber = mFrameNumber; - bufferItem.mBuf = mSlot; - bufferItem.mIsDroppable = mIsDroppable; - bufferItem.mAcquireCalled = mAcquireCalled; - bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse; - return bufferItem; -} - -size_t GonkBufferItem::getPodSize() const { - size_t c = sizeof(mCrop) + - sizeof(mTransform) + - sizeof(mScalingMode) + - sizeof(mTimestamp) + - sizeof(mIsAutoTimestamp) + - sizeof(mFrameNumber) + - sizeof(mSlot) + - sizeof(mIsDroppable) + - sizeof(mAcquireCalled) + - sizeof(mTransformToDisplayInverse); - return c; -} - -size_t GonkBufferItem::getFlattenedSize() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - if (mFence != 0) { - c += mFence->getFlattenedSize(); - FlattenableUtils::align<4>(c); - } - return sizeof(int32_t) + c + getPodSize(); -} - -size_t GonkBufferItem::getFdCount() const { - size_t c = 0; - if (mGraphicBuffer != 0) { - c += mGraphicBuffer->getFdCount(); - } - if (mFence != 0) { - c += mFence->getFdCount(); - } - return c; -} - -status_t GonkBufferItem::flatten( - void*& buffer, size_t& size, int*& fds, size_t& count) const { - - // make sure we have enough space - if (count < GonkBufferItem::getFlattenedSize()) { - return NO_MEMORY; - } - - // content flags are stored first - uint32_t& flags = *static_cast<uint32_t*>(buffer); - - // advance the pointer - FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); - - flags = 0; - if (mGraphicBuffer != 0) { - status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 1; - } - if (mFence != 0) { - status_t err = mFence->flatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - flags |= 2; - } - - // check we have enough space (in case flattening the fence/graphicbuffer lied to us) - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::write(buffer, size, mCrop); - FlattenableUtils::write(buffer, size, mTransform); - FlattenableUtils::write(buffer, size, mScalingMode); - FlattenableUtils::write(buffer, size, mTimestamp); - FlattenableUtils::write(buffer, size, mIsAutoTimestamp); - FlattenableUtils::write(buffer, size, mFrameNumber); - FlattenableUtils::write(buffer, size, mSlot); - FlattenableUtils::write(buffer, size, mIsDroppable); - FlattenableUtils::write(buffer, size, mAcquireCalled); - FlattenableUtils::write(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -status_t GonkBufferItem::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - - if (size < sizeof(uint32_t)) - return NO_MEMORY; - - uint32_t flags = 0; - FlattenableUtils::read(buffer, size, flags); - - if (flags & 1) { - mGraphicBuffer = new GraphicBuffer(); - status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - if (flags & 2) { - mFence = new Fence(); - status_t err = mFence->unflatten(buffer, size, fds, count); - if (err) return err; - size -= FlattenableUtils::align<4>(buffer); - } - - // check we have enough space - if (size < getPodSize()) { - return NO_MEMORY; - } - - FlattenableUtils::read(buffer, size, mCrop); - FlattenableUtils::read(buffer, size, mTransform); - FlattenableUtils::read(buffer, size, mScalingMode); - FlattenableUtils::read(buffer, size, mTimestamp); - FlattenableUtils::read(buffer, size, mIsAutoTimestamp); - FlattenableUtils::read(buffer, size, mFrameNumber); - FlattenableUtils::read(buffer, size, mSlot); - FlattenableUtils::read(buffer, size, mIsDroppable); - FlattenableUtils::read(buffer, size, mAcquireCalled); - FlattenableUtils::read(buffer, size, mTransformToDisplayInverse); - - return NO_ERROR; -} - -const char* GonkBufferItem::scalingModeName(uint32_t scalingMode) { - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; - default: return "Unknown"; - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h deleted file mode 100644 index b2d6d3068..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERITEM_LL_H -#define NATIVEWINDOW_GONKBUFFERITEM_LL_H - -#include "IGonkGraphicBufferConsumerLL.h" - -#include <ui/Rect.h> - -#include <utils/Flattenable.h> -#include <utils/StrongPointer.h> - -namespace android { - -class Fence; -class GraphicBuffer; - -class GonkBufferItem : public Flattenable<GonkBufferItem> { - friend class Flattenable<GonkBufferItem>; - size_t getPodSize() const; - size_t getFlattenedSize() const; - size_t getFdCount() const; - status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; - status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); - - public: - // The default value of mBuf, used to indicate this doesn't correspond to a slot. - enum { INVALID_BUFFER_SLOT = -1 }; - GonkBufferItem(); - operator IGonkGraphicBufferConsumer::BufferItem() const; - - static const char* scalingModeName(uint32_t scalingMode); - - // mGraphicBuffer points to the buffer allocated for this slot, or is NULL - // if the buffer in this slot has been acquired in the past (see - // BufferSlot.mAcquireCalled). - sp<GraphicBuffer> mGraphicBuffer; - - // mFence is a fence that will signal when the buffer is idle. - sp<Fence> mFence; - - // mCrop is the current crop rectangle for this buffer slot. - Rect mCrop; - - // mTransform is the current transform flags for this buffer slot. - // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h> - uint32_t mTransform; - - // mScalingMode is the current scaling mode for this buffer slot. - // refer to NATIVE_WINDOW_SCALING_* in <window.h> - uint32_t mScalingMode; - - // mTimestamp is the current timestamp for this buffer slot. This gets - // to set by queueBuffer each time this slot is queued. This value - // is guaranteed to be monotonically increasing for each newly - // acquired buffer. - int64_t mTimestamp; - - // mIsAutoTimestamp indicates whether mTimestamp was generated - // automatically when the buffer was queued. - bool mIsAutoTimestamp; - - // mFrameNumber is the number of the queued frame for this slot. - uint64_t mFrameNumber; - - // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT). - int mSlot; - - // mIsDroppable whether this buffer was queued with the - // property that it can be replaced by a new buffer for the purpose of - // making sure dequeueBuffer() won't block. - // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer - // was queued. - bool mIsDroppable; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates this buffer must be transformed by the inverse transform of the screen - // it is displayed onto. This is applied after mTransform. - bool mTransformToDisplayInverse; -}; - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp deleted file mode 100644 index 1d7eb2702..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define LOG_TAG "GonkBufferQueueConsumer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include "GonkBufferItem.h" -#include "GonkBufferQueueConsumer.h" -#include "GonkBufferQueueCore.h" -#include <gui/IConsumerListener.h> -#include <gui/IProducerListener.h> - -namespace android { - -GonkBufferQueueConsumer::GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core) : - mCore(core), - mSlots(core->mSlots), - mConsumerName() {} - -GonkBufferQueueConsumer::~GonkBufferQueueConsumer() {} - -status_t GonkBufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, - nsecs_t expectedPresent) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - - // Check that the consumer doesn't currently have the maximum number of - // buffers acquired. We allow the max buffer count to be exceeded by one - // buffer so that the consumer can successfully set up the newly acquired - // buffer before releasing the old one. - int numAcquiredBuffers = 0; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) { - ++numAcquiredBuffers; - } - } - if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { - ALOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)", - numAcquiredBuffers, mCore->mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - - // Check if the queue is empty. - // In asynchronous mode the list is guaranteed to be one buffer deep, - // while in synchronous mode we use the oldest buffer. - if (mCore->mQueue.empty()) { - return NO_BUFFER_AVAILABLE; - } - - GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); - - // If expectedPresent is specified, we may not want to return a buffer yet. - // If it's specified and there's more than one buffer queued, we may want - // to drop a buffer. - if (expectedPresent != 0) { - const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second - - // The 'expectedPresent' argument indicates when the buffer is expected - // to be presented on-screen. If the buffer's desired present time is - // earlier (less) than expectedPresent -- meaning it will be displayed - // on time or possibly late if we show it as soon as possible -- we - // acquire and return it. If we don't want to display it until after the - // expectedPresent time, we return PRESENT_LATER without acquiring it. - // - // To be safe, we don't defer acquisition if expectedPresent is more - // than one second in the future beyond the desired present time - // (i.e., we'd be holding the buffer for a long time). - // - // NOTE: Code assumes monotonic time values from the system clock - // are positive. - - // Start by checking to see if we can drop frames. We skip this check if - // the timestamps are being auto-generated by Surface. If the app isn't - // generating timestamps explicitly, it probably doesn't want frames to - // be discarded based on them. - while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { - // If entry[1] is timely, drop entry[0] (and repeat). We apply an - // additional criterion here: we only drop the earlier buffer if our - // desiredPresent falls within +/- 1 second of the expected present. - // Otherwise, bogus desiredPresent times (e.g., 0 or a small - // relative timestamp), which normally mean "ignore the timestamp - // and acquire immediately", would cause us to drop frames. - // - // We may want to add an additional criterion: don't drop the - // earlier buffer if entry[1]'s fence hasn't signaled yet. - const BufferItem& bufferItem(mCore->mQueue[1]); - nsecs_t desiredPresent = bufferItem.mTimestamp; - if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || - desiredPresent > expectedPresent) { - // This buffer is set to display in the near future, or - // desiredPresent is garbage. Either way we don't want to drop - // the previous buffer just to get this on the screen sooner. - ALOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%" - PRId64 " (%" PRId64 ") now=%" PRId64, - desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - break; - } - - ALOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64 - " size=%zu", - desiredPresent, expectedPresent, mCore->mQueue.size()); - if (mCore->stillTracking(front)) { - // Front buffer is still in mSlots, so mark the slot as free - mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE; - } - mCore->mQueue.erase(front); - front = mCore->mQueue.begin(); - } - - // See if the front buffer is due - nsecs_t desiredPresent = front->mTimestamp; - if (desiredPresent > expectedPresent && - desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) { - ALOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64 - " (%" PRId64 ") now=%" PRId64, - desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - return PRESENT_LATER; - } - - ALOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " " - "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent, - desiredPresent - expectedPresent, - systemTime(CLOCK_MONOTONIC)); - } - - int slot = front->mSlot; - //*outBuffer = *front; - outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer; - outBuffer->mFrameNumber = mSlots[slot].mFrameNumber; - outBuffer->mBuf = slot; - outBuffer->mFence = mSlots[slot].mFence; - - ATRACE_BUFFER_INDEX(slot); - - ALOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }", - slot, front->mFrameNumber, front->mGraphicBuffer->handle); - // If the front buffer is still being tracked, update its slot state - if (mCore->stillTracking(front)) { - mSlots[slot].mAcquireCalled = true; - mSlots[slot].mNeedsCleanupOnRelease = false; - mSlots[slot].mBufferState = GonkBufferSlot::ACQUIRED; - mSlots[slot].mFence = Fence::NO_FENCE; - } - - // If the buffer has previously been acquired by the consumer, set - // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer - // on the consumer side - //if (outBuffer->mAcquireCalled) { - // outBuffer->mGraphicBuffer = NULL; - //} - - mCore->mQueue.erase(front); - - // We might have freed a slot while dropping old buffers, or the producer - // may be blocked waiting for the number of buffers in the queue to - // decrease. - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::detachBuffer(int slot) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(slot); - ALOGV("detachBuffer(C): slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("detachBuffer(C): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("detachBuffer(C): slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::ACQUIRED) { - ALOGE("detachBuffer(C): slot %d is not owned by the consumer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mCore->freeBufferLocked(slot); - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::attachBuffer(int* outSlot, - const sp<android::GraphicBuffer>& buffer) { - ATRACE_CALL(); - - if (outSlot == NULL) { - ALOGE("attachBuffer(P): outSlot must not be NULL"); - return BAD_VALUE; - } else if (buffer == NULL) { - ALOGE("attachBuffer(P): cannot attach NULL buffer"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - // Make sure we don't have too many acquired buffers and find a free slot - // to put the buffer into (the oldest if there are multiple). - int numAcquiredBuffers = 0; - int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) { - ++numAcquiredBuffers; - } else if (mSlots[s].mBufferState == GonkBufferSlot::FREE) { - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } - } - } - - if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { - ALOGE("attachBuffer(P): max acquired buffer count reached: %d " - "(max %d)", numAcquiredBuffers, - mCore->mMaxAcquiredBufferCount); - return INVALID_OPERATION; - } - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("attachBuffer(P): could not find free buffer slot"); - return NO_MEMORY; - } - - *outSlot = found; - ATRACE_BUFFER_INDEX(*outSlot); - ALOGV("attachBuffer(C): returning slot %d", *outSlot); - - mSlots[*outSlot].mGraphicBuffer = buffer; - mSlots[*outSlot].mBufferState = GonkBufferSlot::ACQUIRED; - mSlots[*outSlot].mAttachedByConsumer = true; - mSlots[*outSlot].mNeedsCleanupOnRelease = false; - mSlots[*outSlot].mFence = Fence::NO_FENCE; - mSlots[*outSlot].mFrameNumber = 0; - - // mAcquireCalled tells GonkBufferQueue that it doesn't need to send a valid - // GraphicBuffer pointer on the next acquireBuffer call, which decreases - // Binder traffic by not un/flattening the GraphicBuffer. However, it - // requires that the consumer maintain a cached copy of the slot <--> buffer - // mappings, which is why the consumer doesn't need the valid pointer on - // acquire. - // - // The StreamSplitter is one of the primary users of the attach/detach - // logic, and while it is running, all buffers it acquires are immediately - // detached, and all buffers it eventually releases are ones that were - // attached (as opposed to having been obtained from acquireBuffer), so it - // doesn't make sense to maintain the slot/buffer mappings, which would - // become invalid for every buffer during detach/attach. By setting this to - // false, the valid GraphicBuffer pointer will always be sent with acquire - // for attached buffers. - mSlots[*outSlot].mAcquireCalled = false; - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, - const sp<Fence>& releaseFence) { - ATRACE_CALL(); - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS || - releaseFence == NULL) { - return BAD_VALUE; - } - - sp<IProducerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - // If the frame number has changed because the buffer has been reallocated, - // we can ignore this releaseBuffer for the old buffer - //if (frameNumber != mSlots[slot].mFrameNumber) { - // return STALE_BUFFER_SLOT; - //} - - // Make sure this buffer hasn't been queued while acquired by the consumer - GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); - while (current != mCore->mQueue.end()) { - if (current->mSlot == slot) { - ALOGE("releaseBuffer: buffer slot %d pending release is " - "currently queued", slot); - return BAD_VALUE; - } - ++current; - } - - if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) { - mSlots[slot].mFence = releaseFence; - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - listener = mCore->mConnectedProducerListener; - ALOGV("releaseBuffer: releasing slot %d", slot); - } else if (mSlots[slot].mNeedsCleanupOnRelease) { - ALOGV("releaseBuffer: releasing a stale buffer slot %d " - "(state = %d)", slot, mSlots[slot].mBufferState); - mSlots[slot].mNeedsCleanupOnRelease = false; - return STALE_BUFFER_SLOT; - } else { - ALOGV("releaseBuffer: attempted to release buffer slot %d " - "but its state was %d", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mCore->mDequeueCondition.broadcast(); - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBufferReleased(); - } - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::connect( - const sp<IConsumerListener>& consumerListener, bool controlledByApp) { - ATRACE_CALL(); - - if (consumerListener == NULL) { - ALOGE("connect(C): consumerListener may not be NULL"); - return BAD_VALUE; - } - - ALOGV("connect(C): controlledByApp=%s", - controlledByApp ? "true" : "false"); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("connect(C): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - mCore->mConsumerListener = consumerListener; - mCore->mConsumerControlledByApp = controlledByApp; - - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::disconnect() { - ATRACE_CALL(); - - ALOGV("disconnect(C)"); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConsumerListener == NULL) { - ALOGE("disconnect(C): no consumer is connected"); - return BAD_VALUE; - } - - mCore->mIsAbandoned = true; - mCore->mConsumerListener = NULL; - mCore->mQueue.clear(); - mCore->freeAllBuffersLocked(); - mCore->mDequeueCondition.broadcast(); - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) { - ATRACE_CALL(); - - if (outSlotMask == NULL) { - ALOGE("getReleasedBuffers: outSlotMask may not be NULL"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - uint64_t mask = 0; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (!mSlots[s].mAcquireCalled) { - mask |= (1ULL << s); - } - } - - // Remove from the mask queued buffers for which acquire has been called, - // since the consumer will not receive their buffer addresses and so must - // retain their cached information - GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); - while (current != mCore->mQueue.end()) { - if (current->mAcquireCalled) { - mask &= ~(1ULL << current->mSlot); - } - ++current; - } - - ALOGV("getReleasedBuffers: returning mask %#" PRIx64, mask); - *outSlotMask = mask; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setDefaultBufferSize(uint32_t width, - uint32_t height) { - ATRACE_CALL(); - - if (width == 0 || height == 0) { - ALOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u " - "height=%u)", width, height); - return BAD_VALUE; - } - - ALOGV("setDefaultBufferSize: width=%u height=%u", width, height); - - Mutex::Autolock lock(mCore->mMutex); - mCore->mDefaultWidth = width; - mCore->mDefaultHeight = height; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - return mCore->setDefaultMaxBufferCountLocked(bufferCount); -} - -status_t GonkBufferQueueConsumer::disableAsyncBuffer() { - ATRACE_CALL(); - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConsumerListener != NULL) { - ALOGE("disableAsyncBuffer: consumer already connected"); - return INVALID_OPERATION; - } - - ALOGV("disableAsyncBuffer"); - mCore->mUseAsyncBuffer = false; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setMaxAcquiredBufferCount( - int maxAcquiredBuffers) { - ATRACE_CALL(); - - if (maxAcquiredBuffers < 1 || - maxAcquiredBuffers > GonkBufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) { - ALOGE("setMaxAcquiredBufferCount: invalid count %d", - maxAcquiredBuffers); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) { - ALOGE("setMaxAcquiredBufferCount: producer is already connected"); - return INVALID_OPERATION; - } - - ALOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); - mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; - return NO_ERROR; -} - -void GonkBufferQueueConsumer::setConsumerName(const String8& name) { - ATRACE_CALL(); - ALOGV("setConsumerName: '%s'", name.string()); - Mutex::Autolock lock(mCore->mMutex); - mCore->mConsumerName = name; - mConsumerName = name; -} - -status_t GonkBufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { - ATRACE_CALL(); - ALOGV("setDefaultBufferFormat: %u", defaultFormat); - Mutex::Autolock lock(mCore->mMutex); - mCore->mDefaultBufferFormat = defaultFormat; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { - ATRACE_CALL(); - ALOGV("setConsumerUsageBits: %#x", usage); - Mutex::Autolock lock(mCore->mMutex); - mCore->mConsumerUsageBits = usage; - return NO_ERROR; -} - -status_t GonkBufferQueueConsumer::setTransformHint(uint32_t hint) { - ATRACE_CALL(); - ALOGV("setTransformHint: %#x", hint); - Mutex::Autolock lock(mCore->mMutex); - mCore->mTransformHint = hint; - return NO_ERROR; -} - -sp<NativeHandle> GonkBufferQueueConsumer::getSidebandStream() const { - return mCore->mSidebandStream; -} - -void GonkBufferQueueConsumer::dumpToString(String8& result, const char* prefix) const { - mCore->dump(result, prefix); -} - -already_AddRefed<GonkBufferSlot::TextureClient> -GonkBufferQueueConsumer::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) -{ - Mutex::Autolock _l(mCore->mMutex); - if (buffer == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return nullptr; - } - - for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) { - RefPtr<TextureClient> client(mSlots[i].mTextureClient); - return client.forget(); - } - } - ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); - return nullptr; -} - -int -GonkBufferQueueConsumer::getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const -{ - if (client == NULL) { - ALOGE("getSlotFromBufferLocked: encountered NULL buffer"); - return BAD_VALUE; - } - - for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].mTextureClient == client) { - return i; - } - } - ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client); - return BAD_VALUE; -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h deleted file mode 100644 index a97cfab42..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H - -#include "GonkBufferQueueDefs.h" -#include "IGonkGraphicBufferConsumerLL.h" - -namespace android { - -class GonkBufferQueueCore; - -class GonkBufferQueueConsumer : public BnGonkGraphicBufferConsumer { - -public: - GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core); - virtual ~GonkBufferQueueConsumer(); - - // acquireBuffer attempts to acquire ownership of the next pending buffer in - // the GonkBufferQueue. If no buffer is pending then it returns - // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the - // information about the buffer is returned in BufferItem. If the buffer - // returned had previously been acquired then the BufferItem::mGraphicBuffer - // field of buffer is set to NULL and it is assumed that the consumer still - // holds a reference to the buffer. - // - // If expectedPresent is nonzero, it indicates the time when the buffer - // will be displayed on screen. If the buffer's timestamp is farther in the - // future, the buffer won't be acquired, and PRESENT_LATER will be - // returned. The presentation time is in nanoseconds, and the time base - // is CLOCK_MONOTONIC. - virtual status_t acquireBuffer(BufferItem* outBuffer, - nsecs_t expectedPresent); - - // See IGonkGraphicBufferConsumer::detachBuffer - virtual status_t detachBuffer(int slot); - - // See IGonkGraphicBufferConsumer::attachBuffer - virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer); - - // releaseBuffer releases a buffer slot from the consumer back to the - // GonkBufferQueue. This may be done while the buffer's contents are still - // being accessed. The fence will signal when the buffer is no longer - // in use. frameNumber is used to indentify the exact buffer returned. - // - // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free - // any references to the just-released buffer that it might have, as if it - // had received a onBuffersReleased() call with a mask set for the released - // buffer. - virtual status_t releaseBuffer(int slot, uint64_t frameNumber, - const sp<Fence>& releaseFence); - - // connect connects a consumer to the GonkBufferQueue. Only one - // consumer may be connected, and when that consumer disconnects the - // GonkBufferQueue is placed into the "abandoned" state, causing most - // interactions with the GonkBufferQueue by the producer to fail. - // controlledByApp indicates whether the consumer is controlled by - // the application. - // - // consumerListener may not be NULL. - virtual status_t connect(const sp<IConsumerListener>& consumerListener, - bool controlledByApp); - - // disconnect disconnects a consumer from the GonkBufferQueue. All - // buffers will be freed and the GonkBufferQueue is placed in the "abandoned" - // state, causing most interactions with the GonkBufferQueue by the producer to - // fail. - virtual status_t disconnect(); - - // getReleasedBuffers sets the value pointed to by outSlotMask to a bit mask - // indicating which buffer slots have been released by the GonkBufferQueue - // but have not yet been released by the consumer. - // - // This should be called from the onBuffersReleased() callback. - virtual status_t getReleasedBuffers(uint64_t* outSlotMask); - - // setDefaultBufferSize is used to set the size of buffers returned by - // dequeueBuffer when a width and height of zero is requested. Default - // is 1x1. - virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height); - - // setDefaultMaxBufferCount sets the default value for the maximum buffer - // count (the initial default is 2). If the producer has requested a - // buffer count using setBufferCount, the default buffer count will only - // take effect if the producer sets the count back to zero. - // - // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. - virtual status_t setDefaultMaxBufferCount(int bufferCount); - - // disableAsyncBuffer disables the extra buffer used in async mode - // (when both producer and consumer have set their "isControlledByApp" - // flag) and has dequeueBuffer() return WOULD_BLOCK instead. - // - // This can only be called before connect(). - virtual status_t disableAsyncBuffer(); - - // setMaxAcquiredBufferCount sets the maximum number of buffers that can - // be acquired by the consumer at one time (default 1). This call will - // fail if a producer is connected to the GonkBufferQueue. - virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers); - - // setConsumerName sets the name used in logging - virtual void setConsumerName(const String8& name); - - // setDefaultBufferFormat allows the GonkBufferQueue to create - // GraphicBuffers of a defaultFormat if no format is specified - // in dequeueBuffer. Formats are enumerated in graphics.h; the - // initial default is HAL_PIXEL_FORMAT_RGBA_8888. - virtual status_t setDefaultBufferFormat(uint32_t defaultFormat); - - // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. - // These are merged with the bits passed to dequeueBuffer. The values are - // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0. - virtual status_t setConsumerUsageBits(uint32_t usage); - - // setTransformHint bakes in rotation to buffers so overlays can be used. - // The values are enumerated in window.h, e.g. - // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). - virtual status_t setTransformHint(uint32_t hint); - - // Retrieve the sideband buffer stream, if any. - virtual sp<NativeHandle> getSidebandStream() const; - - // dump our state in a String - virtual void dumpToString(String8& result, const char* prefix) const; - - // Added by mozilla - virtual already_AddRefed<GonkBufferSlot::TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer); - - virtual int getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const; - - // Functions required for backwards compatibility. - // These will be modified/renamed in IGonkGraphicBufferConsumer and will be - // removed from this class at that time. See b/13306289. - virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, - bool controlledByApp) { - return connect(consumer, controlledByApp); - } - - virtual status_t consumerDisconnect() { return disconnect(); } - - // End functions required for backwards compatibility - -private: - sp<GonkBufferQueueCore> mCore; - - // This references mCore->mSlots. Lock mCore->mMutex while accessing. - GonkBufferQueueDefs::SlotsType& mSlots; - - // This is a cached copy of the name stored in the GonkBufferQueueCore. - // It's updated during setConsumerName. - String8 mConsumerName; - -}; // class GonkBufferQueueConsumer - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp deleted file mode 100644 index 9e8e337f6..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueueCore" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include <inttypes.h> - -#include "GonkBufferItem.h" -#include "GonkBufferQueueCore.h" -#include <gui/IConsumerListener.h> -#include <gui/IGraphicBufferAlloc.h> -#include <gui/IProducerListener.h> -#include <gui/ISurfaceComposer.h> -#include <private/gui/ComposerService.h> - -#include <cutils/compiler.h> -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" - -template <typename T> -static inline T max(T a, T b) { return a > b ? a : b; } - -namespace android { - -static String8 getUniqueName() { - static volatile int32_t counter = 0; - return String8::format("unnamed-%d-%d", getpid(), - android_atomic_inc(&counter)); -} - -GonkBufferQueueCore::GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : - mAllocator(allocator), - mMutex(), - mIsAbandoned(false), - mConsumerControlledByApp(false), - mConsumerName(getUniqueName()), - mConsumerListener(), - mConsumerUsageBits(0), - mConnectedApi(NO_CONNECTED_API), - mConnectedProducerListener(), - mSlots(), - mQueue(), - mOverrideMaxBufferCount(0), - mDequeueCondition(), - mUseAsyncBuffer(true), - mDequeueBufferCannotBlock(false), - mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), - mDefaultWidth(1), - mDefaultHeight(1), - mDefaultMaxBufferCount(2), - mMaxAcquiredBufferCount(1), - mBufferHasBeenQueued(false), - mFrameCounter(0), - mTransformHint(0), - mIsAllocating(false), - mIsAllocatingCondition() -{ - ALOGV("GonkBufferQueueCore"); -} - -GonkBufferQueueCore::~GonkBufferQueueCore() {} - -void GonkBufferQueueCore::dump(String8& result, const char* prefix) const { - Mutex::Autolock lock(mMutex); - - String8 fifo; - Fifo::const_iterator current(mQueue.begin()); - while (current != mQueue.end()) { - fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " - "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n", - current->mSlot, current->mGraphicBuffer.get(), - current->mCrop.left, current->mCrop.top, current->mCrop.right, - current->mCrop.bottom, current->mTransform, current->mTimestamp, - GonkBufferItem::scalingModeName(current->mScalingMode)); - ++current; - } - - result.appendFormat("%s-GonkBufferQueue mMaxAcquiredBufferCount=%d, " - "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " - "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n", - prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, - mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, - mQueue.size(), fifo.string()); - - // Trim the free buffers so as to not spam the dump - int maxBufferCount = 0; - for (int s = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) { - const GonkBufferSlot& slot(mSlots[s]); - if (slot.mBufferState != GonkBufferSlot::FREE || - slot.mGraphicBuffer != NULL) { - maxBufferCount = s + 1; - break; - } - } - - for (int s = 0; s < maxBufferCount; ++s) { - const GonkBufferSlot& slot(mSlots[s]); - const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer); - result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix, - (slot.mBufferState == GonkBufferSlot::ACQUIRED) ? ">" : " ", - s, buffer.get(), - GonkBufferSlot::bufferStateName(slot.mBufferState)); - - if (buffer != NULL) { - result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle, - buffer->width, buffer->height, buffer->stride, - buffer->format); - } - - result.append("\n"); - } -} - -int GonkBufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const { - // If dequeueBuffer is allowed to error out, we don't have to add an - // extra buffer. - if (!mUseAsyncBuffer) { - return mMaxAcquiredBufferCount; - } - - if (mDequeueBufferCannotBlock || async) { - return mMaxAcquiredBufferCount + 1; - } - - return mMaxAcquiredBufferCount; -} - -int GonkBufferQueueCore::getMinMaxBufferCountLocked(bool async) const { - return getMinUndequeuedBufferCountLocked(async) + 1; -} - -int GonkBufferQueueCore::getMaxBufferCountLocked(bool async) const { - int minMaxBufferCount = getMinMaxBufferCountLocked(async); - - int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount); - if (mOverrideMaxBufferCount != 0) { - assert(mOverrideMaxBufferCount >= minMaxBufferCount); - maxBufferCount = mOverrideMaxBufferCount; - } - - // Any buffers that are dequeued by the producer or sitting in the queue - // waiting to be consumed need to have their slots preserved. Such buffers - // will temporarily keep the max buffer count up until the slots no longer - // need to be preserved. - for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - GonkBufferSlot::BufferState state = mSlots[s].mBufferState; - if (state == GonkBufferSlot::QUEUED || state == GonkBufferSlot::DEQUEUED) { - maxBufferCount = s + 1; - } - } - - return maxBufferCount; -} - -status_t GonkBufferQueueCore::setDefaultMaxBufferCountLocked(int count) { - const int minBufferCount = 2; - if (count < minBufferCount || count > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGV("setDefaultMaxBufferCount: invalid count %d, should be in " - "[%d, %d]", - count, minBufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - ALOGV("setDefaultMaxBufferCount: setting count to %d", count); - mDefaultMaxBufferCount = count; - mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -void GonkBufferQueueCore::freeBufferLocked(int slot) { - ALOGV("freeBufferLocked: slot %d", slot); - - if (mSlots[slot].mTextureClient) { - mSlots[slot].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[slot].mTextureClient); - mSlots[slot].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - mSlots[slot].mGraphicBuffer.clear(); - if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) { - mSlots[slot].mNeedsCleanupOnRelease = true; - } - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - mSlots[slot].mFrameNumber = UINT32_MAX; - mSlots[slot].mAcquireCalled = false; - - // Destroy fence as GonkBufferQueue now takes ownership - mSlots[slot].mFence = Fence::NO_FENCE; -} - -void GonkBufferQueueCore::freeAllBuffersLocked() { - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called but mQueue is not empty"); - mQueue.clear(); - mBufferHasBeenQueued = false; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - freeBufferLocked(s); - } -} - -bool GonkBufferQueueCore::stillTracking(const GonkBufferItem* item) const { - const GonkBufferSlot& slot = mSlots[item->mSlot]; - - ALOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } " - "slot { slot=%d/%" PRIu64 " buffer=%p }", - item->mSlot, item->mFrameNumber, - (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), - item->mSlot, slot.mFrameNumber, - (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); - - // Compare item with its original buffer slot. We can check the slot as - // the buffer would not be moved to a different slot by the producer. - return (slot.mGraphicBuffer != NULL) && - (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); -} - -void GonkBufferQueueCore::waitWhileAllocatingLocked() const { - ATRACE_CALL(); - while (mIsAllocating) { - mIsAllocatingCondition.wait(mMutex); - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h deleted file mode 100644 index 936e11686..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H - -#include "GonkBufferQueueDefs.h" -#include "GonkBufferSlot.h" - -#include <utils/Condition.h> -#include <utils/Mutex.h> -#include <utils/NativeHandle.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/StrongPointer.h> -#include <utils/Trace.h> -#include <utils/Vector.h> - -#include "mozilla/layers/TextureClient.h" - -#define ATRACE_BUFFER_INDEX(index) - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::layers; - -namespace android { - -class GonkBufferItem; -class IConsumerListener; -class IGraphicBufferAlloc; -class IProducerListener; - -class GonkBufferQueueCore : public virtual RefBase { - - friend class GonkBufferQueueProducer; - friend class GonkBufferQueueConsumer; - -public: - // Used as a placeholder slot number when the value isn't pointing to an - // existing buffer. - enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem - - // We reserve two slots in order to guarantee that the producer and - // consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 2 }; - - // The default API number used to indicate that no producer is connected - enum { NO_CONNECTED_API = 0 }; - - typedef Vector<GonkBufferItem> Fifo; - typedef mozilla::layers::TextureClient TextureClient; - - // GonkBufferQueueCore manages a pool of gralloc memory slots to be used by - // producers and consumers. allocator is used to allocate all the needed - // gralloc buffers. - GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL); - virtual ~GonkBufferQueueCore(); - -private: - // Dump our state in a string - void dump(String8& result, const char* prefix) const; - - int getSlotFromTextureClientLocked(TextureClient* client) const; - - // getMinUndequeuedBufferCountLocked returns the minimum number of buffers - // that must remain in a state other than DEQUEUED. The async parameter - // tells whether we're in asynchronous mode. - int getMinUndequeuedBufferCountLocked(bool async) const; - - // getMinMaxBufferCountLocked returns the minimum number of buffers allowed - // given the current GonkBufferQueue state. The async parameter tells whether - // we're in asynchonous mode. - int getMinMaxBufferCountLocked(bool async) const; - - // getMaxBufferCountLocked returns the maximum number of buffers that can be - // allocated at once. This value depends on the following member variables: - // - // mDequeueBufferCannotBlock - // mMaxAcquiredBufferCount - // mDefaultMaxBufferCount - // mOverrideMaxBufferCount - // async parameter - // - // Any time one of these member variables is changed while a producer is - // connected, mDequeueCondition must be broadcast. - int getMaxBufferCountLocked(bool async) const; - - // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots - // that will be used if the producer does not override the buffer slot - // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The - // initial default is 2. - status_t setDefaultMaxBufferCountLocked(int count); - - // freeBufferLocked frees the GraphicBuffer and sync resources for the - // given slot. - void freeBufferLocked(int slot); - - // freeAllBuffersLocked frees the GraphicBuffer and sync resources for - // all slots. - void freeAllBuffersLocked(); - - // stillTracking returns true iff the buffer item is still being tracked - // in one of the slots. - bool stillTracking(const GonkBufferItem* item) const; - - // waitWhileAllocatingLocked blocks until mIsAllocating is false. - void waitWhileAllocatingLocked() const; - - // mAllocator is the connection to SurfaceFlinger that is used to allocate - // new GraphicBuffer objects. - sp<IGraphicBufferAlloc> mAllocator; - - // mMutex is the mutex used to prevent concurrent access to the member - // variables of GonkBufferQueueCore objects. It must be locked whenever any - // member variable is accessed. - mutable Mutex mMutex; - - // mIsAbandoned indicates that the GonkBufferQueue will no longer be used to - // consume image buffers pushed to it using the IGraphicBufferProducer - // interface. It is initialized to false, and set to true in the - // consumerDisconnect method. A GonkBufferQueue that is abandoned will return - // the NO_INIT error from all IGraphicBufferProducer methods capable of - // returning an error. - bool mIsAbandoned; - - // mConsumerControlledByApp indicates whether the connected consumer is - // controlled by the application. - bool mConsumerControlledByApp; - - // mConsumerName is a string used to identify the GonkBufferQueue in log - // messages. It is set by the IGraphicBufferConsumer::setConsumerName - // method. - String8 mConsumerName; - - // mConsumerListener is used to notify the connected consumer of - // asynchronous events that it may wish to react to. It is initially - // set to NULL and is written by consumerConnect and consumerDisconnect. - sp<IConsumerListener> mConsumerListener; - - // mConsumerUsageBits contains flags that the consumer wants for - // GraphicBuffers. - uint32_t mConsumerUsageBits; - - // mConnectedApi indicates the producer API that is currently connected - // to this GonkBufferQueue. It defaults to NO_CONNECTED_API, and gets updated - // by the connect and disconnect methods. - int mConnectedApi; - - // mConnectedProducerToken is used to set a binder death notification on - // the producer. - sp<IProducerListener> mConnectedProducerListener; - - // mSlots is an array of buffer slots that must be mirrored on the producer - // side. This allows buffer ownership to be transferred between the producer - // and consumer without sending a GraphicBuffer over Binder. The entire - // array is initialized to NULL at construction time, and buffers are - // allocated for a slot when requestBuffer is called with that slot's index. - GonkBufferQueueDefs::SlotsType mSlots; - - // mQueue is a FIFO of queued buffers used in synchronous mode. - Fifo mQueue; - - // mOverrideMaxBufferCount is the limit on the number of buffers that will - // be allocated at one time. This value is set by the producer by calling - // setBufferCount. The default is 0, which means that the producer doesn't - // care about the number of buffers in the pool. In that case, - // mDefaultMaxBufferCount is used as the limit. - int mOverrideMaxBufferCount; - - // mDequeueCondition is a condition variable used for dequeueBuffer in - // synchronous mode. - mutable Condition mDequeueCondition; - - // mUseAsyncBuffer indicates whether an extra buffer is used in async mode - // to prevent dequeueBuffer from blocking. - bool mUseAsyncBuffer; - - // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to - // block. This flag is set during connect when both the producer and - // consumer are controlled by the application. - bool mDequeueBufferCannotBlock; - - // mDefaultBufferFormat can be set so it will override the buffer format - // when it isn't specified in dequeueBuffer. - uint32_t mDefaultBufferFormat; - - // mDefaultWidth holds the default width of allocated buffers. It is used - // in dequeueBuffer if a width and height of 0 are specified. - int mDefaultWidth; - - // mDefaultHeight holds the default height of allocated buffers. It is used - // in dequeueBuffer if a width and height of 0 are specified. - int mDefaultHeight; - - // mDefaultMaxBufferCount is the default limit on the number of buffers that - // will be allocated at one time. This default limit is set by the consumer. - // The limit (as opposed to the default limit) may be overriden by the - // producer. - int mDefaultMaxBufferCount; - - // mMaxAcquiredBufferCount is the number of buffers that the consumer may - // acquire at one time. It defaults to 1, and can be changed by the consumer - // via setMaxAcquiredBufferCount, but this may only be done while no - // producer is connected to the GonkBufferQueue. This value is used to derive - // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer. - int mMaxAcquiredBufferCount; - - // mBufferHasBeenQueued is true once a buffer has been queued. It is reset - // when something causes all buffers to be freed (e.g., changing the buffer - // count). - bool mBufferHasBeenQueued; - - // mFrameCounter is the free running counter, incremented on every - // successful queueBuffer call and buffer allocation. - uint64_t mFrameCounter; - - // mTransformHint is used to optimize for screen rotations. - uint32_t mTransformHint; - - // mSidebandStream is a handle to the sideband buffer stream, if any - sp<NativeHandle> mSidebandStream; - - // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which - // releases mMutex while doing the allocation proper). Producers should not modify any of the - // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to - // false. - bool mIsAllocating; - - // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating - // becomes false. - mutable Condition mIsAllocatingCondition; -}; // class GonkBufferQueueCore - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h deleted file mode 100644 index 60085706f..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_BUFFERQUEUECOREDEFS_H -#define NATIVEWINDOW_BUFFERQUEUECOREDEFS_H - -#include "GonkBufferSlot.h" - -namespace android { - class GonkBufferQueueCore; - - namespace GonkBufferQueueDefs { - // GonkBufferQueue will keep track of at most this value of buffers. - // Attempts at runtime to increase the number of buffers past this - // will fail. - enum { NUM_BUFFER_SLOTS = 64 }; - - typedef GonkBufferSlot SlotsType[NUM_BUFFER_SLOTS]; - } // namespace GonkBufferQueueDefs -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp deleted file mode 100644 index 649d06bee..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GonkBufferQueue" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_NDEBUG 0 - -#include "GonkBufferQueue.h" -#include "GonkBufferQueueConsumer.h" -#include "GonkBufferQueueCore.h" -#include "GonkBufferQueueProducer.h" - -namespace android { - -GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener( - const wp<ConsumerListener>& consumerListener): - mConsumerListener(consumerListener) {} - -GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} - -#if ANDROID_VERSION == 21 -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(); - } -} -#else -void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable(const ::android::BufferItem& item) { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameAvailable(item); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onFrameReplaced(const ::android::BufferItem& item) { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onFrameReplaced(item); - } -} -#endif - -void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onBuffersReleased(); - } -} - -void GonkBufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { - sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - listener->onSidebandStreamChanged(); - } -} - -void GonkBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, - sp<IGonkGraphicBufferConsumer>* outConsumer, - const sp<IGraphicBufferAlloc>& allocator) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, - "GonkBufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, - "GonkBufferQueue: outConsumer must not be NULL"); - - sp<GonkBufferQueueCore> core(new GonkBufferQueueCore(allocator)); - LOG_ALWAYS_FATAL_IF(core == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueCore"); - - sp<IGraphicBufferProducer> producer(new GonkBufferQueueProducer(core)); - LOG_ALWAYS_FATAL_IF(producer == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueProducer"); - - sp<IGonkGraphicBufferConsumer> consumer(new GonkBufferQueueConsumer(core)); - LOG_ALWAYS_FATAL_IF(consumer == NULL, - "GonkBufferQueue: failed to create GonkBufferQueueConsumer"); - - *outProducer = producer; - *outConsumer = consumer; -} - -}; // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h deleted file mode 100644 index b1b4e06b5..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUE_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUE_LL_H - -#include "GonkBufferQueueDefs.h" -#include "IGonkGraphicBufferConsumerLL.h" -#include <gui/IGraphicBufferProducer.h> -#include <gui/IConsumerListener.h> - -// These are only required to keep other parts of the framework with incomplete -// dependencies building successfully -#include <gui/IGraphicBufferAlloc.h> - -namespace android { - -class GonkBufferQueue { -public: - // GonkBufferQueue will keep track of at most this value of buffers. - // Attempts at runtime to increase the number of buffers past this will fail. - enum { NUM_BUFFER_SLOTS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS }; - // Used as a placeholder slot# when the value isn't pointing to an existing buffer. - enum { INVALID_BUFFER_SLOT = IGonkGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT }; - // Alias to <IGonkGraphicBufferConsumer.h> -- please scope from there in future code! - enum { - NO_BUFFER_AVAILABLE = IGonkGraphicBufferConsumer::NO_BUFFER_AVAILABLE, - PRESENT_LATER = IGonkGraphicBufferConsumer::PRESENT_LATER, - }; - - // When in async mode we reserve two slots in order to guarantee that the - // producer and consumer can run asynchronously. - enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 }; - - // for backward source compatibility - typedef ::android::ConsumerListener ConsumerListener; - typedef IGonkGraphicBufferConsumer::BufferItem BufferItem; - - // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak - // reference to the actual consumer object. It forwards all calls to that - // consumer object so long as it exists. - // - // This class exists to avoid having a circular reference between the - // GonkBufferQueue object and the consumer object. The reason this can't be a weak - // reference in the GonkBufferQueue class is because we're planning to expose the - // consumer side of a GonkBufferQueue as a binder interface, which doesn't support - // weak references. - class ProxyConsumerListener : public BnConsumerListener { - public: - ProxyConsumerListener(const wp<ConsumerListener>& consumerListener); - virtual ~ProxyConsumerListener(); -#if ANDROID_VERSION == 21 - virtual void onFrameAvailable(); -#else - virtual void onFrameAvailable(const ::android::BufferItem& item); - virtual void onFrameReplaced(const ::android::BufferItem& item); -#endif - virtual void onBuffersReleased(); - virtual void onSidebandStreamChanged(); - private: - // mConsumerListener is a weak reference to the IConsumerListener. This is - // the raison d'etre of ProxyConsumerListener. - wp<ConsumerListener> mConsumerListener; - }; - - // GonkBufferQueue manages a pool of gralloc memory slots to be used by - // producers and consumers. allocator is used to allocate all the - // needed gralloc buffers. - static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, - sp<IGonkGraphicBufferConsumer>* outConsumer, - const sp<IGraphicBufferAlloc>& allocator = NULL); - -private: - GonkBufferQueue(); // Create through createBufferQueue -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // NATIVEWINDOW_GONKBUFFERQUEUE_LL_H diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp deleted file mode 100644 index d3436756f..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define LOG_TAG "GonkBufferQueueProducer" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include "GonkBufferItem.h" -#include "GonkBufferQueueCore.h" -#include "GonkBufferQueueProducer.h" -#include <gui/IConsumerListener.h> -#include <gui/IGraphicBufferAlloc.h> -#include <gui/IProducerListener.h> - -#include <cutils/compiler.h> -#include <utils/Log.h> -#include <utils/Trace.h> - -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layers/TextureClient.h" - -namespace android { - -GonkBufferQueueProducer::GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core) : - mCore(core), - mSlots(core->mSlots), - mConsumerName(), - mSynchronousMode(true), - mStickyTransform(0) {} - -GonkBufferQueueProducer::~GonkBufferQueueProducer() {} - -status_t GonkBufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - ATRACE_CALL(); - ALOGV("requestBuffer: slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("requestBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("requestBuffer: slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("requestBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } - - mSlots[slot].mRequestBufferCalled = true; - *buf = mSlots[slot].mGraphicBuffer; - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::setBufferCount(int bufferCount) { - ATRACE_CALL(); - ALOGV("setBufferCount: count = %d", bufferCount); - - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - ALOGE("setBufferCount: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (bufferCount > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("setBufferCount: bufferCount %d too large (max %d)", - bufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } - - // There must be no dequeued buffers when changing the buffer count. - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::DEQUEUED) { - ALOGE("setBufferCount: buffer owned by producer"); - return BAD_VALUE; - } - } - - if (bufferCount == 0) { - mCore->mOverrideMaxBufferCount = 0; - mCore->mDequeueCondition.broadcast(); - return NO_ERROR; - } - - const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false); - if (bufferCount < minBufferSlots) { - ALOGE("setBufferCount: requested buffer count %d is less than " - "minimum %d", bufferCount, minBufferSlots); - return BAD_VALUE; - } - - // Here we are guaranteed that the producer doesn't have any dequeued - // buffers and will release all of its buffer references. We don't - // clear the queue, however, so that currently queued buffers still - // get displayed. - mCore->freeAllBuffersLocked(); - mCore->mOverrideMaxBufferCount = bufferCount; - mCore->mDequeueCondition.broadcast(); - listener = mCore->mConsumerListener; - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, - bool async, int* found, status_t* returnFlags) const { - bool tryAgain = true; - while (tryAgain) { - if (mCore->mIsAbandoned) { - ALOGE("%s: GonkBufferQueue has been abandoned", caller); - return NO_INIT; - } - - const int maxBufferCount = mCore->getMaxBufferCountLocked(async); - if (async && mCore->mOverrideMaxBufferCount) { - // FIXME: Some drivers are manually setting the buffer count - // (which they shouldn't), so we do this extra test here to - // handle that case. This is TEMPORARY until we get this fixed. - if (mCore->mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("%s: async mode is invalid with buffer count override", - caller); - return BAD_VALUE; - } - } - - // Free up any buffers that are in slots beyond the max buffer count - //for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - // assert(mSlots[s].mBufferState == GonkBufferSlot::FREE); - // if (mSlots[s].mGraphicBuffer != NULL) { - // mCore->freeBufferLocked(s); - // *returnFlags |= RELEASE_ALL_BUFFERS; - // } - //} - - // Look for a free buffer to give to the client - *found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - int dequeuedCount = 0; - int acquiredCount = 0; - for (int s = 0; s < maxBufferCount; ++s) { - switch (mSlots[s].mBufferState) { - case GonkBufferSlot::DEQUEUED: - ++dequeuedCount; - break; - case GonkBufferSlot::ACQUIRED: - ++acquiredCount; - break; - case GonkBufferSlot::FREE: - // We return the oldest of the free buffers to avoid - // stalling the producer if possible, since the consumer - // may still have pending reads of in-flight buffers - if (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) { - *found = s; - } - break; - default: - break; - } - } - - // Producers are not allowed to dequeue more than one buffer if they - // did not set a buffer count - if (!mCore->mOverrideMaxBufferCount && dequeuedCount) { - ALOGE("%s: can't dequeue multiple buffers without setting the " - "buffer count", caller); - return INVALID_OPERATION; - } - - // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the min undequeued - // buffers check below - if (mCore->mBufferHasBeenQueued) { - // Make sure the producer is not trying to dequeue more buffers - // than allowed - const int newUndequeuedCount = - maxBufferCount - (dequeuedCount + 1); - const int minUndequeuedCount = - mCore->getMinUndequeuedBufferCountLocked(async); - if (newUndequeuedCount < minUndequeuedCount) { - ALOGE("%s: min undequeued buffer count (%d) exceeded " - "(dequeued=%d undequeued=%d)", - caller, minUndequeuedCount, - dequeuedCount, newUndequeuedCount); - return INVALID_OPERATION; - } - } - - // If we disconnect and reconnect quickly, we can be in a state where - // our slots are empty but we have many buffers in the queue. This can - // cause us to run out of memory if we outrun the consumer. Wait here if - // it looks like we have too many buffers queued up. - bool tooManyBuffers = mCore->mQueue.size() - > static_cast<size_t>(maxBufferCount); - if (tooManyBuffers) { - ALOGV("%s: queue size is %zu, waiting", caller, - mCore->mQueue.size()); - } - - // If no buffer is found, or if the queue has too many buffers - // outstanding, wait for a buffer to be acquired or released, or for the - // max buffer count to change. - tryAgain = (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) || - tooManyBuffers; - if (tryAgain) { - // Return an error if we're in non-blocking mode (producer and - // consumer are controlled by the application). - // However, the consumer is allowed to briefly acquire an extra - // buffer (which could cause us to have to wait here), which is - // okay, since it is only used to implement an atomic acquire + - // release (e.g., in GLConsumer::updateTexImage()) - if (mCore->mDequeueBufferCannotBlock && - (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { - return WOULD_BLOCK; - } - mCore->mDequeueCondition.wait(mCore->mMutex); - } - } // while (tryAgain) - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::dequeueBuffer(int *outSlot, - sp<android::Fence> *outFence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { - ATRACE_CALL(); - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mConsumerName = mCore->mConsumerName; - } // Autolock scope - - ALOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x", - async ? "true" : "false", width, height, format, usage); - - if ((width && !height) || (!width && height)) { - ALOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); - return BAD_VALUE; - } - - status_t returnFlags = NO_ERROR; - // Reset slot - *outSlot = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - - bool attachedByConsumer = false; - - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (format == 0) { - format = mCore->mDefaultBufferFormat; - } - - // Enable the usage bits the consumer requested - usage |= mCore->mConsumerUsageBits; - - int found; - status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, - &found, &returnFlags); - if (status != NO_ERROR) { - return status; - } - - // This should not happen - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; - } - - *outSlot = found; - - attachedByConsumer = mSlots[found].mAttachedByConsumer; - - const bool useDefaultSize = !width && !height; - if (useDefaultSize) { - width = mCore->mDefaultWidth; - height = mCore->mDefaultHeight; - } - - mSlots[found].mBufferState = GonkBufferSlot::DEQUEUED; - - const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); - if ((buffer == NULL) || - (static_cast<uint32_t>(buffer->width) != width) || - (static_cast<uint32_t>(buffer->height) != height) || - (static_cast<uint32_t>(buffer->format) != format) || - ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) - { - mSlots[found].mAcquireCalled = false; - mSlots[found].mGraphicBuffer = NULL; - mSlots[found].mRequestBufferCalled = false; - mSlots[found].mFence = Fence::NO_FENCE; - - if (mSlots[found].mTextureClient) { - mSlots[found].mTextureClient->ClearRecycleCallback(); - // release TextureClient in ImageBridge thread - RefPtr<TextureClientReleaseTask> task = - MakeAndAddRef<TextureClientReleaseTask>(mSlots[found].mTextureClient); - mSlots[found].mTextureClient = NULL; - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget()); - } - - returnFlags |= BUFFER_NEEDS_REALLOCATION; - } - - if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { - ALOGE("dequeueBuffer: about to return a NULL fence - " - "slot=%d w=%d h=%d format=%u", - found, buffer->width, buffer->height, buffer->format); - } - - *outFence = mSlots[found].mFence; - mSlots[found].mFence = Fence::NO_FENCE; - } // Autolock scope - - if (returnFlags & BUFFER_NEEDS_REALLOCATION) { - RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton(); - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format, - gfx::BackendType::NONE, - usage, allocator); - if (!texData) { - ALOGE("dequeueBuffer: failed to alloc gralloc buffer"); - return -ENOMEM; - } - RefPtr<TextureClient> textureClient = TextureClient::CreateWithData( - texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator); - - sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer(); - - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - mSlots[*outSlot].mFrameNumber = UINT32_MAX; - mSlots[*outSlot].mGraphicBuffer = graphicBuffer; - mSlots[*outSlot].mTextureClient = textureClient; - } // Autolock scope - } - - if (attachedByConsumer) { - returnFlags |= BUFFER_NEEDS_REALLOCATION; - } - - ALOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", - *outSlot, - mSlots[*outSlot].mFrameNumber, - mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); - - return returnFlags; -} - -status_t GonkBufferQueueProducer::detachBuffer(int slot) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(slot); - ALOGV("detachBuffer(P): slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("detachBuffer(P): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("detachBuffer(P): slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("detachBuffer(P): slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } else if (!mSlots[slot].mRequestBufferCalled) { - ALOGE("detachBuffer(P): buffer in slot %d has not been requested", - slot); - return BAD_VALUE; - } - - mCore->freeBufferLocked(slot); - mCore->mDequeueCondition.broadcast(); - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, - sp<Fence>* outFence) { - ATRACE_CALL(); - - if (outBuffer == NULL) { - ALOGE("detachNextBuffer: outBuffer must not be NULL"); - return BAD_VALUE; - } else if (outFence == NULL) { - ALOGE("detachNextBuffer: outFence must not be NULL"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - ALOGE("detachNextBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - // Find the oldest valid slot - int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (mSlots[s].mBufferState == GonkBufferSlot::FREE && - mSlots[s].mGraphicBuffer != NULL) { - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT || - mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { - found = s; - } - } - } - - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - return NO_MEMORY; - } - - ALOGV("detachNextBuffer detached slot %d", found); - - *outBuffer = mSlots[found].mGraphicBuffer; - *outFence = mSlots[found].mFence; - mCore->freeBufferLocked(found); - - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::attachBuffer(int* outSlot, - const sp<android::GraphicBuffer>& buffer) { - ATRACE_CALL(); - - if (outSlot == NULL) { - ALOGE("attachBuffer(P): outSlot must not be NULL"); - return BAD_VALUE; - } else if (buffer == NULL) { - ALOGE("attachBuffer(P): cannot attach NULL buffer"); - return BAD_VALUE; - } - - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - status_t returnFlags = NO_ERROR; - int found; - // TODO: Should we provide an async flag to attachBuffer? It seems - // unlikely that buffers which we are attaching to a GonkBufferQueue will - // be asynchronous (droppable), but it may not be impossible. - status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, - &found, &returnFlags); - if (status != NO_ERROR) { - return status; - } - - // This should not happen - if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) { - ALOGE("attachBuffer(P): no available buffer slots"); - return -EBUSY; - } - - *outSlot = found; - ATRACE_BUFFER_INDEX(*outSlot); - ALOGV("attachBuffer(P): returning slot %d flags=%#x", - *outSlot, returnFlags); - - mSlots[*outSlot].mGraphicBuffer = buffer; - mSlots[*outSlot].mBufferState = GonkBufferSlot::DEQUEUED; - mSlots[*outSlot].mFence = Fence::NO_FENCE; - mSlots[*outSlot].mRequestBufferCalled = true; - - return returnFlags; -} - -status_t GonkBufferQueueProducer::setSynchronousMode(bool enabled) { - ALOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("setSynchronousMode: BufferQueue has been abandoned!"); - return NO_INIT; - } - - if (mSynchronousMode != enabled) { - mSynchronousMode = enabled; - mCore->mDequeueCondition.broadcast(); - } - return OK; -} - -status_t GonkBufferQueueProducer::queueBuffer(int slot, - const QueueBufferInput &input, QueueBufferOutput *output) { - ATRACE_CALL(); - - int64_t timestamp; - bool isAutoTimestamp; - Rect crop; - int scalingMode; - uint32_t transform; - uint32_t stickyTransform; - bool async; - sp<Fence> fence; - input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, - &async, &fence, &stickyTransform); - - if (fence == NULL) { - ALOGE("queueBuffer: fence is NULL"); - // Temporary workaround for b/17946343: soldier-on instead of returning an error. This - // prevents the client from dying, at the risk of visible corruption due to hwcomposer - // reading the buffer before the producer is done rendering it. Unless the buffer is the - // last frame of an animation, the corruption will be transient. - fence = Fence::NO_FENCE; - // return BAD_VALUE; - } - - switch (scalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: - case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: - break; - default: - ALOGE("queueBuffer: unknown scaling mode %d", scalingMode); - return BAD_VALUE; - } - - GonkBufferItem item; - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("queueBuffer: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - const int maxBufferCount = mCore->getMaxBufferCountLocked(async); - if (async && mCore->mOverrideMaxBufferCount) { - // FIXME: Some drivers are manually setting the buffer count - // (which they shouldn't), so we do this extra test here to - // handle that case. This is TEMPORARY until we get this fixed. - if (mCore->mOverrideMaxBufferCount < maxBufferCount) { - ALOGE("queueBuffer: async mode is invalid with " - "buffer count override"); - return BAD_VALUE; - } - } - - if (slot < 0 || slot >= maxBufferCount) { - ALOGE("queueBuffer: slot index %d out of range [0, %d)", - slot, maxBufferCount); - return BAD_VALUE; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("queueBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return BAD_VALUE; - } else if (!mSlots[slot].mRequestBufferCalled) { - ALOGE("queueBuffer: slot %d was queued without requesting " - "a buffer", slot); - return BAD_VALUE; - } - - ALOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 - " crop=[%d,%d,%d,%d] transform=%#x scale=%s", - slot, mCore->mFrameCounter + 1, timestamp, - crop.left, crop.top, crop.right, crop.bottom, - transform, GonkBufferItem::scalingModeName(scalingMode)); - - const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); - Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); - Rect croppedRect; - crop.intersect(bufferRect, &croppedRect); - if (croppedRect != crop) { - ALOGE("queueBuffer: crop rect is not contained within the " - "buffer in slot %d", slot); - return BAD_VALUE; - } - - mSlots[slot].mFence = fence; - mSlots[slot].mBufferState = GonkBufferSlot::QUEUED; - ++mCore->mFrameCounter; - mSlots[slot].mFrameNumber = mCore->mFrameCounter; - - item.mAcquireCalled = mSlots[slot].mAcquireCalled; - item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; - item.mCrop = crop; - item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; - item.mTransformToDisplayInverse = - bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); - item.mScalingMode = scalingMode; - item.mTimestamp = timestamp; - item.mIsAutoTimestamp = isAutoTimestamp; - item.mFrameNumber = mCore->mFrameCounter; - item.mSlot = slot; - item.mFence = fence; - item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; - - mStickyTransform = stickyTransform; - - if (mCore->mQueue.empty()) { - // When the queue is empty, we can ignore mDequeueBufferCannotBlock - // and simply queue this buffer - mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; - } else { - // When the queue is not empty, we need to look at the front buffer - // state to see if we need to replace it - GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); - if (front->mIsDroppable || !mSynchronousMode) { - // If the front queued buffer is still being tracked, we first - // mark it as freed - if (mCore->stillTracking(front)) { - mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE; - // Reset the frame number of the freed buffer so that it is - // the first in line to be dequeued again - mSlots[front->mSlot].mFrameNumber = 0; - } - // Overwrite the droppable buffer with the incoming one - *front = item; - listener = mCore->mConsumerListener; - } else { - mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; - } - } - - mCore->mBufferHasBeenQueued = true; - mCore->mDequeueCondition.broadcast(); - - output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); - - item.mGraphicBuffer.clear(); - item.mSlot = GonkBufferItem::INVALID_BUFFER_SLOT; - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { -#if ANDROID_VERSION == 21 - listener->onFrameAvailable(); -#else - listener->onFrameAvailable(reinterpret_cast<::android::BufferItem&>(item)); -#endif - } - - return NO_ERROR; -} - -void GonkBufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { - ATRACE_CALL(); - ALOGV("cancelBuffer: slot %d", slot); - Mutex::Autolock lock(mCore->mMutex); - - if (mCore->mIsAbandoned) { - ALOGE("cancelBuffer: GonkBufferQueue has been abandoned"); - return; - } - - if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) { - ALOGE("cancelBuffer: slot index %d out of range [0, %d)", - slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS); - return; - } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { - ALOGE("cancelBuffer: slot %d is not owned by the producer " - "(state = %d)", slot, mSlots[slot].mBufferState); - return; - } else if (fence == NULL) { - ALOGE("cancelBuffer: fence is NULL"); - return; - } - - mSlots[slot].mBufferState = GonkBufferSlot::FREE; - mSlots[slot].mFrameNumber = 0; - mSlots[slot].mFence = fence; - mCore->mDequeueCondition.broadcast(); -} - -int GonkBufferQueueProducer::query(int what, int *outValue) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - - if (outValue == NULL) { - ALOGE("query: outValue was NULL"); - return BAD_VALUE; - } - - if (mCore->mIsAbandoned) { - ALOGE("query: GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - int value; - switch (what) { - case NATIVE_WINDOW_WIDTH: - value = mCore->mDefaultWidth; - break; - case NATIVE_WINDOW_HEIGHT: - value = mCore->mDefaultHeight; - break; - case NATIVE_WINDOW_FORMAT: - value = mCore->mDefaultBufferFormat; - break; - case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = mCore->getMinUndequeuedBufferCountLocked(false); - break; - case NATIVE_WINDOW_STICKY_TRANSFORM: - value = static_cast<int>(mStickyTransform); - break; - case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: - value = (mCore->mQueue.size() > 1); - break; - case NATIVE_WINDOW_CONSUMER_USAGE_BITS: - value = mCore->mConsumerUsageBits; - break; - default: - return BAD_VALUE; - } - - ALOGV("query: %d? %d", what, value); - *outValue = value; - return NO_ERROR; -} - -status_t GonkBufferQueueProducer::connect(const sp<IProducerListener>& listener, - int api, bool producerControlledByApp, QueueBufferOutput *output) { - ATRACE_CALL(); - Mutex::Autolock lock(mCore->mMutex); - mConsumerName = mCore->mConsumerName; - ALOGV("connect(P): api=%d producerControlledByApp=%s", api, - producerControlledByApp ? "true" : "false"); - - if (mCore->mIsAbandoned) { - ALOGE("connect(P): GonkBufferQueue has been abandoned"); - return NO_INIT; - } - - if (mCore->mConsumerListener == NULL) { - ALOGE("connect(P): GonkBufferQueue has no consumer"); - return NO_INIT; - } - - if (output == NULL) { - ALOGE("connect(P): output was NULL"); - return BAD_VALUE; - } - - if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) { - ALOGE("connect(P): already connected (cur=%d req=%d)", mCore->mConnectedApi, - api); - return BAD_VALUE; - } - - int status = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - mCore->mConnectedApi = api; - output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, - mCore->mTransformHint, mCore->mQueue.size()); - - // Set up a death notification so that we can disconnect - // automatically if the remote producer dies - if (listener != NULL && - listener->asBinder()->remoteBinder() != NULL) { - status = listener->asBinder()->linkToDeath( - static_cast<IBinder::DeathRecipient*>(this)); - if (status != NO_ERROR) { - ALOGE("connect(P): linkToDeath failed: %s (%d)", - strerror(-status), status); - } - } - mCore->mConnectedProducerListener = listener; - break; - default: - ALOGE("connect(P): unknown API %d", api); - status = BAD_VALUE; - break; - } - - mCore->mBufferHasBeenQueued = false; - mCore->mDequeueBufferCannotBlock = - mCore->mConsumerControlledByApp && producerControlledByApp; - - return status; -} - -status_t GonkBufferQueueProducer::disconnect(int api) { - ATRACE_CALL(); - ALOGV("disconnect(P): api %d", api); - - int status = NO_ERROR; - sp<IConsumerListener> listener; - { // Autolock scope - Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); - - if (mCore->mIsAbandoned) { - // It's not really an error to disconnect after the surface has - // been abandoned; it should just be a no-op. - return NO_ERROR; - } - - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mCore->mConnectedApi == api) { - mCore->freeAllBuffersLocked(); - mCore->mConnectedApi = GonkBufferQueueCore::NO_CONNECTED_API; - mCore->mSidebandStream.clear(); - mCore->mDequeueCondition.broadcast(); - listener = mCore->mConsumerListener; - } else { - ALOGE("disconnect(P): connected to another API " - "(cur=%d req=%d)", mCore->mConnectedApi, api); - status = BAD_VALUE; - } - break; - default: - ALOGE("disconnect(P): unknown API %d", api); - status = BAD_VALUE; - break; - } - } // Autolock scope - - // Call back without lock held - if (listener != NULL) { - listener->onBuffersReleased(); - } - - return status; -} - -status_t GonkBufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { - return INVALID_OPERATION; -} - -void GonkBufferQueueProducer::allocateBuffers(bool async, uint32_t width, - uint32_t height, uint32_t format, uint32_t usage) { - ALOGE("allocateBuffers: no op"); -} - -void GonkBufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { - // If we're here, it means that a producer we were connected to died. - // We're guaranteed that we are still connected to it because we remove - // this callback upon disconnect. It's therefore safe to read mConnectedApi - // without synchronization here. - int api = mCore->mConnectedApi; - disconnect(api); -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h deleted file mode 100644 index a1a22416a..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H -#define NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H - -#include "GonkBufferQueueDefs.h" -#include <gui/IGraphicBufferProducer.h> - -namespace android { - -class GonkBufferQueueProducer : public BnGraphicBufferProducer, - private IBinder::DeathRecipient { -public: - friend class GonkBufferQueue; // Needed to access binderDied - - GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core); - virtual ~GonkBufferQueueProducer(); - - // requestBuffer returns the GraphicBuffer for slot N. - // - // In normal operation, this is called the first time slot N is returned - // by dequeueBuffer. It must be called again if dequeueBuffer returns - // flags indicating that previously-returned buffers are no longer valid. - virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); - - // setBufferCount updates the number of available buffer slots. If this - // method succeeds, buffer slots will be both unallocated and owned by - // the GonkBufferQueue object (i.e. they are not owned by the producer or - // consumer). - // - // This will fail if the producer has dequeued any buffers, or if - // bufferCount is invalid. bufferCount must generally be a value - // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS - // (inclusive). It may also be set to zero (the default) to indicate - // that the producer does not wish to set a value. The minimum value - // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - // ...). - // - // This may only be called by the producer. The consumer will be told - // to discard buffers through the onBuffersReleased callback. - virtual status_t setBufferCount(int bufferCount); - - // dequeueBuffer gets the next buffer slot index for the producer to use. - // If a buffer slot is available then that slot index is written to the - // location pointed to by the buf argument and a status of OK is returned. - // If no slot is available then a status of -EBUSY is returned and buf is - // unmodified. - // - // The outFence parameter will be updated to hold the fence associated with - // the buffer. The contents of the buffer must not be overwritten until the - // fence signals. If the fence is Fence::NO_FENCE, the buffer may be - // written immediately. - // - // The width and height parameters must be no greater than the minimum of - // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). - // An error due to invalid dimensions might not be reported until - // updateTexImage() is called. If width and height are both zero, the - // default values specified by setDefaultBufferSize() are used instead. - // - // The pixel formats are enumerated in graphics.h, e.g. - // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format - // will be used. - // - // The usage argument specifies gralloc buffer usage flags. The values - // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These - // will be merged with the usage flags specified by setConsumerUsageBits. - // - // The return value may be a negative error value or a non-negative - // collection of flags. If the flags are set, the return values are - // valid, but additional actions must be performed. - // - // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the - // producer must discard cached GraphicBuffer references for the slot - // returned in buf. - // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer - // must discard cached GraphicBuffer references for all slots. - // - // In both cases, the producer will need to call requestBuffer to get a - // GraphicBuffer handle for the returned slot. - virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence, bool async, - uint32_t width, uint32_t height, uint32_t format, uint32_t usage); - - // See IGraphicBufferProducer::detachBuffer - virtual status_t detachBuffer(int slot); - - // See IGraphicBufferProducer::detachNextBuffer - virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, - sp<Fence>* outFence); - - // See IGraphicBufferProducer::attachBuffer - virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer); - - // queueBuffer returns a filled buffer to the GonkBufferQueue. - // - // Additional data is provided in the QueueBufferInput struct. Notably, - // a timestamp must be provided for the buffer. The timestamp is in - // nanoseconds, and must be monotonically increasing. Its other semantics - // (zero point, etc) are producer-specific and should be documented by the - // producer. - // - // The caller may provide a fence that signals when all rendering - // operations have completed. Alternatively, NO_FENCE may be used, - // indicating that the buffer is ready immediately. - // - // Some values are returned in the output struct: the current settings - // for default width and height, the current transform hint, and the - // number of queued buffers. - virtual status_t queueBuffer(int slot, - const QueueBufferInput& input, QueueBufferOutput* output); - - // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't - // queue it for use by the consumer. - // - // The buffer will not be overwritten until the fence signals. The fence - // will usually be the one obtained from dequeueBuffer. - virtual void cancelBuffer(int slot, const sp<Fence>& fence); - - // Query native window attributes. The "what" values are enumerated in - // window.h (e.g. NATIVE_WINDOW_FORMAT). - virtual int query(int what, int* outValue); - - // connect attempts to connect a producer API to the GonkBufferQueue. This - // must be called before any other IGraphicBufferProducer methods are - // called except for getAllocator. A consumer must already be connected. - // - // This method will fail if connect was previously called on the - // GonkBufferQueue and no corresponding disconnect call was made (i.e. if - // it's still connected to a producer). - // - // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU). - virtual status_t connect(const sp<IProducerListener>& listener, - int api, bool producerControlledByApp, QueueBufferOutput* output); - - // disconnect attempts to disconnect a producer API from the GonkBufferQueue. - // Calling this method will cause any subsequent calls to other - // IGraphicBufferProducer methods to fail except for getAllocator and connect. - // Successfully calling connect after this will allow the other methods to - // succeed again. - // - // This method will fail if the the GonkBufferQueue is not currently - // connected to the specified producer API. - virtual status_t disconnect(int api); - - // Attaches a sideband buffer stream to the IGraphicBufferProducer. - // - // A sideband stream is a device-specific mechanism for passing buffers - // from the producer to the consumer without using dequeueBuffer/ - // queueBuffer. If a sideband stream is present, the consumer can choose - // whether to acquire buffers from the sideband stream or from the queued - // buffers. - // - // Passing NULL or a different stream handle will detach the previous - // handle if any. - virtual status_t setSidebandStream(const sp<NativeHandle>& stream); - - // See IGraphicBufferProducer::allocateBuffers - virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, - uint32_t format, uint32_t usage); - - // setSynchronousMode sets whether dequeueBuffer is synchronous or - // asynchronous. In synchronous mode, dequeueBuffer blocks until - // a buffer is available, the currently bound buffer can be dequeued and - // queued buffers will be acquired in order. In asynchronous mode, - // a queued buffer may be replaced by a subsequently queued buffer. - // - // The default mode is synchronous. - // This should be called only during initialization. - virtual status_t setSynchronousMode(bool enabled); - -private: - // This is required by the IBinder::DeathRecipient interface - virtual void binderDied(const wp<IBinder>& who); - - // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may - // block if there are no available slots and we are not in non-blocking - // mode (producer and consumer controlled by the application). If it blocks, - // it will release mCore->mMutex while blocked so that other operations on - // the GonkBufferQueue may succeed. - status_t waitForFreeSlotThenRelock(const char* caller, bool async, - int* found, status_t* returnFlags) const; - - sp<GonkBufferQueueCore> mCore; - - // This references mCore->mSlots. Lock mCore->mMutex while accessing. - GonkBufferQueueDefs::SlotsType& mSlots; - - // This is a cached copy of the name stored in the GonkBufferQueueCore. - // It's updated during connect and dequeueBuffer (which should catch - // most updates). - String8 mConsumerName; - - // mSynchronousMode whether we're in synchronous mode or not - bool mSynchronousMode; - - uint32_t mStickyTransform; - -}; // class GonkBufferQueueProducer - -} // namespace android - -#endif diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp deleted file mode 100644 index 9e4a424a9..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GonkBufferSlot.h" - -namespace android { - -const char* GonkBufferSlot::bufferStateName(BufferState state) { - switch (state) { - case GonkBufferSlot::DEQUEUED: return "DEQUEUED"; - case GonkBufferSlot::QUEUED: return "QUEUED"; - case GonkBufferSlot::FREE: return "FREE"; - case GonkBufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; - } -} - -} // namespace android diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h deleted file mode 100644 index 759bb7b23..000000000 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * Copyright (C) 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NATIVEWINDOW_GONKBUFFERSLOT_LL_H -#define NATIVEWINDOW_GONKBUFFERSLOT_LL_H - -#include <ui/Fence.h> -#include <ui/GraphicBuffer.h> - -#include <utils/StrongPointer.h> - -#include "mozilla/layers/TextureClient.h" - -namespace android { - -struct GonkBufferSlot { - typedef mozilla::layers::TextureClient TextureClient; - - GonkBufferSlot() - : mBufferState(GonkBufferSlot::FREE), - mRequestBufferCalled(false), - mFrameNumber(0), - mAcquireCalled(false), - mNeedsCleanupOnRelease(false), - mAttachedByConsumer(false) { - } - - // mGraphicBuffer points to the buffer allocated for this slot or is NULL - // if no buffer has been allocated. - sp<GraphicBuffer> mGraphicBuffer; - - // BufferState represents the different states in which a buffer slot - // can be. All slots are initially FREE. - enum BufferState { - // FREE indicates that the buffer is available to be dequeued - // by the producer. The buffer may be in use by the consumer for - // a finite time, so the buffer must not be modified until the - // associated fence is signaled. - // - // The slot is "owned" by BufferQueue. It transitions to DEQUEUED - // when dequeueBuffer is called. - FREE = 0, - - // DEQUEUED indicates that the buffer has been dequeued by the - // producer, but has not yet been queued or canceled. The - // producer may modify the buffer's contents as soon as the - // associated ready fence is signaled. - // - // The slot is "owned" by the producer. It can transition to - // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer). - DEQUEUED = 1, - - // QUEUED indicates that the buffer has been filled by the - // producer and queued for use by the consumer. The buffer - // contents may continue to be modified for a finite time, so - // the contents must not be accessed until the associated fence - // is signaled. - // - // The slot is "owned" by BufferQueue. It can transition to - // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is - // queued in asynchronous mode). - QUEUED = 2, - - // ACQUIRED indicates that the buffer has been acquired by the - // consumer. As with QUEUED, the contents must not be accessed - // by the consumer until the fence is signaled. - // - // The slot is "owned" by the consumer. It transitions to FREE - // when releaseBuffer is called. - ACQUIRED = 3 - }; - - static const char* bufferStateName(BufferState state); - - // mBufferState is the current state of this buffer slot. - BufferState mBufferState; - - // mRequestBufferCalled is used for validating that the producer did - // call requestBuffer() when told to do so. Technically this is not - // needed but useful for debugging and catching producer bugs. - bool mRequestBufferCalled; - - // mFrameNumber is the number of the queued frame for this slot. This - // is used to dequeue buffers in LRU order (useful because buffers - // may be released before their release fence is signaled). - uint64_t mFrameNumber; - - // mFence is a fence which will signal when work initiated by the - // previous owner of the buffer is finished. When the buffer is FREE, - // the fence indicates when the consumer has finished reading - // from the buffer, or when the producer has finished writing if it - // called cancelBuffer after queueing some writes. When the buffer is - // QUEUED, it indicates when the producer has finished filling the - // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been - // passed to the consumer or producer along with ownership of the - // buffer, and mFence is set to NO_FENCE. - sp<Fence> mFence; - - // Indicates whether this buffer has been seen by a consumer yet - bool mAcquireCalled; - - // Indicates whether this buffer needs to be cleaned up by the - // consumer. This is set when a buffer in ACQUIRED state is freed. - // It causes releaseBuffer to return STALE_BUFFER_SLOT. - bool mNeedsCleanupOnRelease; - - // Indicates whether the buffer was attached on the consumer side. - // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued - // to prevent the producer from using a stale cached buffer. - bool mAttachedByConsumer; - - // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer. - RefPtr<TextureClient> mTextureClient; -}; - -} // namespace android - -#endif |