diff options
Diffstat (limited to 'libs/gui')
-rw-r--r-- | libs/gui/Android.mk | 16 | ||||
-rw-r--r-- | libs/gui/BufferQueue.cpp | 100 | ||||
-rw-r--r-- | libs/gui/ConsumerBase.cpp | 206 | ||||
-rw-r--r-- | libs/gui/CpuConsumer.cpp | 242 | ||||
-rw-r--r-- | libs/gui/ISensorServer.cpp | 4 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 165 | ||||
-rw-r--r-- | libs/gui/ISurfaceTexture.cpp | 99 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 39 | ||||
-rw-r--r-- | libs/gui/Sensor.cpp | 18 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 18 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 276 | ||||
-rw-r--r-- | libs/gui/SurfaceTexture.cpp | 302 | ||||
-rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 209 | ||||
-rw-r--r-- | libs/gui/tests/Android.mk | 6 | ||||
-rw-r--r-- | libs/gui/tests/CpuConsumer_test.cpp | 503 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTextureClient_test.cpp | 182 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTexture_test.cpp | 112 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 13 |
18 files changed, 1792 insertions, 718 deletions
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 8224847..3aa3a50 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ BitTube.cpp \ BufferQueue.cpp \ + ConsumerBase.cpp \ DisplayEventReceiver.cpp \ IDisplayEventConnection.cpp \ ISensorEventConnection.cpp \ @@ -21,17 +22,17 @@ LOCAL_SRC_FILES:= \ LayerState.cpp \ Surface.cpp \ SurfaceComposerClient.cpp \ - DummyConsumer.cpp + DummyConsumer.cpp \ + CpuConsumer.cpp LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ libbinder \ - libhardware \ - libhardware_legacy \ - libui \ + libcutils \ libEGL \ libGLESv2 \ + libsync \ + libui \ + libutils \ LOCAL_MODULE:= libgui @@ -42,6 +43,9 @@ endif ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) LOCAL_CFLAGS += -DUSE_FENCE_SYNC endif +ifeq ($(TARGET_BOARD_PLATFORM), exynos5) + LOCAL_CFLAGS += -DUSE_FENCE_SYNC +endif ifneq ($(filter generic%,$(TARGET_DEVICE)),) # Emulator build LOCAL_CFLAGS += -DUSE_FENCE_SYNC diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index a0774cf..697635b 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -81,10 +81,10 @@ static const char* scalingModeName(int scalingMode) { } } -BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : +BufferQueue::BufferQueue(bool allowSynchronousMode, int bufferCount, + const sp<IGraphicBufferAlloc>& allocator) : mDefaultWidth(1), mDefaultHeight(1), - mPixelFormat(PIXEL_FORMAT_RGBA_8888), mMinUndequeuedBuffers(bufferCount), mMinAsyncBufferSlots(bufferCount + 1), mMinSyncBufferSlots(bufferCount), @@ -97,7 +97,7 @@ BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : mAbandoned(false), mFrameCounter(0), mBufferHasBeenQueued(false), - mDefaultBufferFormat(0), + mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), mConsumerUsageBits(0), mTransformHint(0) { @@ -105,10 +105,14 @@ BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); ST_LOGV("BufferQueue"); - sp<ISurfaceComposer> composer(ComposerService::getComposerService()); - mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); - if (mGraphicBufferAlloc == 0) { - ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); + if (allocator == NULL) { + sp<ISurfaceComposer> composer(ComposerService::getComposerService()); + mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); + if (mGraphicBufferAlloc == 0) { + ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); + } + } else { + mGraphicBufferAlloc = allocator; } } @@ -120,7 +124,8 @@ status_t BufferQueue::setBufferCountServerLocked(int bufferCount) { if (bufferCount > NUM_BUFFER_SLOTS) return BAD_VALUE; - // special-case, nothing to do + mServerBufferCount = bufferCount; + if (bufferCount == mBufferCount) return OK; @@ -128,7 +133,6 @@ status_t BufferQueue::setBufferCountServerLocked(int bufferCount) { bufferCount >= mBufferCount) { // easy, we just have more buffers mBufferCount = bufferCount; - mServerBufferCount = bufferCount; mDequeueCondition.broadcast(); } else { // we're here because we're either @@ -145,7 +149,6 @@ status_t BufferQueue::setBufferCountServerLocked(int bufferCount) { // own one. the actual resizing will happen during the next // dequeueBuffer. - mServerBufferCount = bufferCount; mDequeueCondition.broadcast(); } return OK; @@ -255,7 +258,7 @@ int BufferQueue::query(int what, int* outValue) value = mDefaultHeight; break; case NATIVE_WINDOW_FORMAT: - value = mPixelFormat; + value = mDefaultBufferFormat; break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: value = mSynchronousMode ? @@ -289,8 +292,8 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { return NO_ERROR; } -status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, - uint32_t format, uint32_t usage) { +status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { ATRACE_CALL(); ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); @@ -301,7 +304,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, status_t returnFlags(OK); EGLDisplay dpy = EGL_NO_DISPLAY; - EGLSyncKHR fence = EGL_NO_SYNC_KHR; + EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; { // Scope for the lock Mutex::Autolock lock(mMutex); @@ -313,7 +316,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, usage |= mConsumerUsageBits; int found = -1; - int foundSync = -1; int dequeuedCount = 0; bool tryAgain = true; while (tryAgain) { @@ -364,7 +366,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, // look for a free buffer to give to the client found = INVALID_BUFFER_SLOT; - foundSync = INVALID_BUFFER_SLOT; dequeuedCount = 0; for (int i = 0; i < mBufferCount; i++) { const int state = mSlots[i].mBufferState; @@ -388,7 +389,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, bool isOlder = mSlots[i].mFrameNumber < mSlots[found].mFrameNumber; if (found < 0 || isOlder) { - foundSync = i; found = i; } } @@ -445,12 +445,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, h = mDefaultHeight; } - const bool updateFormat = (format != 0); - if (!updateFormat) { - // keep the current (or default) format - format = mPixelFormat; - } - // buffer is now in DEQUEUED (but can also be current at the same time, // if we're in synchronous mode) mSlots[buf].mBufferState = BufferSlot::DEQUEUED; @@ -471,26 +465,26 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, "failed"); return error; } - if (updateFormat) { - mPixelFormat = format; - } mSlots[buf].mAcquireCalled = false; mSlots[buf].mGraphicBuffer = graphicBuffer; mSlots[buf].mRequestBufferCalled = false; - mSlots[buf].mFence = EGL_NO_SYNC_KHR; + mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; + mSlots[buf].mFence.clear(); mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } dpy = mSlots[buf].mEglDisplay; - fence = mSlots[buf].mFence; - mSlots[buf].mFence = EGL_NO_SYNC_KHR; + eglFence = mSlots[buf].mEglFence; + outFence = mSlots[buf].mFence; + mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; + mSlots[buf].mFence.clear(); } // end lock scope - if (fence != EGL_NO_SYNC_KHR) { - EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); + if (eglFence != EGL_NO_SYNC_KHR) { + EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. @@ -499,7 +493,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { ST_LOGE("dequeueBuffer: timeout waiting for fence"); } - eglDestroySyncKHR(dpy, fence); + eglDestroySyncKHR(dpy, eglFence); } ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, @@ -549,8 +543,9 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; + sp<Fence> fence; - input.deflate(×tamp, &crop, &scalingMode, &transform); + input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " "scale=%s", @@ -617,6 +612,7 @@ status_t BufferQueue::queueBuffer(int buf, mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; mSlots[buf].mTransform = transform; + mSlots[buf].mFence = fence; switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: @@ -650,7 +646,7 @@ status_t BufferQueue::queueBuffer(int buf, return OK; } -void BufferQueue::cancelBuffer(int buf) { +void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) { ATRACE_CALL(); ST_LOGV("cancelBuffer: slot=%d", buf); Mutex::Autolock lock(mMutex); @@ -671,6 +667,7 @@ void BufferQueue::cancelBuffer(int buf) { } mSlots[buf].mBufferState = BufferSlot::FREE; mSlots[buf].mFrameNumber = 0; + mSlots[buf].mFence = fence; mDequeueCondition.broadcast(); } @@ -783,9 +780,9 @@ void BufferQueue::dump(String8& result, const char* prefix, snprintf(buffer, SIZE, "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " - "mPixelFormat=%d, FIFO(%d)={%s}\n", + "default-format=%d, FIFO(%d)={%s}\n", prefix, mBufferCount, mSynchronousMode, mDefaultWidth, - mDefaultHeight, mPixelFormat, fifoSize, fifo.string()); + mDefaultHeight, mDefaultBufferFormat, fifoSize, fifo.string()); result.append(buffer); @@ -827,20 +824,22 @@ void BufferQueue::dump(String8& result, const char* prefix, } } -void BufferQueue::freeBufferLocked(int i) { - mSlots[i].mGraphicBuffer = 0; - if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { - mSlots[i].mNeedsCleanupOnRelease = true; +void BufferQueue::freeBufferLocked(int slot) { + ST_LOGV("freeBufferLocked: slot=%d", slot); + mSlots[slot].mGraphicBuffer = 0; + if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { + mSlots[slot].mNeedsCleanupOnRelease = true; } - mSlots[i].mBufferState = BufferSlot::FREE; - mSlots[i].mFrameNumber = 0; - mSlots[i].mAcquireCalled = false; + mSlots[slot].mBufferState = BufferSlot::FREE; + mSlots[slot].mFrameNumber = 0; + mSlots[slot].mAcquireCalled = false; // destroy fence as BufferQueue now takes ownership - if (mSlots[i].mFence != EGL_NO_SYNC_KHR) { - eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence); - mSlots[i].mFence = EGL_NO_SYNC_KHR; + if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { + eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); + mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; } + mSlots[slot].mFence.clear(); } void BufferQueue::freeAllBuffersLocked() { @@ -876,9 +875,13 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) { buffer->mFrameNumber = mSlots[buf].mFrameNumber; buffer->mTimestamp = mSlots[buf].mTimestamp; buffer->mBuf = buf; - mSlots[buf].mAcquireCalled = true; + buffer->mFence = mSlots[buf].mFence; + mSlots[buf].mAcquireCalled = true; + mSlots[buf].mNeedsCleanupOnRelease = false; mSlots[buf].mBufferState = BufferSlot::ACQUIRED; + mSlots[buf].mFence.clear(); + mQueue.erase(front); mDequeueCondition.broadcast(); @@ -891,7 +894,7 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) { } status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, - EGLSyncKHR fence) { + EGLSyncKHR eglFence, const sp<Fence>& fence) { ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); @@ -902,6 +905,7 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, } mSlots[buf].mEglDisplay = display; + mSlots[buf].mEglFence = eglFence; mSlots[buf].mFence = fence; // The buffer can now only be released if its in the acquired state diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp new file mode 100644 index 0000000..17bbfd1 --- /dev/null +++ b/libs/gui/ConsumerBase.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 "ConsumerBase" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +//#define LOG_NDEBUG 0 + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <hardware/hardware.h> + +#include <gui/IGraphicBufferAlloc.h> +#include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/ConsumerBase.h> + +#include <private/gui/ComposerService.h> + +#include <utils/Log.h> +#include <utils/String8.h> +#include <utils/Trace.h> + +// Macros for including the ConsumerBase name in log messages +#define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) + +namespace android { + +// Get an ID that's unique within this process. +static int32_t createProcessUniqueId() { + static volatile int32_t globalCounter = 0; + return android_atomic_inc(&globalCounter); +} + +ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) : + mAbandoned(false), + mBufferQueue(bufferQueue) { + // Choose a name using the PID and a process-unique ID. + mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); + + // Note that we can't create an sp<...>(this) in a ctor that will not keep a + // reference once the ctor ends, as that would cause the refcount of 'this' + // dropping to 0 at the end of the ctor. Since all we need is a wp<...> + // that's what we create. + wp<BufferQueue::ConsumerListener> listener; + sp<BufferQueue::ConsumerListener> proxy; + listener = static_cast<BufferQueue::ConsumerListener*>(this); + proxy = new BufferQueue::ProxyConsumerListener(listener); + + status_t err = mBufferQueue->consumerConnect(proxy); + if (err != NO_ERROR) { + CB_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)", + strerror(-err), err); + } else { + mBufferQueue->setConsumerName(mName); + } +} + +ConsumerBase::~ConsumerBase() { + CB_LOGV("~ConsumerBase"); + abandon(); +} + +void ConsumerBase::freeBufferLocked(int slotIndex) { + CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); + mSlots[slotIndex].mGraphicBuffer = 0; + mSlots[slotIndex].mFence = 0; +} + +// Used for refactoring, should not be in final interface +sp<BufferQueue> ConsumerBase::getBufferQueue() const { + Mutex::Autolock lock(mMutex); + return mBufferQueue; +} + +void ConsumerBase::onFrameAvailable() { + CB_LOGV("onFrameAvailable"); + + sp<FrameAvailableListener> listener; + { // scope for the lock + Mutex::Autolock lock(mMutex); + listener = mFrameAvailableListener; + } + + if (listener != NULL) { + CB_LOGV("actually calling onFrameAvailable"); + listener->onFrameAvailable(); + } +} + +void ConsumerBase::onBuffersReleased() { + Mutex::Autolock lock(mMutex); + + CB_LOGV("onBuffersReleased"); + + if (mAbandoned) { + // Nothing to do if we're already abandoned. + return; + } + + uint32_t mask = 0; + mBufferQueue->getReleasedBuffers(&mask); + for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + if (mask & (1 << i)) { + freeBufferLocked(i); + } + } +} + +void ConsumerBase::abandon() { + CB_LOGV("abandon"); + Mutex::Autolock lock(mMutex); + + if (!mAbandoned) { + abandonLocked(); + mAbandoned = true; + } +} + +void ConsumerBase::abandonLocked() { + CB_LOGV("abandonLocked"); + for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + freeBufferLocked(i); + } + // disconnect from the BufferQueue + mBufferQueue->consumerDisconnect(); + mBufferQueue.clear(); +} + +void ConsumerBase::setFrameAvailableListener( + const sp<FrameAvailableListener>& listener) { + CB_LOGV("setFrameAvailableListener"); + Mutex::Autolock lock(mMutex); + mFrameAvailableListener = listener; +} + +void ConsumerBase::dump(String8& result) const { + char buffer[1024]; + dump(result, "", buffer, 1024); +} + +void ConsumerBase::dump(String8& result, const char* prefix, + char* buffer, size_t size) const { + Mutex::Autolock _l(mMutex); + dumpLocked(result, prefix, buffer, size); +} + +void ConsumerBase::dumpLocked(String8& result, const char* prefix, + char* buffer, size_t SIZE) const { + snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned)); + result.append(buffer); + + if (!mAbandoned) { + mBufferQueue->dump(result, prefix, buffer, SIZE); + } +} + +status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item) { + status_t err = mBufferQueue->acquireBuffer(item); + if (err != NO_ERROR) { + return err; + } + + if (item->mGraphicBuffer != NULL) { + mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; + } + + CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf); + + return OK; +} + +status_t ConsumerBase::releaseBufferLocked(int slot, EGLDisplay display, + EGLSyncKHR eglFence, const sp<Fence>& fence) { + CB_LOGV("releaseBufferLocked: slot=%d", slot); + status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence, fence); + if (err == BufferQueue::STALE_BUFFER_SLOT) { + freeBufferLocked(slot); + } + + mSlots[slot].mFence.clear(); + + return err; +} + +} // namespace android
\ No newline at end of file diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp new file mode 100644 index 0000000..513828c --- /dev/null +++ b/libs/gui/CpuConsumer.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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_NDEBUG 0 +#define LOG_TAG "CpuConsumer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include <utils/Log.h> + +#include <gui/CpuConsumer.h> + +#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) +#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) + +namespace android { + +// Get an ID that's unique within this process. +static int32_t createProcessUniqueId() { + static volatile int32_t globalCounter = 0; + return android_atomic_inc(&globalCounter); +} + +CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : + mMaxLockedBuffers(maxLockedBuffers), + mCurrentLockedBuffers(0) +{ + mName = String8::format("cc-unnamed-%d-%d", getpid(), + createProcessUniqueId()); + + for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + mBufferPointers[i] = NULL; + } + + mBufferQueue = new BufferQueue(true); + + wp<BufferQueue::ConsumerListener> listener; + sp<BufferQueue::ConsumerListener> proxy; + listener = static_cast<BufferQueue::ConsumerListener*>(this); + proxy = new BufferQueue::ProxyConsumerListener(listener); + + status_t err = mBufferQueue->consumerConnect(proxy); + if (err != NO_ERROR) { + ALOGE("CpuConsumer: error connecting to BufferQueue: %s (%d)", + strerror(-err), err); + } else { + mBufferQueue->setSynchronousMode(true); + mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); + mBufferQueue->setConsumerName(mName); + } +} + +CpuConsumer::~CpuConsumer() +{ + Mutex::Autolock _l(mMutex); + for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + freeBufferLocked(i); + } + mBufferQueue->consumerDisconnect(); + mBufferQueue.clear(); +} + +void CpuConsumer::setName(const String8& name) { + Mutex::Autolock _l(mMutex); + mName = name; + mBufferQueue->setConsumerName(name); +} + +status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { + status_t err; + + if (!nativeBuffer) return BAD_VALUE; + if (mCurrentLockedBuffers == mMaxLockedBuffers) { + return INVALID_OPERATION; + } + + BufferQueue::BufferItem b; + + Mutex::Autolock _l(mMutex); + + err = mBufferQueue->acquireBuffer(&b); + if (err != OK) { + if (err == BufferQueue::NO_BUFFER_AVAILABLE) { + return BAD_VALUE; + } else { + CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); + return err; + } + } + + int buf = b.mBuf; + + if (b.mGraphicBuffer != NULL) { + if (mBufferPointers[buf] != NULL) { + CC_LOGE("Reallocation of buffer %d while in consumer use!", buf); + mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, + Fence::NO_FENCE); + return BAD_VALUE; + } + mBufferSlot[buf] = b.mGraphicBuffer; + } + + if (b.mFence.get()) { + err = b.mFence->wait(Fence::TIMEOUT_NEVER); + if (err != OK) { + CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", + strerror(-err), err); + return err; + } + } + + err = mBufferSlot[buf]->lock( + GraphicBuffer::USAGE_SW_READ_OFTEN, + b.mCrop, + &mBufferPointers[buf]); + + if (mBufferPointers[buf] != NULL && err != OK) { + CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err), + err); + return err; + } + + nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]); + nativeBuffer->width = mBufferSlot[buf]->getWidth(); + nativeBuffer->height = mBufferSlot[buf]->getHeight(); + nativeBuffer->format = mBufferSlot[buf]->getPixelFormat(); + nativeBuffer->stride = mBufferSlot[buf]->getStride(); + + nativeBuffer->crop = b.mCrop; + nativeBuffer->transform = b.mTransform; + nativeBuffer->scalingMode = b.mScalingMode; + nativeBuffer->timestamp = b.mTimestamp; + nativeBuffer->frameNumber = b.mFrameNumber; + + mCurrentLockedBuffers++; + + return OK; +} + +status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { + Mutex::Autolock _l(mMutex); + int buf = 0; + status_t err; + + void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); + for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) { + if (bufPtr == mBufferPointers[buf]) break; + } + if (buf == BufferQueue::NUM_BUFFER_SLOTS) { + CC_LOGE("%s: Can't find buffer to free", __FUNCTION__); + return BAD_VALUE; + } + + mBufferPointers[buf] = NULL; + err = mBufferSlot[buf]->unlock(); + if (err != OK) { + CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); + return err; + } + err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, + Fence::NO_FENCE); + if (err == BufferQueue::STALE_BUFFER_SLOT) { + freeBufferLocked(buf); + } else if (err != OK) { + CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__, + buf); + return err; + } + + mCurrentLockedBuffers--; + + return OK; +} + +void CpuConsumer::setFrameAvailableListener( + const sp<FrameAvailableListener>& listener) { + CC_LOGV("setFrameAvailableListener"); + Mutex::Autolock lock(mMutex); + mFrameAvailableListener = listener; +} + + +void CpuConsumer::onFrameAvailable() { + CC_LOGV("onFrameAvailable"); + sp<FrameAvailableListener> listener; + { // scope for the lock + Mutex::Autolock _l(mMutex); + listener = mFrameAvailableListener; + } + + if (listener != NULL) { + CC_LOGV("actually calling onFrameAvailable"); + listener->onFrameAvailable(); + } +} + +void CpuConsumer::onBuffersReleased() { + CC_LOGV("onBuffersReleased"); + + Mutex::Autolock lock(mMutex); + + uint32_t mask = 0; + mBufferQueue->getReleasedBuffers(&mask); + for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + if (mask & (1 << i)) { + freeBufferLocked(i); + } + } + +} + +status_t CpuConsumer::freeBufferLocked(int buf) { + status_t err = OK; + + if (mBufferPointers[buf] != NULL) { + CC_LOGW("Buffer %d freed while locked by consumer", buf); + mBufferPointers[buf] = NULL; + err = mBufferSlot[buf]->unlock(); + if (err != OK) { + CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); + } + mCurrentLockedBuffers--; + } + mBufferSlot[buf] = NULL; + return err; +} + +} // namespace android diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp index 7111092..0b76f37 100644 --- a/libs/gui/ISensorServer.cpp +++ b/libs/gui/ISensorServer.cpp @@ -55,7 +55,7 @@ public: int32_t n = reply.readInt32(); v.setCapacity(n); while (n--) { - reply.read(static_cast<Flattenable&>(s)); + reply.read(s); v.add(s); } return v; @@ -84,7 +84,7 @@ status_t BnSensorServer::onTransact( size_t n = v.size(); reply->writeInt32(n); for (size_t i=0 ; i<n ; i++) { - reply->write(static_cast<const Flattenable&>(v[i])); + reply->write(v[i]); } return NO_ERROR; } break; diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 1f1794c..76b23f3 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -68,26 +68,29 @@ public: return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder()); } - virtual sp<IMemoryHeap> getCblk() const + virtual void setTransactionState( + const Vector<ComposerState>& state, + const Vector<DisplayState>& displays, + uint32_t flags) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::GET_CBLK, data, &reply); - return interface_cast<IMemoryHeap>(reply.readStrongBinder()); - } - - virtual void setTransactionState(const Vector<ComposerState>& state, - int orientation, uint32_t flags) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - Vector<ComposerState>::const_iterator b(state.begin()); - Vector<ComposerState>::const_iterator e(state.end()); - data.writeInt32(state.size()); - for ( ; b != e ; ++b ) { - b->write(data); + { + Vector<ComposerState>::const_iterator b(state.begin()); + Vector<ComposerState>::const_iterator e(state.end()); + data.writeInt32(state.size()); + for ( ; b != e ; ++b ) { + b->write(data); + } + } + { + Vector<DisplayState>::const_iterator b(displays.begin()); + Vector<DisplayState>::const_iterator e(displays.end()); + data.writeInt32(displays.size()); + for ( ; b != e ; ++b ) { + b->write(data); + } } - data.writeInt32(orientation); data.writeInt32(flags); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -120,24 +123,6 @@ public: return reply.readInt32(); } - virtual status_t turnElectronBeamOff(int32_t mode) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_OFF, data, &reply); - return reply.readInt32(); - } - - virtual status_t turnElectronBeamOn(int32_t mode) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_ON, data, &reply); - return reply.readInt32(); - } - virtual bool authenticateSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) const { @@ -193,6 +178,55 @@ public: result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder()); return result; } + + virtual sp<IBinder> createDisplay() + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply); + return reply.readStrongBinder(); + } + + virtual sp<IBinder> getBuiltInDisplay(int32_t id) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeInt32(id); + remote()->transact(BnSurfaceComposer::GET_BUILT_IN_DISPLAY, data, &reply); + return reply.readStrongBinder(); + } + + virtual void blank() + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::BLANK, data, &reply); + } + + virtual void unblank() + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply); + } + + virtual status_t getDisplayInfo(DisplayID dpy, DisplayInfo* info) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeInt32(dpy); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply); + memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); + return reply.readInt32(); + } + + + virtual void connectDisplay(const sp<ISurfaceTexture> display) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display->asBinder()); + remote()->transact(BnSurfaceComposer::CONNECT_DISPLAY, data, &reply); + } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -223,19 +257,21 @@ status_t BnSurfaceComposer::onTransact( s.read(data); state.add(s); } - int orientation = data.readInt32(); + count = data.readInt32(); + DisplayState d; + Vector<DisplayState> displays; + displays.setCapacity(count); + for (size_t i=0 ; i<count ; i++) { + d.read(data); + displays.add(d); + } uint32_t flags = data.readInt32(); - setTransactionState(state, orientation, flags); + setTransactionState(state, displays, flags); } break; case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); bootFinished(); } break; - case GET_CBLK: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> b = getCblk()->asBinder(); - reply->writeStrongBinder(b); - } break; case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); DisplayID dpy = data.readInt32(); @@ -254,18 +290,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(f); reply->writeInt32(res); } break; - case TURN_ELECTRON_BEAM_OFF: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - int32_t mode = data.readInt32(); - status_t res = turnElectronBeamOff(mode); - reply->writeInt32(res); - } break; - case TURN_ELECTRON_BEAM_ON: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - int32_t mode = data.readInt32(); - status_t res = turnElectronBeamOn(mode); - reply->writeInt32(res); - } break; case AUTHENTICATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<ISurfaceTexture> surfaceTexture = @@ -279,6 +303,41 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(connection->asBinder()); return NO_ERROR; } break; + case CREATE_DISPLAY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> display(createDisplay()); + reply->writeStrongBinder(display); + return NO_ERROR; + } break; + case GET_BUILT_IN_DISPLAY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t id = data.readInt32(); + sp<IBinder> display(getBuiltInDisplay(id)); + reply->writeStrongBinder(display); + return NO_ERROR; + } break; + case BLANK: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + blank(); + } break; + case UNBLANK: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + unblank(); + } break; + case GET_DISPLAY_INFO: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + DisplayInfo info; + DisplayID dpy = data.readInt32(); + status_t result = getDisplayInfo(dpy, &info); + memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo)); + reply->writeInt32(result); + } break; + case CONNECT_DISPLAY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<ISurfaceTexture> surfaceTexture = + interface_cast<ISurfaceTexture>(data.readStrongBinder()); + connectDisplay(surfaceTexture); + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index 3eb5e7a..a0b1e74 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -81,8 +81,8 @@ public: return result; } - virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, - uint32_t format, uint32_t usage) { + virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(w); @@ -94,6 +94,12 @@ public: return result; } *buf = reply.readInt32(); + fence.clear(); + bool hasFence = reply.readInt32(); + if (hasFence) { + fence = new Fence(); + reply.read(*fence.get()); + } result = reply.readInt32(); return result; } @@ -103,7 +109,7 @@ public: Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); - memcpy(data.writeInplace(sizeof(input)), &input, sizeof(input)); + data.write(input); status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; @@ -113,10 +119,15 @@ public: return result; } - virtual void cancelBuffer(int buf) { + virtual void cancelBuffer(int buf, sp<Fence> fence) { Parcel data, reply; + bool hasFence = fence.get() && fence->isValid(); data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); + data.writeInt32(hasFence); + if (hasFence) { + data.write(*fence.get()); + } remote()->transact(CANCEL_BUFFER, data, &reply); } @@ -205,28 +216,38 @@ status_t BnSurfaceTexture::onTransact( uint32_t format = data.readInt32(); uint32_t usage = data.readInt32(); int buf; - int result = dequeueBuffer(&buf, w, h, format, usage); + sp<Fence> fence; + int result = dequeueBuffer(&buf, fence, w, h, format, usage); + bool hasFence = fence.get() && fence->isValid(); reply->writeInt32(buf); + reply->writeInt32(hasFence); + if (hasFence) { + reply->write(*fence.get()); + } reply->writeInt32(result); return NO_ERROR; } break; case QUEUE_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); - QueueBufferInput const* const input = - reinterpret_cast<QueueBufferInput const *>( - data.readInplace(sizeof(QueueBufferInput))); + QueueBufferInput input(data); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); - status_t result = queueBuffer(buf, *input, output); + status_t result = queueBuffer(buf, input, output); reply->writeInt32(result); return NO_ERROR; } break; case CANCEL_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); - cancelBuffer(buf); + sp<Fence> fence; + bool hasFence = data.readInt32(); + if (hasFence) { + fence = new Fence(); + data.read(*fence.get()); + } + cancelBuffer(buf, fence); return NO_ERROR; } break; case QUERY: { @@ -268,4 +289,62 @@ status_t BnSurfaceTexture::onTransact( // ---------------------------------------------------------------------------- +static bool isValid(const sp<Fence>& fence) { + return fence.get() && fence->isValid(); +} + +ISurfaceTexture::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { + parcel.read(*this); +} + +size_t ISurfaceTexture::QueueBufferInput::getFlattenedSize() const +{ + return sizeof(timestamp) + + sizeof(crop) + + sizeof(scalingMode) + + sizeof(transform) + + sizeof(bool) + + (isValid(fence) ? fence->getFlattenedSize() : 0); +} + +size_t ISurfaceTexture::QueueBufferInput::getFdCount() const +{ + return isValid(fence) ? fence->getFdCount() : 0; +} + +status_t ISurfaceTexture::QueueBufferInput::flatten(void* buffer, size_t size, + int fds[], size_t count) const +{ + status_t err = NO_ERROR; + bool haveFence = isValid(fence); + char* p = (char*)buffer; + memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); + memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); + memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); + memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); + memcpy(p, &haveFence, sizeof(haveFence)); p += sizeof(haveFence); + if (haveFence) { + err = fence->flatten(p, size - (p - (char*)buffer), fds, count); + } + return err; +} + +status_t ISurfaceTexture::QueueBufferInput::unflatten(void const* buffer, + size_t size, int fds[], size_t count) +{ + status_t err = NO_ERROR; + bool haveFence; + const char* p = (const char*)buffer; + memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); + memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); + memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); + memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); + memcpy(&haveFence, p, sizeof(haveFence)); p += sizeof(haveFence); + if (haveFence) { + fence = new Fence(); + err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); + } + return err; +} + }; // namespace android diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 224c305..e2604f8 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -17,6 +17,7 @@ #include <utils/Errors.h> #include <binder/Parcel.h> #include <gui/ISurfaceComposerClient.h> +#include <gui/ISurfaceTexture.h> #include <private/gui/LayerState.h> namespace android { @@ -25,14 +26,7 @@ status_t layer_state_t::write(Parcel& output) const { status_t err; - size_t len = transparentRegion.write(NULL, 0); - err = output.writeInt32(len); - if (err < NO_ERROR) return err; - - void* buf = output.writeInplace(len); - if (buf == NULL) return NO_MEMORY; - - err = transparentRegion.write(buf, len); + err = output.write(transparentRegion); if (err < NO_ERROR) return err; // NOTE: regions are at the end of the structure @@ -45,11 +39,8 @@ status_t layer_state_t::write(Parcel& output) const status_t layer_state_t::read(const Parcel& input) { status_t err; - size_t len = input.readInt32(); - void const* buf = input.readInplace(len); - if (buf == NULL) return NO_MEMORY; - err = transparentRegion.read(buf); + err = input.read(transparentRegion); if (err < NO_ERROR) return err; // NOTE: regions are at the end of the structure @@ -69,4 +60,28 @@ status_t ComposerState::read(const Parcel& input) { return state.read(input); } + +status_t DisplayState::write(Parcel& output) const { + output.writeStrongBinder(token); + output.writeStrongBinder(surface->asBinder()); + output.writeInt32(what); + output.writeInt32(layerStack); + output.writeInt32(orientation); + output.write(viewport); + output.write(frame); + return NO_ERROR; +} + +status_t DisplayState::read(const Parcel& input) { + token = input.readStrongBinder(); + surface = interface_cast<ISurfaceTexture>(input.readStrongBinder()); + what = input.readInt32(); + layerStack = input.readInt32(); + orientation = input.readInt32(); + input.read(viewport); + input.read(frame); + return NO_ERROR; +} + + }; // namespace android diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 5cc76b4..c52a88f 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -98,7 +98,7 @@ int32_t Sensor::getVersion() const { return mVersion; } -size_t Sensor::getFlattenedSize() const +size_t Sensor::getSize() const { return sizeof(int32_t) + ((mName.length() + 3) & ~3) + sizeof(int32_t) + ((mVendor.length() + 3) & ~3) + @@ -107,11 +107,6 @@ size_t Sensor::getFlattenedSize() const sizeof(int32_t); } -size_t Sensor::getFdCount() const -{ - return 0; -} - static inline size_t write(void* buffer, size_t offset, const String8& value) { memcpy(static_cast<char*>(buffer) + offset, value.string(), value.length()); @@ -130,12 +125,8 @@ size_t write(void* buffer, size_t offset, int32_t value) { return sizeof(int32_t); } -status_t Sensor::flatten(void* buffer, size_t size, - int fds[], size_t count) const +status_t Sensor::flatten(void* buffer) const { - if (size < Sensor::getFlattenedSize()) - return -ENOMEM; - size_t offset = 0; offset += write(buffer, offset, int32_t(mName.length())); offset += write(buffer, offset, mName); @@ -149,7 +140,6 @@ status_t Sensor::flatten(void* buffer, size_t size, offset += write(buffer, offset, mResolution); offset += write(buffer, offset, mPower); offset += write(buffer, offset, mMinDelay); - return NO_ERROR; } @@ -171,8 +161,7 @@ size_t read(void const* buffer, size_t offset, int32_t* value) { return sizeof(int32_t); } -status_t Sensor::unflatten(void const* buffer, size_t size, - int fds[], size_t count) +status_t Sensor::unflatten(void const* buffer, size_t size) { int32_t len; size_t offset = 0; @@ -188,7 +177,6 @@ status_t Sensor::unflatten(void const* buffer, size_t size, offset += read(buffer, offset, &mResolution); offset += read(buffer, offset, &mPower); offset += read(buffer, offset, &mMinDelay); - return NO_ERROR; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index d7590f0..b9cbfa6 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -122,18 +122,6 @@ status_t SurfaceControl::show(int32_t layer) { const sp<SurfaceComposerClient>& client(mClient); return client->show(mToken, layer); } -status_t SurfaceControl::freeze() { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->freeze(mToken); -} -status_t SurfaceControl::unfreeze() { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->unfreeze(mToken); -} status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { status_t err = validate(); if (err < 0) return err; @@ -158,12 +146,6 @@ status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtd const sp<SurfaceComposerClient>& client(mClient); return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); } -status_t SurfaceControl::setFreezeTint(uint32_t tint) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setFreezeTint(mToken, tint); -} status_t SurfaceControl::setCrop(const Rect& crop) { status_t err = validate(); if (err < 0) return err; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8fa2167..1e6e1bd 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -38,7 +38,6 @@ #include <private/gui/ComposerService.h> #include <private/gui/LayerState.h> -#include <private/gui/SharedBufferStack.h> namespace android { // --------------------------------------------------------------------------- @@ -51,33 +50,16 @@ ComposerService::ComposerService() while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); } - mServerCblkMemory = mComposerService->getCblk(); - mServerCblk = static_cast<surface_flinger_cblk_t volatile *>( - mServerCblkMemory->getBase()); } sp<ISurfaceComposer> ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService; } -surface_flinger_cblk_t const volatile * ComposerService::getControlBlock() { - return ComposerService::getInstance().mServerCblk; -} - -static inline sp<ISurfaceComposer> getComposerService() { - return ComposerService::getComposerService(); -} - -static inline surface_flinger_cblk_t const volatile * get_cblk() { - return ComposerService::getControlBlock(); -} - // --------------------------------------------------------------------------- -// NOTE: this is NOT a member function (it's a friend defined with its -// declaration). static inline -int compare_type( const ComposerState& lhs, const ComposerState& rhs) { +int compare_type(const ComposerState& lhs, const ComposerState& rhs) { if (lhs.client < rhs.client) return -1; if (lhs.client > rhs.client) return 1; if (lhs.state.surface < rhs.state.surface) return -1; @@ -85,17 +67,21 @@ int compare_type( const ComposerState& lhs, const ComposerState& rhs) { return 0; } +static inline +int compare_type(const DisplayState& lhs, const DisplayState& rhs) { + return compare_type(lhs.token, rhs.token); +} + class Composer : public Singleton<Composer> { friend class Singleton<Composer>; mutable Mutex mLock; - SortedVector<ComposerState> mStates; - int mOrientation; + SortedVector<ComposerState> mComposerStates; + SortedVector<DisplayState > mDisplayStates; uint32_t mForceSynchronous; Composer() : Singleton<Composer>(), - mOrientation(ISurfaceComposer::eOrientationUnchanged), mForceSynchronous(0) { } @@ -104,7 +90,10 @@ class Composer : public Singleton<Composer> layer_state_t* getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id); + DisplayState& getDisplayStateLocked(const sp<IBinder>& token); + public: + sp<IBinder> createDisplay(); status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id, float x, float y); @@ -121,12 +110,17 @@ public: float alpha); status_t setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); - status_t setFreezeTint( - const sp<SurfaceComposerClient>& client, SurfaceID id, - uint32_t tint); status_t setOrientation(int orientation); status_t setCrop(const sp<SurfaceComposerClient>& client, SurfaceID id, const Rect& crop); + status_t setLayerStack(const sp<SurfaceComposerClient>& client, + SurfaceID id, uint32_t layerStack); + + void setDisplaySurface(const sp<IBinder>& token, const sp<ISurfaceTexture>& surface); + void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack); + void setDisplayOrientation(const sp<IBinder>& token, uint32_t orientation); + void setDisplayViewport(const sp<IBinder>& token, const Rect& viewport); + void setDisplayFrame(const sp<IBinder>& token, const Rect& frame); static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(synchronous); @@ -137,20 +131,24 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- +sp<IBinder> Composer::createDisplay() { + return ComposerService::getComposerService()->createDisplay(); +} + void Composer::closeGlobalTransactionImpl(bool synchronous) { - sp<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); Vector<ComposerState> transaction; - int orientation; + Vector<DisplayState> displayTransaction; uint32_t flags = 0; { // scope for the lock Mutex::Autolock _l(mLock); - transaction = mStates; - mStates.clear(); + transaction = mComposerStates; + mComposerStates.clear(); - orientation = mOrientation; - mOrientation = ISurfaceComposer::eOrientationUnchanged; + displayTransaction = mDisplayStates; + mDisplayStates.clear(); if (synchronous || mForceSynchronous) { flags |= ISurfaceComposer::eSynchronous; @@ -158,7 +156,7 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) { mForceSynchronous = false; } - sm->setTransactionState(transaction, orientation, flags); + sm->setTransactionState(transaction, displayTransaction, flags); } layer_state_t* Composer::getLayerStateLocked( @@ -168,13 +166,13 @@ layer_state_t* Composer::getLayerStateLocked( s.client = client->mClient; s.state.surface = id; - ssize_t index = mStates.indexOf(s); + ssize_t index = mComposerStates.indexOf(s); if (index < 0) { // we don't have it, add an initialized layer_state to our list - index = mStates.add(s); + index = mComposerStates.add(s); } - ComposerState* const out = mStates.editArray(); + ComposerState* const out = mComposerStates.editArray(); return &(out[index].state); } @@ -184,7 +182,7 @@ status_t Composer::setPosition(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::ePositionChanged; + s->what |= layer_state_t::ePositionChanged; s->x = x; s->y = y; return NO_ERROR; @@ -196,7 +194,7 @@ status_t Composer::setSize(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eSizeChanged; + s->what |= layer_state_t::eSizeChanged; s->w = w; s->h = h; @@ -212,7 +210,7 @@ status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eLayerChanged; + s->what |= layer_state_t::eLayerChanged; s->z = z; return NO_ERROR; } @@ -224,7 +222,7 @@ status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eVisibilityChanged; + s->what |= layer_state_t::eVisibilityChanged; s->flags &= ~mask; s->flags |= (flags & mask); s->mask |= mask; @@ -238,7 +236,7 @@ status_t Composer::setTransparentRegionHint( layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eTransparentRegionChanged; + s->what |= layer_state_t::eTransparentRegionChanged; s->transparentRegion = transparentRegion; return NO_ERROR; } @@ -249,11 +247,22 @@ status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eAlphaChanged; + s->what |= layer_state_t::eAlphaChanged; s->alpha = alpha; return NO_ERROR; } +status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client, + SurfaceID id, uint32_t layerStack) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eLayerStackChanged; + s->layerStack = layerStack; + return NO_ERROR; +} + status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy) { @@ -261,7 +270,7 @@ status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client, layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eMatrixChanged; + s->what |= layer_state_t::eMatrixChanged; layer_state_t::matrix22_t matrix; matrix.dsdx = dsdx; matrix.dtdx = dtdx; @@ -271,36 +280,78 @@ status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client, return NO_ERROR; } -status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client, - SurfaceID id, uint32_t tint) { +status_t Composer::setCrop(const sp<SurfaceComposerClient>& client, + SurfaceID id, const Rect& crop) { Mutex::Autolock _l(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eFreezeTintChanged; - s->tint = tint; + s->what |= layer_state_t::eCropChanged; + s->crop = crop; return NO_ERROR; } -status_t Composer::setOrientation(int orientation) { +// --------------------------------------------------------------------------- + +DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) { + DisplayState s; + s.token = token; + ssize_t index = mDisplayStates.indexOf(s); + if (index < 0) { + // we don't have it, add an initialized layer_state to our list + s.what = 0; + index = mDisplayStates.add(s); + } + return mDisplayStates.editItemAt(index); +} + +void Composer::setDisplaySurface(const sp<IBinder>& token, + const sp<ISurfaceTexture>& surface) { Mutex::Autolock _l(mLock); - mOrientation = orientation; + DisplayState& s(getDisplayStateLocked(token)); + s.surface = surface; + s.what |= DisplayState::eSurfaceChanged; +} - // Changing the orientation makes the transaction synchronous. - mForceSynchronous = true; +void Composer::setDisplayLayerStack(const sp<IBinder>& token, + uint32_t layerStack) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.layerStack = layerStack; + s.what |= DisplayState::eLayerStackChanged; +} +void Composer::setDisplayOrientation(const sp<IBinder>& token, + uint32_t orientation) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.orientation = orientation; + s.what |= DisplayState::eOrientationChanged; + mForceSynchronous = true; // TODO: do we actually still need this? +} + +// FIXME: get rid of this eventually +status_t Composer::setOrientation(int orientation) { + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); + sp<IBinder> token(sm->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + Composer::setDisplayOrientation(token, orientation); return NO_ERROR; } -status_t Composer::setCrop(const sp<SurfaceComposerClient>& client, - SurfaceID id, const Rect& crop) { +void Composer::setDisplayViewport(const sp<IBinder>& token, + const Rect& viewport) { Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eCropChanged; - s->crop = crop; - return NO_ERROR; + DisplayState& s(getDisplayStateLocked(token)); + s.viewport = viewport; + s.what |= DisplayState::eViewportChanged; +} + +void Composer::setDisplayFrame(const sp<IBinder>& token, + const Rect& frame) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.frame = frame; + s.what |= DisplayState::eFrameChanged; } // --------------------------------------------------------------------------- @@ -311,7 +362,7 @@ SurfaceComposerClient::SurfaceComposerClient() } void SurfaceComposerClient::onFirstRef() { - sp<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { @@ -336,7 +387,7 @@ sp<IBinder> SurfaceComposerClient::connection() const { status_t SurfaceComposerClient::linkToComposerDeath( const sp<IBinder::DeathRecipient>& recipient, void* cookie, uint32_t flags) { - sp<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); return sm->asBinder()->linkToDeath(recipient, cookie, flags); } @@ -388,6 +439,10 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface( return result; } +sp<IBinder> SurfaceComposerClient::createDisplay() { + return Composer::getInstance().createDisplay(); +} + status_t SurfaceComposerClient::destroySurface(SurfaceID sid) { if (mStatus != NO_ERROR) return mStatus; @@ -415,10 +470,6 @@ status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) { return getComposer().setCrop(this, id, crop); } -status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { - return getComposer().setFreezeTint(this, id, tint); -} - status_t SurfaceComposerClient::setPosition(SurfaceID id, float x, float y) { return getComposer().setPosition(this, id, x, y); } @@ -433,26 +484,14 @@ status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { status_t SurfaceComposerClient::hide(SurfaceID id) { return getComposer().setFlags(this, id, - ISurfaceComposer::eLayerHidden, - ISurfaceComposer::eLayerHidden); + layer_state_t::eLayerHidden, + layer_state_t::eLayerHidden); } status_t SurfaceComposerClient::show(SurfaceID id, int32_t) { return getComposer().setFlags(this, id, 0, - ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::freeze(SurfaceID id) { - return getComposer().setFlags(this, id, - ISurfaceComposer::eLayerFrozen, - ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::unfreeze(SurfaceID id) { - return getComposer().setFlags(this, id, - 0, - ISurfaceComposer::eLayerFrozen); + layer_state_t::eLayerHidden); } status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, @@ -469,6 +508,10 @@ status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { return getComposer().setAlpha(this, id, alpha); } +status_t SurfaceComposerClient::setLayerStack(SurfaceID id, uint32_t layerStack) { + return getComposer().setLayerStack(this, id, layerStack); +} + status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy) { return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy); @@ -482,76 +525,37 @@ status_t SurfaceComposerClient::setOrientation(DisplayID dpy, // ---------------------------------------------------------------------------- -status_t SurfaceComposerClient::getDisplayInfo( - DisplayID dpy, DisplayInfo* info) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - - info->w = dcblk->w; - info->h = dcblk->h; - info->orientation = dcblk->orientation; - info->xdpi = dcblk->xdpi; - info->ydpi = dcblk->ydpi; - info->fps = dcblk->fps; - info->density = dcblk->density; - return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo)); +void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token, + const sp<ISurfaceTexture>& surface) { + Composer::getInstance().setDisplaySurface(token, surface); } -ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->w; +void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token, + uint32_t layerStack) { + Composer::getInstance().setDisplayLayerStack(token, layerStack); } -ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->h; +void SurfaceComposerClient::setDisplayOrientation(const sp<IBinder>& token, + uint32_t orientation) { + Composer::getInstance().setDisplayOrientation(token, orientation); } -ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->orientation; +void SurfaceComposerClient::setDisplayViewport(const sp<IBinder>& token, + const Rect& viewport) { + Composer::getInstance().setDisplayViewport(token, viewport); } -ssize_t SurfaceComposerClient::getNumberOfDisplays() -{ - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - uint32_t connected = cblk->connected; - int n = 0; - while (connected) { - if (connected&1) n++; - connected >>= 1; - } - return n; +void SurfaceComposerClient::setDisplayFrame(const sp<IBinder>& token, + const Rect& frame) { + Composer::getInstance().setDisplayFrame(token, frame); } // ---------------------------------------------------------------------------- -status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) -{ - // This has been made a no-op because it can cause Gralloc buffer deadlocks. - return NO_ERROR; -} - -status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) +status_t SurfaceComposerClient::getDisplayInfo( + DisplayID dpy, DisplayInfo* info) { - // This has been made a no-op because it can cause Gralloc buffer deadlocks. - return NO_ERROR; + return ComposerService::getComposerService()->getDisplayInfo(dpy, info); } // ---------------------------------------------------------------------------- diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 55be4bc..451ccc2 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -98,14 +98,10 @@ static float mtxRot270[16] = { static void mtxMul(float out[16], const float a[16], const float b[16]); -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) : + ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue), mCurrentTransform(0), mCurrentTimestamp(0), mFilteringEnabled(true), @@ -118,47 +114,15 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, mTexTarget(texTarget), mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), - mAbandoned(false), mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), mAttached(true) { - // Choose a name using the PID and a process-unique ID. - mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); ST_LOGV("SurfaceTexture"); - if (bufferQueue == 0) { - ST_LOGV("Creating a new BufferQueue"); - mBufferQueue = new BufferQueue(allowSynchronousMode); - } - else { - mBufferQueue = bufferQueue; - } memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); - // Note that we can't create an sp<...>(this) in a ctor that will not keep a - // reference once the ctor ends, as that would cause the refcount of 'this' - // dropping to 0 at the end of the ctor. Since all we need is a wp<...> - // that's what we create. - wp<BufferQueue::ConsumerListener> listener; - sp<BufferQueue::ConsumerListener> proxy; - listener = static_cast<BufferQueue::ConsumerListener*>(this); - proxy = new BufferQueue::ProxyConsumerListener(listener); - - status_t err = mBufferQueue->consumerConnect(proxy); - if (err != NO_ERROR) { - ST_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)", - strerror(-err), err); - } else { - mBufferQueue->setConsumerName(mName); - mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); - } -} - -SurfaceTexture::~SurfaceTexture() { - ST_LOGV("~SurfaceTexture"); - - abandon(); + mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); } status_t SurfaceTexture::setBufferCountServer(int bufferCount) { @@ -179,6 +143,42 @@ status_t SurfaceTexture::updateTexImage() { return SurfaceTexture::updateTexImage(NULL); } +status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) { + status_t err = ConsumerBase::acquireBufferLocked(item); + if (err != NO_ERROR) { + return err; + } + + int slot = item->mBuf; + if (item->mGraphicBuffer != NULL) { + if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage); + mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR; + } + } + + // Update the GL texture object. We may have to do this even when + // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when + // detaching from a context but the buffer has not been re-allocated. + EGLImageKHR image = createImage(mEglDisplay, mSlots[slot].mGraphicBuffer); + if (image == EGL_NO_IMAGE_KHR) { + return UNKNOWN_ERROR; + } + mEglSlots[slot].mEglImage = image; + + return NO_ERROR; +} + +status_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display, + EGLSyncKHR eglFence, const sp<Fence>& fence) { + status_t err = ConsumerBase::releaseBufferLocked(buf, mEglDisplay, + eglFence, fence); + + mEglSlots[mCurrentTexture].mEglFence = EGL_NO_SYNC_KHR; + + return err; +} + status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) { ATRACE_CALL(); ST_LOGV("updateTexImage"); @@ -219,106 +219,74 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) { // In asynchronous mode the list is guaranteed to be one buffer // deep, while in synchronous mode we use the oldest buffer. - err = mBufferQueue->acquireBuffer(&item); + err = acquireBufferLocked(&item); if (err == NO_ERROR) { int buf = item.mBuf; - // This buffer was newly allocated, so we need to clean up on our side - if (item.mGraphicBuffer != NULL) { - mEGLSlots[buf].mGraphicBuffer = 0; - if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage); - mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; - } - mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer; - } // we call the rejecter here, in case the caller has a reason to // not accept this buffer. this is used by SurfaceFlinger to // reject buffers which have the wrong size - if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) { - mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence); - mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR; + if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { + releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence); glBindTexture(mTexTarget, mTexName); return NO_ERROR; } - // Update the GL texture object. We may have to do this even when - // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when - // detaching from a context but the buffer has not been re-allocated. - EGLImageKHR image = mEGLSlots[buf].mEglImage; - if (image == EGL_NO_IMAGE_KHR) { - if (mEGLSlots[buf].mGraphicBuffer == NULL) { - ST_LOGE("updateTexImage: buffer at slot %d is null", buf); - err = BAD_VALUE; - } else { - image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer); - mEGLSlots[buf].mEglImage = image; - if (image == EGL_NO_IMAGE_KHR) { - // NOTE: if dpy was invalid, createImage() is guaranteed to - // fail. so we'd end up here. - err = UNKNOWN_ERROR; - } - } + GLint error; + while ((error = glGetError()) != GL_NO_ERROR) { + ST_LOGW("updateTexImage: clearing GL error: %#04x", error); } - if (err == NO_ERROR) { - GLint error; - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGW("updateTexImage: clearing GL error: %#04x", error); - } - - glBindTexture(mTexTarget, mTexName); - glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); + EGLImageKHR image = mEglSlots[buf].mEglImage; + glBindTexture(mTexTarget, mTexName); + glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGE("updateTexImage: error binding external texture image %p " - "(slot %d): %#04x", image, buf, error); - err = UNKNOWN_ERROR; - } + while ((error = glGetError()) != GL_NO_ERROR) { + ST_LOGE("updateTexImage: error binding external texture image %p " + "(slot %d): %#04x", image, buf, error); + err = UNKNOWN_ERROR; + } - if (err == NO_ERROR) { - err = syncForReleaseLocked(dpy); - } + if (err == NO_ERROR) { + err = syncForReleaseLocked(dpy); } if (err != NO_ERROR) { // Release the buffer we just acquired. It's not safe to // release the old buffer, so instead we just drop the new frame. - mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence); - mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR; + releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence); return err; } ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, - buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0); + buf, mSlots[buf].mGraphicBuffer->handle); // release old buffer if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { - status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy, - mEGLSlots[mCurrentTexture].mFence); - - mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR; - if (status == BufferQueue::STALE_BUFFER_SLOT) { - freeBufferLocked(mCurrentTexture); - } else if (status != NO_ERROR) { - ST_LOGE("updateTexImage: released invalid buffer"); + status_t status = releaseBufferLocked(mCurrentTexture, dpy, + mEglSlots[mCurrentTexture].mEglFence, + mSlots[mCurrentTexture].mFence); + if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) { + ST_LOGE("updateTexImage: failed to release buffer: %s (%d)", + strerror(-status), status); err = status; } } // Update the SurfaceTexture state. mCurrentTexture = buf; - mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer; + mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; mCurrentCrop = item.mCrop; mCurrentTransform = item.mTransform; mCurrentScalingMode = item.mScalingMode; mCurrentTimestamp = item.mTimestamp; + mCurrentFence = item.mFence; computeCurrentTransformMatrix(); } else { if (err < 0) { - ALOGE("updateTexImage failed on acquire %d", err); + ST_LOGE("updateTexImage failed on acquire %d", err); } // We always bind the texture even if we don't update its contents. glBindTexture(mTexTarget, mTexName); @@ -328,6 +296,27 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) { return err; } +void SurfaceTexture::setReleaseFence(int fenceFd) { + sp<Fence> fence(new Fence(fenceFd)); + if (fenceFd == -1 || mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) + return; + if (!mSlots[mCurrentTexture].mFence.get()) { + mSlots[mCurrentTexture].mFence = fence; + } else { + sp<Fence> mergedFence = Fence::merge( + String8("SurfaceTexture merged release"), + mSlots[mCurrentTexture].mFence, fence); + if (!mergedFence.get()) { + ST_LOGE("failed to merge release fences"); + // synchronization is broken, the best we can do is hope fences + // signal in order so the new fence will act like a union + mSlots[mCurrentTexture].mFence = fence; + return; + } + mSlots[mCurrentTexture].mFence = mergedFence; + } +} + status_t SurfaceTexture::detachFromContext() { ATRACE_CALL(); ST_LOGV("detachFromContext"); @@ -371,10 +360,10 @@ status_t SurfaceTexture::detachFromContext() { // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a // new EGLDisplay). for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { - EGLImageKHR img = mEGLSlots[i].mEglImage; + EGLImageKHR img = mEglSlots[i].mEglImage; if (img != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(mEglDisplay, img); - mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR; + mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR; } } @@ -462,7 +451,7 @@ status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) { ST_LOGV("syncForReleaseLocked"); if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { - EGLSyncKHR fence = mEGLSlots[mCurrentTexture].mFence; + EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence; if (fence != EGL_NO_SYNC_KHR) { // There is already a fence for the current slot. We need to wait // on that before replacing it with another fence to ensure that all @@ -490,7 +479,7 @@ status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) { return UNKNOWN_ERROR; } glFlush(); - mEGLSlots[mCurrentTexture].mFence = fence; + mEglSlots[mCurrentTexture].mEglFence = fence; } return OK; @@ -587,11 +576,13 @@ void SurfaceTexture::computeCurrentTransformMatrix() { // We know there's no subsampling of any channels, so we // only need to shrink by a half a pixel. shrinkAmount = 0.5; + break; default: // If we don't recognize the format, we must assume the // worst case (that we care about), which is YUV420. shrinkAmount = 1.0; + break; } } @@ -631,13 +622,6 @@ nsecs_t SurfaceTexture::getTimestamp() { return mCurrentTimestamp; } -void SurfaceTexture::setFrameAvailableListener( - const sp<FrameAvailableListener>& listener) { - ST_LOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer) { EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); @@ -705,6 +689,11 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const { return mCurrentScalingMode; } +sp<Fence> SurfaceTexture::getCurrentFence() const { + Mutex::Autolock lock(mMutex); + return mCurrentFence; +} + bool SurfaceTexture::isSynchronousMode() const { Mutex::Autolock lock(mMutex); return mBufferQueue->isSynchronousMode(); @@ -712,35 +701,21 @@ bool SurfaceTexture::isSynchronousMode() const { void SurfaceTexture::freeBufferLocked(int slotIndex) { ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mEGLSlots[slotIndex].mGraphicBuffer = 0; if (slotIndex == mCurrentTexture) { mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; } - EGLImageKHR img = mEGLSlots[slotIndex].mEglImage; + EGLImageKHR img = mEglSlots[slotIndex].mEglImage; if (img != EGL_NO_IMAGE_KHR) { ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img); eglDestroyImageKHR(mEglDisplay, img); } - mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR; + mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR; } -void SurfaceTexture::abandon() { - ST_LOGV("abandon"); - Mutex::Autolock lock(mMutex); - - if (!mAbandoned) { - mAbandoned = true; - mCurrentTextureBuf.clear(); - - // destroy all egl buffers - for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { - freeBufferLocked(i); - } - - // disconnect from the BufferQueue - mBufferQueue->consumerDisconnect(); - mBufferQueue.clear(); - } +void SurfaceTexture::abandonLocked() { + ST_LOGV("abandonLocked"); + mCurrentTextureBuf.clear(); + ConsumerBase::abandonLocked(); } void SurfaceTexture::setName(const String8& name) { @@ -772,71 +747,18 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { return mBufferQueue->setSynchronousMode(enabled); } -// Used for refactoring, should not be in final interface -sp<BufferQueue> SurfaceTexture::getBufferQueue() const { - Mutex::Autolock lock(mMutex); - return mBufferQueue; -} - -void SurfaceTexture::onFrameAvailable() { - ST_LOGV("onFrameAvailable"); - - sp<FrameAvailableListener> listener; - { // scope for the lock - Mutex::Autolock lock(mMutex); - listener = mFrameAvailableListener; - } - - if (listener != NULL) { - ST_LOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); - } -} - -void SurfaceTexture::onBuffersReleased() { - ST_LOGV("onBuffersReleased"); - - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - // Nothing to do if we're already abandoned. - return; - } - - uint32_t mask = 0; - mBufferQueue->getReleasedBuffers(&mask); - for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { - if (mask & (1 << i)) { - freeBufferLocked(i); - } - } -} - -void SurfaceTexture::dump(String8& result) const +void SurfaceTexture::dumpLocked(String8& result, const char* prefix, + char* buffer, size_t size) const { - char buffer[1024]; - dump(result, "", buffer, 1024); -} - -void SurfaceTexture::dump(String8& result, const char* prefix, - char* buffer, size_t SIZE) const -{ - Mutex::Autolock _l(mMutex); - snprintf(buffer, SIZE, "%smTexName=%d, mAbandoned=%d\n", prefix, mTexName, - int(mAbandoned)); + snprintf(buffer, size, + "%smTexName=%d mCurrentTexture=%d\n" + "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n", + prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, + mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, + mCurrentTransform); result.append(buffer); - snprintf(buffer, SIZE, - "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n", - prefix, mCurrentCrop.left, - mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, - mCurrentTransform, mCurrentTexture - ); - result.append(buffer); - - if (!mAbandoned) { - mBufferQueue->dump(result, prefix, buffer, SIZE); - } + ConsumerBase::dumpLocked(result, prefix, buffer, size); } static void mtxMul(float out[16], const float a[16], const float b[16]) { diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 36a81a6..718fe84 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -23,6 +23,8 @@ #include <utils/Log.h> #include <utils/Trace.h> +#include <ui/Fence.h> + #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> #include <gui/SurfaceTexture.h> @@ -62,11 +64,15 @@ void SurfaceTextureClient::init() { ANativeWindow::setSwapInterval = hook_setSwapInterval; ANativeWindow::dequeueBuffer = hook_dequeueBuffer; ANativeWindow::cancelBuffer = hook_cancelBuffer; - ANativeWindow::lockBuffer = hook_lockBuffer; ANativeWindow::queueBuffer = hook_queueBuffer; ANativeWindow::query = hook_query; ANativeWindow::perform = hook_perform; + ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED; + ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED; + ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED; + ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED; + const_cast<int&>(ANativeWindow::minSwapInterval) = 0; const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; @@ -103,27 +109,54 @@ int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interv } int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window, - ANativeWindowBuffer** buffer) { + ANativeWindowBuffer** buffer, int* fenceFd) { SurfaceTextureClient* c = getSelf(window); - return c->dequeueBuffer(buffer); + return c->dequeueBuffer(buffer, fenceFd); } int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window, + ANativeWindowBuffer* buffer, int fenceFd) { + SurfaceTextureClient* c = getSelf(window); + return c->cancelBuffer(buffer, fenceFd); +} + +int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window, + ANativeWindowBuffer* buffer, int fenceFd) { + SurfaceTextureClient* c = getSelf(window); + return c->queueBuffer(buffer, fenceFd); +} + +int SurfaceTextureClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, + ANativeWindowBuffer** buffer) { + SurfaceTextureClient* c = getSelf(window); + int fenceFd = -1; + int result = c->dequeueBuffer(buffer, &fenceFd); + sp<Fence> fence(new Fence(fenceFd)); + int waitResult = fence->wait(Fence::TIMEOUT_NEVER); + if (waitResult != OK) { + ALOGE("hook_dequeueBuffer_DEPRECATED: Fence::wait returned an " + "error: %d", waitResult); + return waitResult; + } + return result; +} + +int SurfaceTextureClient::hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); - return c->cancelBuffer(buffer); + return c->cancelBuffer(buffer, -1); } -int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_lockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); - return c->lockBuffer(buffer); + return c->lockBuffer_DEPRECATED(buffer); } -int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); - return c->queueBuffer(buffer); + return c->queueBuffer(buffer, -1); } int SurfaceTextureClient::hook_query(const ANativeWindow* window, @@ -157,14 +190,16 @@ int SurfaceTextureClient::setSwapInterval(int interval) { return res; } -int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { +int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer, + int* fenceFd) { ATRACE_CALL(); ALOGV("SurfaceTextureClient::dequeueBuffer"); Mutex::Autolock lock(mMutex); int buf = -1; int reqW = mReqWidth ? mReqWidth : mUserWidth; int reqH = mReqHeight ? mReqHeight : mUserHeight; - status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH, + sp<Fence> fence; + status_t result = mSurfaceTexture->dequeueBuffer(&buf, fence, reqW, reqH, mReqFormat, mReqUsage); if (result < 0) { ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" @@ -185,11 +220,25 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { return result; } } + + if (fence.get()) { + *fenceFd = fence->dup(); + if (*fenceFd == -1) { + ALOGE("dequeueBuffer: error duping fence: %d", errno); + // dup() should never fail; something is badly wrong. Soldier on + // and hope for the best; the worst that should happen is some + // visible corruption that lasts until the next frame. + } + } else { + *fenceFd = -1; + } + *buffer = gbuf.get(); return OK; } -int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { +int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer, + int fenceFd) { ATRACE_CALL(); ALOGV("SurfaceTextureClient::cancelBuffer"); Mutex::Autolock lock(mMutex); @@ -197,7 +246,8 @@ int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { if (i < 0) { return i; } - mSurfaceTexture->cancelBuffer(i); + sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : NULL); + mSurfaceTexture->cancelBuffer(i, fence); return OK; } @@ -214,13 +264,13 @@ int SurfaceTextureClient::getSlotFromBufferLocked( return BAD_VALUE; } -int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { +int SurfaceTextureClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) { ALOGV("SurfaceTextureClient::lockBuffer"); Mutex::Autolock lock(mMutex); return OK; } -int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { +int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { ATRACE_CALL(); ALOGV("SurfaceTextureClient::queueBuffer"); Mutex::Autolock lock(mMutex); @@ -237,13 +287,15 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { return i; } + // Make sure the crop rectangle is entirely inside the buffer. Rect crop; mCrop.intersect(Rect(buffer->width, buffer->height), &crop); + sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : NULL); ISurfaceTexture::QueueBufferOutput output; ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode, - mTransform); + mTransform, fence); status_t err = mSurfaceTexture->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); @@ -692,78 +744,83 @@ status_t SurfaceTextureClient::lock( } ANativeWindowBuffer* out; - status_t err = dequeueBuffer(&out); + int fenceFd = -1; + status_t err = dequeueBuffer(&out, &fenceFd); ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); - err = lockBuffer(backBuffer.get()); - ALOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", - backBuffer->handle, strerror(-err)); - if (err == NO_ERROR) { - const Rect bounds(backBuffer->width, backBuffer->height); - - Region newDirtyRegion; - if (inOutDirtyBounds) { - newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); - newDirtyRegion.andSelf(bounds); - } else { - newDirtyRegion.set(bounds); - } + sp<Fence> fence(new Fence(fenceFd)); - // figure out if we can copy the frontbuffer back - const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); - const bool canCopyBack = (frontBuffer != 0 && - backBuffer->width == frontBuffer->width && - backBuffer->height == frontBuffer->height && - backBuffer->format == frontBuffer->format); - - if (canCopyBack) { - // copy the area that is invalid and not repainted this round - const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); - if (!copyback.isEmpty()) - copyBlt(backBuffer, frontBuffer, copyback); - } else { - // if we can't copy-back anything, modify the user's dirty - // region to make sure they redraw the whole buffer - newDirtyRegion.set(bounds); - mDirtyRegion.clear(); - Mutex::Autolock lock(mMutex); - for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) { - mSlots[i].dirtyRegion.clear(); - } - } + err = fence->wait(Fence::TIMEOUT_NEVER); + if (err != OK) { + ALOGE("Fence::wait failed (%s)", strerror(-err)); + cancelBuffer(out, fenceFd); + return err; + } + const Rect bounds(backBuffer->width, backBuffer->height); - { // scope for the lock - Mutex::Autolock lock(mMutex); - int backBufferSlot(getSlotFromBufferLocked(backBuffer.get())); - if (backBufferSlot >= 0) { - Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); - mDirtyRegion.subtract(dirtyRegion); - dirtyRegion = newDirtyRegion; - } - } + Region newDirtyRegion; + if (inOutDirtyBounds) { + newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); + newDirtyRegion.andSelf(bounds); + } else { + newDirtyRegion.set(bounds); + } - mDirtyRegion.orSelf(newDirtyRegion); - if (inOutDirtyBounds) { - *inOutDirtyBounds = newDirtyRegion.getBounds(); + // figure out if we can copy the frontbuffer back + const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); + const bool canCopyBack = (frontBuffer != 0 && + backBuffer->width == frontBuffer->width && + backBuffer->height == frontBuffer->height && + backBuffer->format == frontBuffer->format); + + if (canCopyBack) { + // copy the area that is invalid and not repainted this round + const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); + if (!copyback.isEmpty()) + copyBlt(backBuffer, frontBuffer, copyback); + } else { + // if we can't copy-back anything, modify the user's dirty + // region to make sure they redraw the whole buffer + newDirtyRegion.set(bounds); + mDirtyRegion.clear(); + Mutex::Autolock lock(mMutex); + for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) { + mSlots[i].dirtyRegion.clear(); } + } - void* vaddr; - status_t res = backBuffer->lock( - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - newDirtyRegion.bounds(), &vaddr); - ALOGW_IF(res, "failed locking buffer (handle = %p)", - backBuffer->handle); + { // scope for the lock + Mutex::Autolock lock(mMutex); + int backBufferSlot(getSlotFromBufferLocked(backBuffer.get())); + if (backBufferSlot >= 0) { + Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); + mDirtyRegion.subtract(dirtyRegion); + dirtyRegion = newDirtyRegion; + } + } - mLockedBuffer = backBuffer; - outBuffer->width = backBuffer->width; - outBuffer->height = backBuffer->height; - outBuffer->stride = backBuffer->stride; - outBuffer->format = backBuffer->format; - outBuffer->bits = vaddr; + mDirtyRegion.orSelf(newDirtyRegion); + if (inOutDirtyBounds) { + *inOutDirtyBounds = newDirtyRegion.getBounds(); } + + void* vaddr; + status_t res = backBuffer->lock( + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + newDirtyRegion.bounds(), &vaddr); + + ALOGW_IF(res, "failed locking buffer (handle = %p)", + backBuffer->handle); + + mLockedBuffer = backBuffer; + outBuffer->width = backBuffer->width; + outBuffer->height = backBuffer->height; + outBuffer->stride = backBuffer->stride; + outBuffer->format = backBuffer->format; + outBuffer->bits = vaddr; } return err; } @@ -778,7 +835,7 @@ status_t SurfaceTextureClient::unlockAndPost() status_t err = mLockedBuffer->unlock(); ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); - err = queueBuffer(mLockedBuffer.get()); + err = queueBuffer(mLockedBuffer.get(), -1); ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", mLockedBuffer->handle, strerror(-err)); diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index 741534b..e8863d3 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -2,14 +2,15 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE := SurfaceTexture_test +LOCAL_MODULE := libgui_test LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ - Surface_test.cpp \ + CpuConsumer_test.cpp \ SurfaceTextureClient_test.cpp \ SurfaceTexture_test.cpp \ + Surface_test.cpp \ LOCAL_SHARED_LIBRARIES := \ libEGL \ @@ -18,6 +19,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libgui \ libstlport \ + libsync \ libui \ libutils \ diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp new file mode 100644 index 0000000..371fb8b --- /dev/null +++ b/libs/gui/tests/CpuConsumer_test.cpp @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 "CpuConsumer_test" +//#define LOG_NDEBUG 0 +//#define LOG_NNDEBUG 0 + +#ifdef LOG_NNDEBUG +#define ALOGVV(...) ALOGV(__VA_ARGS__) +#else +#define ALOGVV(...) ((void)0) +#endif + +#include <gtest/gtest.h> +#include <gui/CpuConsumer.h> +#include <gui/SurfaceTextureClient.h> +#include <ui/GraphicBuffer.h> +#include <utils/String8.h> +#include <utils/Thread.h> +#include <utils/Mutex.h> +#include <utils/Condition.h> + +#include <ui/FramebufferNativeWindow.h> + +namespace android { + +struct CpuConsumerTestParams { + uint32_t width; + uint32_t height; + int maxLockedBuffers; + PixelFormat format; +}; + +::std::ostream& operator<<(::std::ostream& os, const CpuConsumerTestParams& p) { + return os << "[ (" << p.width << ", " << p.height << "), B:" + << p.maxLockedBuffers << ", F:0x" + << ::std::hex << p.format << "]"; +} + +class CpuConsumerTest : public ::testing::TestWithParam<CpuConsumerTestParams> { +protected: + + virtual void SetUp() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + CpuConsumerTestParams params = GetParam(); + ALOGV("** Starting test %s (%d x %d, %d, 0x%x)", + test_info->name(), + params.width, params.height, + params.maxLockedBuffers, params.format); + mCC = new CpuConsumer(params.maxLockedBuffers); + String8 name("CpuConsumer_Under_Test"); + mCC->setName(name); + mSTC = new SurfaceTextureClient(mCC->getProducerInterface()); + mANW = mSTC; + } + + virtual void TearDown() { + mANW.clear(); + mSTC.clear(); + mCC.clear(); + } + + class FrameWaiter : public CpuConsumer::FrameAvailableListener { + public: + FrameWaiter(): + mPendingFrames(0) { + } + + void waitForFrame() { + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + mCondition.wait(mMutex); + } + mPendingFrames--; + } + + virtual void onFrameAvailable() { + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mCondition.signal(); + } + + int mPendingFrames; + Mutex mMutex; + Condition mCondition; + }; + + // Note that SurfaceTexture will lose the notifications + // onBuffersReleased and onFrameAvailable as there is currently + // no way to forward the events. This DisconnectWaiter will not let the + // disconnect finish until finishDisconnect() is called. It will + // also block until a disconnect is called + class DisconnectWaiter : public BufferQueue::ConsumerListener { + public: + DisconnectWaiter () : + mWaitForDisconnect(false), + mPendingFrames(0) { + } + + void waitForFrame() { + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + mFrameCondition.wait(mMutex); + } + mPendingFrames--; + } + + virtual void onFrameAvailable() { + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mFrameCondition.signal(); + } + + virtual void onBuffersReleased() { + Mutex::Autolock lock(mMutex); + while (!mWaitForDisconnect) { + mDisconnectCondition.wait(mMutex); + } + } + + void finishDisconnect() { + Mutex::Autolock lock(mMutex); + mWaitForDisconnect = true; + mDisconnectCondition.signal(); + } + + private: + Mutex mMutex; + + bool mWaitForDisconnect; + Condition mDisconnectCondition; + + int mPendingFrames; + Condition mFrameCondition; + }; + + sp<CpuConsumer> mCC; + sp<SurfaceTextureClient> mSTC; + sp<ANativeWindow> mANW; +}; + +#define ASSERT_NO_ERROR(err, msg) \ + ASSERT_EQ(NO_ERROR, err) << msg << strerror(-err) + +void checkPixel(const CpuConsumer::LockedBuffer &buf, + uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b) { + // Ignores components that don't exist for given pixel + switch(buf.format) { + case HAL_PIXEL_FORMAT_RAW_SENSOR: { + String8 msg; + uint16_t *bPtr = (uint16_t*)buf.data; + bPtr += y * buf.stride + x; + // GRBG Bayer mosaic; only check the matching channel + switch( ((y & 1) << 1) | (x & 1) ) { + case 0: // G + case 3: // G + EXPECT_EQ(g, *bPtr); + break; + case 1: // R + EXPECT_EQ(r, *bPtr); + break; + case 2: // B + EXPECT_EQ(b, *bPtr); + break; + } + break; + } + default: { + ADD_FAILURE() << "Unknown format for check:" << buf.format; + break; + } + } +} + +// Fill a YV12 buffer with a multi-colored checkerboard pattern +void fillYV12Buffer(uint8_t* buf, int w, int h, int stride); + +// Fill a RAW sensor buffer with a multi-colored checkerboard pattern. +// Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern +// of [ R, B; G, W] +void fillBayerRawBuffer(uint8_t* buf, int w, int h, int stride) { + ALOGVV("fillBayerRawBuffer: %p with %d x %d, stride %d", buf, w, h ,stride); + // Blocks need to be even-width/height, aim for 8-wide otherwise + const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1; + const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1; + for (int y = 0; y < h; y+=2) { + uint16_t *bPtr1 = ((uint16_t*)buf) + stride*y; + uint16_t *bPtr2 = bPtr1 + stride; + for (int x = 0; x < w; x+=2) { + int blockX = (x / blockWidth ) & 1; + int blockY = (y / blockHeight) & 1; + unsigned short r = (blockX == blockY) ? 1000 : 200; + unsigned short g = blockY ? 1000: 200; + unsigned short b = blockX ? 1000: 200; + // GR row + *bPtr1++ = g; + *bPtr1++ = r; + // BG row + *bPtr2++ = b; + *bPtr2++ = g; + } + } + +} + +void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) { + uint32_t w = buf.width; + uint32_t h = buf.height; + const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1; + const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1; + const int blockRows = h / blockHeight; + const int blockCols = w / blockWidth; + + // Top-left square is red + checkPixel(buf, 0, 0, 1000, 200, 200); + checkPixel(buf, 1, 0, 1000, 200, 200); + checkPixel(buf, 0, 1, 1000, 200, 200); + checkPixel(buf, 1, 1, 1000, 200, 200); + + // One-right square is blue + checkPixel(buf, blockWidth, 0, 200, 200, 1000); + checkPixel(buf, blockWidth + 1, 0, 200, 200, 1000); + checkPixel(buf, blockWidth, 1, 200, 200, 1000); + checkPixel(buf, blockWidth + 1, 1, 200, 200, 1000); + + // One-down square is green + checkPixel(buf, 0, blockHeight, 200, 1000, 200); + checkPixel(buf, 1, blockHeight, 200, 1000, 200); + checkPixel(buf, 0, blockHeight + 1, 200, 1000, 200); + checkPixel(buf, 1, blockHeight + 1, 200, 1000, 200); + + // One-diag square is white + checkPixel(buf, blockWidth, blockHeight, 1000, 1000, 1000); + checkPixel(buf, blockWidth + 1, blockHeight, 1000, 1000, 1000); + checkPixel(buf, blockWidth, blockHeight + 1, 1000, 1000, 1000); + checkPixel(buf, blockWidth + 1, blockHeight + 1, 1000, 1000, 1000); + + // Test bottom-right pixel + const int maxBlockX = ((w-1) / blockWidth) & 0x1; + const int maxBlockY = ((w-1) / blockHeight) & 0x1; + unsigned short maxR = (maxBlockX == maxBlockY) ? 1000 : 200; + unsigned short maxG = maxBlockY ? 1000: 200; + unsigned short maxB = maxBlockX ? 1000: 200; + checkPixel(buf, w-1, h-1, maxR, maxG, maxB); +} + +void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, + const android_native_rect_t& rect); + +void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride); + +void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r, + uint8_t g, uint8_t b, uint8_t a); + +// Configures the ANativeWindow producer-side interface based on test parameters +void configureANW(const sp<ANativeWindow>& anw, + const CpuConsumerTestParams& params, + int maxBufferSlack) { + status_t err; + err = native_window_set_buffers_geometry(anw.get(), + params.width, params.height, params.format); + ASSERT_NO_ERROR(err, "set_buffers_geometry error: "); + + err = native_window_set_usage(anw.get(), + GRALLOC_USAGE_SW_WRITE_OFTEN); + ASSERT_NO_ERROR(err, "set_usage error: "); + + int minUndequeuedBuffers; + err = anw.get()->query(anw.get(), + NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + &minUndequeuedBuffers); + ASSERT_NO_ERROR(err, "query error: "); + + ALOGVV("Setting buffer count to %d", + maxBufferSlack + 1 + minUndequeuedBuffers); + err = native_window_set_buffer_count(anw.get(), + maxBufferSlack + 1 + minUndequeuedBuffers); + ASSERT_NO_ERROR(err, "set_buffer_count error: "); + +} + +// Produce one frame of image data; assumes format and resolution configuration +// is already done. +void produceOneFrame(const sp<ANativeWindow>& anw, + const CpuConsumerTestParams& params, + int64_t timestamp, uint32_t *stride) { + status_t err; + ANativeWindowBuffer* anb; + ALOGVV("Dequeue buffer from %p", anw.get()); + err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); + ASSERT_NO_ERROR(err, "dequeueBuffer error: "); + + ASSERT_TRUE(anb != NULL); + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + + *stride = buf->getStride(); + uint8_t* img = NULL; + + ALOGVV("Lock buffer from %p for write", anw.get()); + err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + ASSERT_NO_ERROR(err, "lock error: "); + + switch (params.format) { + case HAL_PIXEL_FORMAT_YV12: + fillYV12Buffer(img, params.width, params.height, *stride); + break; + case HAL_PIXEL_FORMAT_RAW_SENSOR: + fillBayerRawBuffer(img, params.width, params.height, buf->getStride()); + break; + default: + FAIL() << "Unknown pixel format under test!"; + break; + } + ALOGVV("Unlock buffer from %p", anw.get()); + err = buf->unlock(); + ASSERT_NO_ERROR(err, "unlock error: "); + + ALOGVV("Set timestamp to %p", anw.get()); + err = native_window_set_buffers_timestamp(anw.get(), timestamp); + ASSERT_NO_ERROR(err, "set_buffers_timestamp error: "); + + ALOGVV("Queue buffer to %p", anw.get()); + err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1); + ASSERT_NO_ERROR(err, "queueBuffer error:"); +}; + +TEST_P(CpuConsumerTest, FromCpuSingle) { + status_t err; + CpuConsumerTestParams params = GetParam(); + + // Set up + + ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, 1)); + + // Produce + + const int64_t time = 12345678L; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, + &stride)); + + // Consume + + CpuConsumer::LockedBuffer b; + err = mCC->lockNextBuffer(&b); + ASSERT_NO_ERROR(err, "getNextBuffer error: "); + + ASSERT_TRUE(b.data != NULL); + EXPECT_EQ(params.width, b.width); + EXPECT_EQ(params.height, b.height); + EXPECT_EQ(params.format, b.format); + EXPECT_EQ(stride, b.stride); + EXPECT_EQ(time, b.timestamp); + + checkBayerRawBuffer(b); + mCC->unlockBuffer(b); +} + +TEST_P(CpuConsumerTest, FromCpuManyInQueue) { + status_t err; + CpuConsumerTestParams params = GetParam(); + + const int numInQueue = 5; + // Set up + + ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, numInQueue)); + + // Produce + + const int64_t time[numInQueue] = { 1L, 2L, 3L, 4L, 5L}; + uint32_t stride[numInQueue]; + + for (int i = 0; i < numInQueue; i++) { + ALOGV("Producing frame %d", i); + ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i], + &stride[i])); + } + + // Consume + + for (int i = 0; i < numInQueue; i++) { + ALOGV("Consuming frame %d", i); + CpuConsumer::LockedBuffer b; + err = mCC->lockNextBuffer(&b); + ASSERT_NO_ERROR(err, "getNextBuffer error: "); + + ASSERT_TRUE(b.data != NULL); + EXPECT_EQ(params.width, b.width); + EXPECT_EQ(params.height, b.height); + EXPECT_EQ(params.format, b.format); + EXPECT_EQ(stride[i], b.stride); + EXPECT_EQ(time[i], b.timestamp); + + checkBayerRawBuffer(b); + + mCC->unlockBuffer(b); + } +} + +TEST_P(CpuConsumerTest, FromCpuLockMax) { + status_t err; + CpuConsumerTestParams params = GetParam(); + + // Set up + + ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1)); + + // Produce + + const int64_t time = 1234L; + uint32_t stride; + + for (int i = 0; i < params.maxLockedBuffers + 1; i++) { + ALOGV("Producing frame %d", i); + ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, + &stride)); + } + + // Consume + + CpuConsumer::LockedBuffer *b = new CpuConsumer::LockedBuffer[params.maxLockedBuffers]; + for (int i = 0; i < params.maxLockedBuffers; i++) { + ALOGV("Locking frame %d", i); + err = mCC->lockNextBuffer(&b[i]); + ASSERT_NO_ERROR(err, "getNextBuffer error: "); + + ASSERT_TRUE(b[i].data != NULL); + EXPECT_EQ(params.width, b[i].width); + EXPECT_EQ(params.height, b[i].height); + EXPECT_EQ(params.format, b[i].format); + EXPECT_EQ(stride, b[i].stride); + EXPECT_EQ(time, b[i].timestamp); + + checkBayerRawBuffer(b[i]); + } + + ALOGV("Locking frame %d (too many)", params.maxLockedBuffers); + CpuConsumer::LockedBuffer bTooMuch; + err = mCC->lockNextBuffer(&bTooMuch); + ASSERT_TRUE(err == INVALID_OPERATION) << "Allowing too many locks"; + + ALOGV("Unlocking frame 0"); + err = mCC->unlockBuffer(b[0]); + ASSERT_NO_ERROR(err, "Could not unlock buffer 0: "); + + ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers); + err = mCC->lockNextBuffer(&bTooMuch); + ASSERT_NO_ERROR(err, "Did not allow new lock after unlock"); + + ASSERT_TRUE(bTooMuch.data != NULL); + EXPECT_EQ(params.width, bTooMuch.width); + EXPECT_EQ(params.height, bTooMuch.height); + EXPECT_EQ(params.format, bTooMuch.format); + EXPECT_EQ(stride, bTooMuch.stride); + EXPECT_EQ(time, bTooMuch.timestamp); + + checkBayerRawBuffer(bTooMuch); + + ALOGV("Unlocking extra buffer"); + err = mCC->unlockBuffer(bTooMuch); + ASSERT_NO_ERROR(err, "Could not unlock extra buffer: "); + + ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1); + err = mCC->lockNextBuffer(&b[0]); + ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow"; + + for (int i = 1; i < params.maxLockedBuffers; i++) { + mCC->unlockBuffer(b[i]); + } + + delete[] b; + +} + +CpuConsumerTestParams rawTestSets[] = { + { 512, 512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 512, 512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 100, 100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR}, + { 100, 100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR} +}; + +INSTANTIATE_TEST_CASE_P(RawTests, + CpuConsumerTest, + ::testing::ValuesIn(rawTestSets)); + +} // namespace android diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 7d8dd33..59b9efd 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -180,129 +180,129 @@ TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) { TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) { ANativeWindowBuffer* buf; - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) { ANativeWindowBuffer* buf; EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) { ANativeWindowBuffer* buf; EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) { ANativeWindowBuffer* buf; EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) { ANativeWindowBuffer* buf; EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) { ANativeWindowBuffer* buf; EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(1, buf->width); EXPECT_EQ(1, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) { sp<SurfaceTexture> st(mST); ANativeWindowBuffer* buf; EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); EXPECT_EQ(16, buf->width); EXPECT_EQ(8, buf->height); EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1)); } TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) { ANativeWindowBuffer* buf[2]; ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); EXPECT_EQ(16, buf[0]->width); EXPECT_EQ(16, buf[1]->width); EXPECT_EQ(8, buf[0]->height); EXPECT_EQ(8, buf[1]->height); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1)); } TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) { ANativeWindowBuffer* buf[2]; ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); EXPECT_EQ(16, buf[0]->width); EXPECT_EQ(16, buf[1]->width); EXPECT_EQ(8, buf[0]->height); EXPECT_EQ(8, buf[1]->height); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); EXPECT_EQ(12, buf[0]->width); EXPECT_EQ(12, buf[1]->width); EXPECT_EQ(24, buf[0]->height); EXPECT_EQ(24, buf[1]->height); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1)); } TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { @@ -310,18 +310,18 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { ASSERT_EQ(OK, mST->setSynchronousMode(false)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(OK, mST->updateTexImage()); ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(OK, mST->updateTexImage()); @@ -332,15 +332,15 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) { android_native_buffer_t* buf[3]; ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); EXPECT_NE(buf[0], buf[1]); EXPECT_NE(buf[1], buf[2]); EXPECT_NE(buf[2], buf[0]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); EXPECT_EQ(OK, mST->updateTexImage()); @@ -353,19 +353,19 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) { android_native_buffer_t* buf[3]; ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); EXPECT_NE(buf[0], buf[1]); EXPECT_NE(buf[1], buf[2]); EXPECT_NE(buf[2], buf[0]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]); } @@ -375,20 +375,20 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); EXPECT_NE(buf[0], buf[1]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); EXPECT_NE(buf[1], buf[2]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]); } @@ -400,16 +400,16 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) android_native_buffer_t* firstBuf; ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &firstBuf)); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf)); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), firstBuf); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1)); EXPECT_NE(buf[0], buf[1]); EXPECT_NE(buf[1], buf[2]); EXPECT_NE(buf[2], buf[0]); @@ -422,24 +422,24 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); // We should be able to dequeue all the buffers before we've queued mANWy. - EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); + EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1)); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); + EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); // Once we've queued a buffer, however we should not be able to dequeue more // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case. - EXPECT_EQ(-EBUSY, mANW->dequeueBuffer(mANW.get(), &buf[1])); + EXPECT_EQ(-EBUSY, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1)); + ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1)); } TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) { @@ -449,8 +449,8 @@ TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) { ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 4, 4)); android_native_buffer_t* buf; - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf)); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf)); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf)); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf, -1)); ASSERT_EQ(OK, mST->updateTexImage()); Rect crop = mST->getCurrentCrop(); @@ -500,20 +500,20 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) { ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); // dequeue/queue/update so we have a current buffer - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); mST->updateTexImage(); MyThread* thread = new MyThread(mST); sp<Thread> threadBase(thread); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); thread->run(); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - //ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); - //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1)); + //ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2])); + //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1)); thread->bufferDequeued(); thread->requestExitAndWait(); } @@ -522,8 +522,8 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) { android_native_buffer_t* buf[3]; float mtx[16] = {}; ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); ASSERT_EQ(OK, mST->updateTexImage()); mST->getTransformMatrix(mtx); @@ -552,8 +552,8 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) android_native_buffer_t* buf[3]; float mtx[16] = {}; ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); ASSERT_EQ(OK, mST->updateTexImage()); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers mST->getTransformMatrix(mtx); @@ -590,9 +590,9 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWi ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0])); + ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop)); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); + ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1)); ASSERT_EQ(OK, mST->updateTexImage()); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers mST->getTransformMatrix(mtx); diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index 078c17b..0060cf7 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -672,18 +672,19 @@ void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r, // Calls to this function should be wrapped in an ASSERT_NO_FATAL_FAILURE(). void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) { android_native_buffer_t* anb; - ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), + &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf->getNativeBuffer())); uint8_t* img = NULL; ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img))); fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride()); ASSERT_EQ(NO_ERROR, buf->unlock()); - ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer())); + ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(), + -1)); } TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { @@ -696,18 +697,19 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); // Fill the buffer with the a checkerboard pattern uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), + -1)); mST->updateTexImage(); @@ -741,18 +743,19 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); // Fill the buffer with the a checkerboard pattern uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), + -1)); mST->updateTexImage(); @@ -801,19 +804,18 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop)); ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), - buf->getNativeBuffer())); uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop); buf->unlock(); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), - buf->getNativeBuffer())); + buf->getNativeBuffer(), -1)); mST->updateTexImage(); @@ -877,7 +879,8 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { virtual bool threadLoop() { for (int i = 0; i < numFrames; i++) { ANativeWindowBuffer* anb; - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + if (native_window_dequeue_buffer_and_wait(mANW.get(), + &anb) != NO_ERROR) { return false; } if (anb == NULL) { @@ -885,10 +888,6 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { } sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()) - != NO_ERROR) { - return false; - } const int yuvTexOffsetY = 0; int stride = buf->getStride(); @@ -932,7 +931,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { } buf->unlock(); - if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()) + if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1) != NO_ERROR) { return false; } @@ -1093,13 +1092,14 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { for (int numFrames =0 ; numFrames < 2; numFrames ++) { - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + if (native_window_dequeue_buffer_and_wait(mANW.get(), + &anb) != NO_ERROR) { return false; } if (anb == NULL) { return false; } - if (mANW->queueBuffer(mANW.get(), anb) + if (mANW->queueBuffer(mANW.get(), anb, -1) != NO_ERROR) { return false; } @@ -1147,11 +1147,11 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { ANativeWindowBuffer *anb; - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); EXPECT_EQ(OK,mST->updateTexImage()); EXPECT_EQ(OK,mST->updateTexImage()); @@ -1163,8 +1163,8 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { ASSERT_EQ(OK, mST->setSynchronousMode(true)); - EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); // Will fail here if mCurrentTexture is not cleared properly mFW->waitForFrame(); @@ -1193,8 +1193,8 @@ TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) { android_native_rect_t odd = {23, 78, 123, 477}; ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd)); - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); mFW->waitForFrame(); EXPECT_EQ(OK,mST->updateTexImage()); Rect r = mST->getCurrentCrop(); @@ -1227,8 +1227,8 @@ TEST_F(SurfaceTextureGLTest, CroppedScalingMode) { // The crop is in the shape of (320, 180) === 16 x 9 android_native_rect_t standard = {10, 20, 330, 200}; ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard)); - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); mFW->waitForFrame(); EXPECT_EQ(OK,mST->updateTexImage()); Rect r = mST->getCurrentCrop(); @@ -1238,8 +1238,8 @@ TEST_F(SurfaceTextureGLTest, CroppedScalingMode) { // make this wider then desired aspect 239 x 100 (2.39:1) android_native_rect_t wide = {20, 30, 259, 130}; ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide)); - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); mFW->waitForFrame(); EXPECT_EQ(OK,mST->updateTexImage()); r = mST->getCurrentCrop(); @@ -1250,8 +1250,8 @@ TEST_F(SurfaceTextureGLTest, CroppedScalingMode) { // This image is taller then desired aspect 400 x 300 (4:3) android_native_rect_t narrow = {0, 0, 400, 300}; ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow)); - EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb)); - EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); + EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); mFW->waitForFrame(); EXPECT_EQ(OK,mST->updateTexImage()); r = mST->getCurrentCrop(); @@ -1278,31 +1278,34 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { ANativeWindowBuffer* anb; // Frame 1 - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + if (native_window_dequeue_buffer_and_wait(mANW.get(), + &anb) != NO_ERROR) { return false; } if (anb == NULL) { return false; } - if (mANW->queueBuffer(mANW.get(), anb) + if (mANW->queueBuffer(mANW.get(), anb, -1) != NO_ERROR) { return false; } // Frame 2 - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + if (native_window_dequeue_buffer_and_wait(mANW.get(), + &anb) != NO_ERROR) { return false; } if (anb == NULL) { return false; } - if (mANW->queueBuffer(mANW.get(), anb) + if (mANW->queueBuffer(mANW.get(), anb, -1) != NO_ERROR) { return false; } // Frame 3 - error expected - mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb); + mDequeueError = native_window_dequeue_buffer_and_wait(mANW.get(), + &anb); return false; } @@ -1346,26 +1349,29 @@ TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) { // make sure it works with small textures mST->setDefaultBufferSize(16, texHeight); - EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); EXPECT_EQ(16, anb->width); EXPECT_EQ(texHeight, anb->height); - EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); EXPECT_EQ(NO_ERROR, mST->updateTexImage()); // make sure it works with GL_MAX_TEXTURE_SIZE mST->setDefaultBufferSize(maxTextureSize, texHeight); - EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); EXPECT_EQ(maxTextureSize, anb->width); EXPECT_EQ(texHeight, anb->height); - EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); EXPECT_EQ(NO_ERROR, mST->updateTexImage()); // make sure it fails with GL_MAX_TEXTURE_SIZE+1 mST->setDefaultBufferSize(maxTextureSize+1, texHeight); - EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); EXPECT_EQ(maxTextureSize+1, anb->width); EXPECT_EQ(texHeight, anb->height); - EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); ASSERT_NE(NO_ERROR, mST->updateTexImage()); } @@ -2134,11 +2140,11 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); android_native_buffer_t* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); - ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); // Fill the buffer with green uint8_t* img = NULL; @@ -2146,7 +2152,8 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 0, 255); buf->unlock(); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), + -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); @@ -2157,12 +2164,11 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { for (int i = 0; i < 4; i++) { SCOPED_TRACE(String8::format("frame %d", i).string()); - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), + &anb)); ASSERT_TRUE(anb != NULL); buf = new GraphicBuffer(anb, false); - ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), - buf->getNativeBuffer())); // Fill the buffer with red ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, @@ -2171,7 +2177,7 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { 0, 255); ASSERT_EQ(NO_ERROR, buf->unlock()); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), - buf->getNativeBuffer())); + buf->getNativeBuffer(), -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index b585d68..5046bf5 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -97,22 +97,23 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); ANativeWindowBuffer* buf = 0; - status_t err = anw->dequeueBuffer(anw.get(), &buf); + status_t err = native_window_dequeue_buffer_and_wait(anw.get(), &buf); if (err) { // we could fail if GRALLOC_USAGE_PROTECTED is not supported. // that's okay as long as this is the reason for the failure. // try again without the GRALLOC_USAGE_PROTECTED bit. ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0)); - ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), + &buf)); return; } - ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf)); + ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf, -1)); for (int i = 0; i < 4; i++) { // Loop to make sure SurfaceFlinger has retired a protected buffer. - ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); - ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf)); - ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf)); + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), + &buf)); + ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } heap = 0; w = h = fmt = 0; |