diff options
author | Mathias Agopian <mathias@google.com> | 2012-03-07 19:36:08 -0800 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-03-07 19:36:08 -0800 |
commit | 8c79817dc6459baa2c79db88e3c3e4d5c07d6a61 (patch) | |
tree | d7e4dfcc8a7851d5851750989664ec81ca620d6d /libs/gui | |
parent | 08965ec67ada98f63f8ac879cc44c8b0e7ff046d (diff) | |
download | frameworks_base-8c79817dc6459baa2c79db88e3c3e4d5c07d6a61.zip frameworks_base-8c79817dc6459baa2c79db88e3c3e4d5c07d6a61.tar.gz frameworks_base-8c79817dc6459baa2c79db88e3c3e4d5c07d6a61.tar.bz2 |
remove files that moved to frameworks/native
Change-Id: I140d291e520097b1148930f736823650e08488f7
Diffstat (limited to 'libs/gui')
24 files changed, 0 insertions, 7874 deletions
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk deleted file mode 100644 index 2f4ac62..0000000 --- a/libs/gui/Android.mk +++ /dev/null @@ -1,53 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - BitTube.cpp \ - BufferQueue.cpp \ - DisplayEventReceiver.cpp \ - IDisplayEventConnection.cpp \ - ISensorEventConnection.cpp \ - ISensorServer.cpp \ - ISurfaceTexture.cpp \ - Sensor.cpp \ - SensorEventQueue.cpp \ - SensorManager.cpp \ - SurfaceTexture.cpp \ - SurfaceTextureClient.cpp \ - ISurfaceComposer.cpp \ - ISurface.cpp \ - ISurfaceComposerClient.cpp \ - IGraphicBufferAlloc.cpp \ - LayerState.cpp \ - Surface.cpp \ - SurfaceComposerClient.cpp \ - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libbinder \ - libhardware \ - libhardware_legacy \ - libui \ - libEGL \ - libGLESv2 \ - - -LOCAL_MODULE:= libgui - -ifeq ($(TARGET_BOARD_PLATFORM), omap4) - LOCAL_CFLAGS += -DUSE_FENCE_SYNC -endif -ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) - LOCAL_CFLAGS += -DUSE_FENCE_SYNC -endif - -ifeq ($(TARGET_BOARD_PLATFORM), tegra) - LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER -endif - -include $(BUILD_SHARED_LIBRARY) - -ifeq (,$(ONE_SHOT_MAKEFILE)) -include $(call first-makefiles-under,$(LOCAL_PATH)) -endif diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp deleted file mode 100644 index 55f4178..0000000 --- a/libs/gui/BitTube.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <fcntl.h> -#include <signal.h> -#include <unistd.h> - -#include <utils/Errors.h> - -#include <binder/Parcel.h> - -#include <gui/BitTube.h> - -namespace android { -// ---------------------------------------------------------------------------- - -BitTube::BitTube() - : mSendFd(-1), mReceiveFd(-1) -{ - int fds[2]; - if (pipe(fds) == 0) { - mReceiveFd = fds[0]; - mSendFd = fds[1]; - fcntl(mReceiveFd, F_SETFL, O_NONBLOCK); - fcntl(mSendFd, F_SETFL, O_NONBLOCK); - // ignore SIGPIPE, we handle write errors through EPIPE instead - signal(SIGPIPE, SIG_IGN); - } else { - mReceiveFd = -errno; - ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); - } -} - -BitTube::BitTube(const Parcel& data) - : mSendFd(-1), mReceiveFd(-1) -{ - mReceiveFd = dup(data.readFileDescriptor()); - if (mReceiveFd >= 0) { - fcntl(mReceiveFd, F_SETFL, O_NONBLOCK); - } else { - mReceiveFd = -errno; - ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)", - strerror(-mReceiveFd)); - } -} - -BitTube::~BitTube() -{ - if (mSendFd >= 0) - close(mSendFd); - - if (mReceiveFd >= 0) - close(mReceiveFd); -} - -status_t BitTube::initCheck() const -{ - if (mReceiveFd < 0) { - return status_t(mReceiveFd); - } - return NO_ERROR; -} - -int BitTube::getFd() const -{ - return mReceiveFd; -} - -ssize_t BitTube::write(void const* vaddr, size_t size) -{ - ssize_t err, len; - do { - len = ::write(mSendFd, vaddr, size); - err = len < 0 ? errno : 0; - } while (err == EINTR); - return err == 0 ? len : -err; - -} - -ssize_t BitTube::read(void* vaddr, size_t size) -{ - ssize_t err, len; - do { - len = ::read(mReceiveFd, vaddr, size); - err = len < 0 ? errno : 0; - } while (err == EINTR); - if (err == EAGAIN || err == EWOULDBLOCK) { - // EAGAIN means that we have non-blocking I/O but there was - // no data to be read. Nothing the client should care about. - return 0; - } - return err == 0 ? len : -err; -} - -status_t BitTube::writeToParcel(Parcel* reply) const -{ - if (mReceiveFd < 0) - return -EINVAL; - - status_t result = reply->writeDupFileDescriptor(mReceiveFd); - close(mReceiveFd); - mReceiveFd = -1; - return result; -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp deleted file mode 100644 index cb8abdd..0000000 --- a/libs/gui/BufferQueue.cpp +++ /dev/null @@ -1,957 +0,0 @@ -/* - * 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 "BufferQueue" -//#define LOG_NDEBUG 0 -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include <gui/BufferQueue.h> -#include <gui/ISurfaceComposer.h> -#include <private/gui/ComposerService.h> - -#include <utils/Log.h> -#include <gui/SurfaceTexture.h> -#include <utils/Trace.h> - -// This compile option causes SurfaceTexture to return the buffer that is currently -// attached to the GL texture from dequeueBuffer when no other buffers are -// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do -// implicit cross-process synchronization to prevent the buffer from being -// written to before the buffer has (a) been detached from the GL texture and -// (b) all GL reads from the buffer have completed. - -// During refactoring, do not support dequeuing the current buffer -#undef ALLOW_DEQUEUE_CURRENT_BUFFER - -#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER -#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true -#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled" -#else -#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false -#endif - -// Macros for including the BufferQueue name in log messages -#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) -#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) -#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) -#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) -#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) - -#define ATRACE_BUFFER_INDEX(index) \ - char ___traceBuf[1024]; \ - snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index)); \ - android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); - -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); -} - -BufferQueue::BufferQueue( bool allowSynchronousMode ) : - mDefaultWidth(1), - mDefaultHeight(1), - mPixelFormat(PIXEL_FORMAT_RGBA_8888), - mBufferCount(MIN_ASYNC_BUFFER_SLOTS), - mClientBufferCount(0), - mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), - mNextTransform(0), - mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mSynchronousMode(false), - mAllowSynchronousMode(allowSynchronousMode), - mConnectedApi(NO_CONNECTED_API), - mAbandoned(false), - mFrameCounter(0), - mBufferHasBeenQueued(false) -{ - // Choose a name using the PID and a process-unique ID. - mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - - ST_LOGV("BufferQueue"); - sp<ISurfaceComposer> composer(ComposerService::getComposerService()); - mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); - mNextCrop.makeInvalid(); -} - -BufferQueue::~BufferQueue() { - ST_LOGV("~BufferQueue"); -} - -status_t BufferQueue::setBufferCountServerLocked(int bufferCount) { - if (bufferCount > NUM_BUFFER_SLOTS) - return BAD_VALUE; - - // special-case, nothing to do - if (bufferCount == mBufferCount) - return OK; - - if (!mClientBufferCount && - bufferCount >= mBufferCount) { - // easy, we just have more buffers - mBufferCount = bufferCount; - mServerBufferCount = bufferCount; - mDequeueCondition.broadcast(); - } else { - // we're here because we're either - // - reducing the number of available buffers - // - or there is a client-buffer-count in effect - - // less than 2 buffers is never allowed - if (bufferCount < 2) - return BAD_VALUE; - - // when there is non client-buffer-count in effect, the client is not - // allowed to dequeue more than one buffer at a time, - // so the next time they dequeue a buffer, we know that they don't - // own one. the actual resizing will happen during the next - // dequeueBuffer. - - mServerBufferCount = bufferCount; - } - return OK; -} - -bool BufferQueue::isSynchronousMode() const { - Mutex::Autolock lock(mMutex); - return mSynchronousMode; -} - -void BufferQueue::setConsumerName(const String8& name) { - Mutex::Autolock lock(mMutex); - mConsumerName = name; -} - -void BufferQueue::setFrameAvailableListener( - const sp<FrameAvailableListener>& listener) { - ST_LOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - -status_t BufferQueue::setBufferCount(int bufferCount) { - ST_LOGV("setBufferCount: count=%d", bufferCount); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - if (bufferCount > NUM_BUFFER_SLOTS) { - ST_LOGE("setBufferCount: bufferCount larger than slots available"); - return BAD_VALUE; - } - - // Error out if the user has dequeued buffers - for (int i=0 ; i<mBufferCount ; i++) { - if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { - ST_LOGE("setBufferCount: client owns some buffers"); - return -EINVAL; - } - } - - const int minBufferSlots = mSynchronousMode ? - MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; - if (bufferCount == 0) { - mClientBufferCount = 0; - bufferCount = (mServerBufferCount >= minBufferSlots) ? - mServerBufferCount : minBufferSlots; - return setBufferCountServerLocked(bufferCount); - } - - if (bufferCount < minBufferSlots) { - ST_LOGE("setBufferCount: requested buffer count (%d) is less than " - "minimum (%d)", bufferCount, minBufferSlots); - return BAD_VALUE; - } - - // here we're guaranteed that the client doesn't have dequeued buffers - // and will release all of its buffer references. - freeAllBuffersLocked(); - mBufferCount = bufferCount; - mClientBufferCount = bufferCount; - mBufferHasBeenQueued = false; - mQueue.clear(); - mDequeueCondition.broadcast(); - return OK; -} - -int BufferQueue::query(int what, int* outValue) -{ - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("query: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - - int value; - switch (what) { - case NATIVE_WINDOW_WIDTH: - value = mDefaultWidth; - break; - case NATIVE_WINDOW_HEIGHT: - value = mDefaultHeight; - break; - case NATIVE_WINDOW_FORMAT: - value = mPixelFormat; - break; - case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = mSynchronousMode ? - (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; - break; - default: - return BAD_VALUE; - } - outValue[0] = value; - return NO_ERROR; -} - -status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - ATRACE_CALL(); - ST_LOGV("requestBuffer: slot=%d", slot); - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - if (slot < 0 || mBufferCount <= slot) { - ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", - mBufferCount, slot); - return BAD_VALUE; - } - mSlots[slot].mRequestBufferCalled = true; - *buf = mSlots[slot].mGraphicBuffer; - return NO_ERROR; -} - -status_t BufferQueue::dequeueBuffer(int *outBuf, 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); - - if ((w && !h) || (!w && h)) { - ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); - return BAD_VALUE; - } - - status_t returnFlags(OK); - EGLDisplay dpy = EGL_NO_DISPLAY; - EGLSyncKHR fence = EGL_NO_SYNC_KHR; - - { // Scope for the lock - Mutex::Autolock lock(mMutex); - - int found = -1; - int foundSync = -1; - int dequeuedCount = 0; - bool tryAgain = true; - while (tryAgain) { - if (mAbandoned) { - ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - - // We need to wait for the FIFO to drain if the number of buffer - // needs to change. - // - // The condition "number of buffers needs to change" is true if - // - the client doesn't care about how many buffers there are - // - AND the actual number of buffer is different from what was - // set in the last setBufferCountServer() - // - OR - - // setBufferCountServer() was set to a value incompatible with - // the synchronization mode (for instance because the sync mode - // changed since) - // - // As long as this condition is true AND the FIFO is not empty, we - // wait on mDequeueCondition. - - const int minBufferCountNeeded = mSynchronousMode ? - MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; - - const bool numberOfBuffersNeedsToChange = !mClientBufferCount && - ((mServerBufferCount != mBufferCount) || - (mServerBufferCount < minBufferCountNeeded)); - - if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) { - // wait for the FIFO to drain - mDequeueCondition.wait(mMutex); - // NOTE: we continue here because we need to reevaluate our - // whole state (eg: we could be abandoned or disconnected) - continue; - } - - if (numberOfBuffersNeedsToChange) { - // here we're guaranteed that mQueue is empty - freeAllBuffersLocked(); - // XXX: signal? - mBufferCount = mServerBufferCount; - if (mBufferCount < minBufferCountNeeded) - mBufferCount = minBufferCountNeeded; - mBufferHasBeenQueued = false; - returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; - } - - // 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; - if (state == BufferSlot::DEQUEUED) { - dequeuedCount++; - } - - // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) - // but dequeuing the current buffer is disabled. - if (false) { - // This functionality has been temporarily removed so - // BufferQueue and SurfaceTexture can be refactored into - // separate objects - } else { - if (state == BufferSlot::FREE) { - /* We return the oldest of the free buffers to avoid - * stalling the producer if possible. This is because - * the consumer may still have pending reads of the - * buffers in flight. - */ - bool isOlder = mSlots[i].mFrameNumber < - mSlots[found].mFrameNumber; - if (found < 0 || isOlder) { - foundSync = i; - found = i; - } - } - } - } - - // clients are not allowed to dequeue more than one buffer - // if they didn't set a buffer count. - if (!mClientBufferCount && dequeuedCount) { - ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " - "setting the buffer count"); - return -EINVAL; - } - - // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the - // MIN_UNDEQUEUED_BUFFERS check below. - if (mBufferHasBeenQueued) { - // make sure the client is not trying to dequeue more buffers - // than allowed. - const int avail = mBufferCount - (dequeuedCount+1); - if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { - ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded " - "(dequeued=%d)", - MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), - dequeuedCount); - return -EBUSY; - } - } - - // if no buffer is found, wait for a buffer to be released - tryAgain = found == INVALID_BUFFER_SLOT; - if (tryAgain) { - mDequeueCondition.wait(mMutex); - } - } - - - if (found == INVALID_BUFFER_SLOT) { - // This should not happen. - ST_LOGE("dequeueBuffer: no available buffer slots"); - return -EBUSY; - } - - const int buf = found; - *outBuf = found; - - ATRACE_BUFFER_INDEX(buf); - - const bool useDefaultSize = !w && !h; - if (useDefaultSize) { - // use the default size - w = mDefaultWidth; - 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; - - const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); - if ((buffer == NULL) || - (uint32_t(buffer->width) != w) || - (uint32_t(buffer->height) != h) || - (uint32_t(buffer->format) != format) || - ((uint32_t(buffer->usage) & usage) != usage)) - { - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - status_t error; - sp<GraphicBuffer> graphicBuffer( - mGraphicBufferAlloc->createGraphicBuffer( - w, h, format, usage, &error)); - if (graphicBuffer == 0) { - ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " - "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].mEglDisplay = EGL_NO_DISPLAY; - - - - - returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; - } - - dpy = mSlots[buf].mEglDisplay; - fence = mSlots[buf].mFence; - mSlots[buf].mFence = EGL_NO_SYNC_KHR; - } // end lock scope - - if (fence != EGL_NO_SYNC_KHR) { - EGLint result = eglClientWaitSyncKHR(dpy, fence, 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. - if (result == EGL_FALSE) { - ALOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError()); - } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { - ALOGE("dequeueBuffer: timeout waiting for fence"); - } - eglDestroySyncKHR(dpy, fence); - - } - - ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, - mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); - - return returnFlags; -} - -status_t BufferQueue::setSynchronousMode(bool enabled) { - ATRACE_CALL(); - ST_LOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - - status_t err = OK; - if (!mAllowSynchronousMode && enabled) - return err; - - if (!enabled) { - // going to asynchronous mode, drain the queue - err = drainQueueLocked(); - if (err != NO_ERROR) - return err; - } - - if (mSynchronousMode != enabled) { - // - if we're going to asynchronous mode, the queue is guaranteed to be - // empty here - // - if the client set the number of buffers, we're guaranteed that - // we have at least 3 (because we don't allow less) - mSynchronousMode = enabled; - mDequeueCondition.broadcast(); - } - return err; -} - -status_t BufferQueue::queueBuffer(int buf, int64_t timestamp, - uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(buf); - - ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp); - - sp<FrameAvailableListener> listener; - - { // scope for the lock - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - if (buf < 0 || buf >= mBufferCount) { - ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", - mBufferCount, buf); - return -EINVAL; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ST_LOGE("queueBuffer: slot %d is not owned by the client " - "(state=%d)", buf, mSlots[buf].mBufferState); - return -EINVAL; - } else if (!mSlots[buf].mRequestBufferCalled) { - ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " - "buffer", buf); - return -EINVAL; - } - - if (mSynchronousMode) { - // In synchronous mode we queue all buffers in a FIFO. - mQueue.push_back(buf); - - // Synchronous mode always signals that an additional frame should - // be consumed. - listener = mFrameAvailableListener; - } else { - // In asynchronous mode we only keep the most recent buffer. - if (mQueue.empty()) { - mQueue.push_back(buf); - - // Asynchronous mode only signals that a frame should be - // consumed if no previous frame was pending. If a frame were - // pending then the consumer would have already been notified. - listener = mFrameAvailableListener; - } else { - Fifo::iterator front(mQueue.begin()); - // buffer currently queued is freed - mSlots[*front].mBufferState = BufferSlot::FREE; - // and we record the new buffer index in the queued list - *front = buf; - } - } - - mSlots[buf].mBufferState = BufferSlot::QUEUED; - mSlots[buf].mCrop = mNextCrop; - mSlots[buf].mTransform = mNextTransform; - mSlots[buf].mScalingMode = mNextScalingMode; - mSlots[buf].mTimestamp = timestamp; - mFrameCounter++; - mSlots[buf].mFrameNumber = mFrameCounter; - - mBufferHasBeenQueued = true; - mDequeueCondition.broadcast(); - - *outWidth = mDefaultWidth; - *outHeight = mDefaultHeight; - *outTransform = 0; - - ATRACE_INT(mConsumerName.string(), mQueue.size()); - } // scope for the lock - - // call back without lock held - if (listener != 0) { - listener->onFrameAvailable(); - } - return OK; -} - -void BufferQueue::cancelBuffer(int buf) { - ATRACE_CALL(); - ST_LOGV("cancelBuffer: slot=%d", buf); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGW("cancelBuffer: BufferQueue has been abandoned!"); - return; - } - - if (buf < 0 || buf >= mBufferCount) { - ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", - mBufferCount, buf); - return; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); - return; - } - mSlots[buf].mBufferState = BufferSlot::FREE; - mSlots[buf].mFrameNumber = 0; - mDequeueCondition.broadcast(); -} - -status_t BufferQueue::setCrop(const Rect& crop) { - ATRACE_CALL(); - ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right, - crop.bottom); - - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("setCrop: BufferQueue has been abandoned!"); - return NO_INIT; - } - mNextCrop = crop; - return OK; -} - -status_t BufferQueue::setTransform(uint32_t transform) { - ATRACE_CALL(); - ST_LOGV("setTransform: xform=%#x", transform); - Mutex::Autolock lock(mMutex); - if (mAbandoned) { - ST_LOGE("setTransform: BufferQueue has been abandoned!"); - return NO_INIT; - } - mNextTransform = transform; - return OK; -} - -status_t BufferQueue::setScalingMode(int mode) { - ATRACE_CALL(); - ST_LOGV("setScalingMode: mode=%d", mode); - - switch (mode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - break; - default: - ST_LOGE("unknown scaling mode: %d", mode); - return BAD_VALUE; - } - - Mutex::Autolock lock(mMutex); - mNextScalingMode = mode; - return OK; -} - -status_t BufferQueue::connect(int api, - uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - ATRACE_CALL(); - ST_LOGV("connect: api=%d", api); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("connect: BufferQueue has been abandoned!"); - return NO_INIT; - } - - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mConnectedApi != NO_CONNECTED_API) { - ST_LOGE("connect: already connected (cur=%d, req=%d)", - mConnectedApi, api); - err = -EINVAL; - } else { - mConnectedApi = api; - *outWidth = mDefaultWidth; - *outHeight = mDefaultHeight; - *outTransform = 0; - } - break; - default: - err = -EINVAL; - break; - } - - mBufferHasBeenQueued = false; - - return err; -} - -status_t BufferQueue::disconnect(int api) { - ATRACE_CALL(); - ST_LOGV("disconnect: api=%d", api); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - // it is not really an error to disconnect after the surface - // has been abandoned, it should just be a no-op. - return NO_ERROR; - } - - int err = NO_ERROR; - switch (api) { - case NATIVE_WINDOW_API_EGL: - case NATIVE_WINDOW_API_CPU: - case NATIVE_WINDOW_API_MEDIA: - case NATIVE_WINDOW_API_CAMERA: - if (mConnectedApi == api) { - drainQueueAndFreeBuffersLocked(); - mConnectedApi = NO_CONNECTED_API; - mNextCrop.makeInvalid(); - mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; - mNextTransform = 0; - mDequeueCondition.broadcast(); - } else { - ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", - mConnectedApi, api); - err = -EINVAL; - } - break; - default: - ST_LOGE("disconnect: unknown API %d", api); - err = -EINVAL; - break; - } - return err; -} - -void BufferQueue::dump(String8& result) const -{ - char buffer[1024]; - BufferQueue::dump(result, "", buffer, 1024); -} - -void BufferQueue::dump(String8& result, const char* prefix, - char* buffer, size_t SIZE) const -{ - Mutex::Autolock _l(mMutex); - snprintf(buffer, SIZE, - "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x}\n" - ,prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, - mNextCrop.bottom, mNextTransform - ); - result.append(buffer); - - String8 fifo; - int fifoSize = 0; - Fifo::const_iterator i(mQueue.begin()); - while (i != mQueue.end()) { - snprintf(buffer, SIZE, "%02d ", *i++); - fifoSize++; - fifo.append(buffer); - } - - snprintf(buffer, SIZE, - "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " - "mPixelFormat=%d, FIFO(%d)={%s}\n", - prefix, mBufferCount, mSynchronousMode, mDefaultWidth, - mDefaultHeight, mPixelFormat, fifoSize, fifo.string()); - result.append(buffer); - - - struct { - const char * operator()(int state) const { - switch (state) { - case BufferSlot::DEQUEUED: return "DEQUEUED"; - case BufferSlot::QUEUED: return "QUEUED"; - case BufferSlot::FREE: return "FREE"; - case BufferSlot::ACQUIRED: return "ACQUIRED"; - default: return "Unknown"; - } - } - } stateName; - - for (int i=0 ; i<mBufferCount ; i++) { - const BufferSlot& slot(mSlots[i]); - snprintf(buffer, SIZE, - "%s%s[%02d] " - "state=%-8s, crop=[%d,%d,%d,%d], " - "transform=0x%02x, timestamp=%lld", - prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, - stateName(slot.mBufferState), - slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, - slot.mCrop.bottom, slot.mTransform, slot.mTimestamp - ); - result.append(buffer); - - const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); - if (buf != NULL) { - snprintf(buffer, SIZE, - ", %p [%4ux%4u:%4u,%3X]", - buf->handle, buf->width, buf->height, buf->stride, - buf->format); - result.append(buffer); - } - result.append("\n"); - } -} - -void BufferQueue::freeBufferLocked(int i) { - mSlots[i].mGraphicBuffer = 0; - mSlots[i].mBufferState = BufferSlot::FREE; - mSlots[i].mFrameNumber = 0; - mSlots[i].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; - } -} - -void BufferQueue::freeAllBuffersLocked() { - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called but mQueue is not empty"); - mQueue.clear(); - mBufferHasBeenQueued = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - freeBufferLocked(i); - } -} - -status_t BufferQueue::acquire(BufferItem *buffer) { - ATRACE_CALL(); - Mutex::Autolock _l(mMutex); - // check if queue is empty - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - if (!mQueue.empty()) { - Fifo::iterator front(mQueue.begin()); - int buf = *front; - - ATRACE_BUFFER_INDEX(buf); - - if (mSlots[buf].mAcquireCalled) { - buffer->mGraphicBuffer = NULL; - } - else { - buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; - } - buffer->mCrop = mSlots[buf].mCrop; - buffer->mTransform = mSlots[buf].mTransform; - buffer->mScalingMode = mSlots[buf].mScalingMode; - buffer->mFrameNumber = mSlots[buf].mFrameNumber; - buffer->mTimestamp = mSlots[buf].mTimestamp; - buffer->mBuf = buf; - mSlots[buf].mAcquireCalled = true; - - mSlots[buf].mBufferState = BufferSlot::ACQUIRED; - mQueue.erase(front); - mDequeueCondition.broadcast(); - - ATRACE_INT(mConsumerName.string(), mQueue.size()); - } - else { - return -EINVAL; //should be a better return code - } - - return OK; -} - -status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, - EGLSyncKHR fence) { - ATRACE_CALL(); - ATRACE_BUFFER_INDEX(buf); - - Mutex::Autolock _l(mMutex); - - if (buf == INVALID_BUFFER_SLOT) { - return -EINVAL; - } - - mSlots[buf].mEglDisplay = display; - mSlots[buf].mFence = fence; - - // The current buffer becomes FREE if it was still in the queued - // state. If it has already been given to the client - // (synchronous mode), then it stays in DEQUEUED state. - if (mSlots[buf].mBufferState == BufferSlot::QUEUED - || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { - mSlots[buf].mBufferState = BufferSlot::FREE; - } - - mDequeueCondition.broadcast(); - - return OK; -} - -status_t BufferQueue::consumerDisconnect() { - Mutex::Autolock lock(mMutex); - // Once the SurfaceTexture disconnects, the BufferQueue - // is considered abandoned - mAbandoned = true; - freeAllBuffersLocked(); - mDequeueCondition.broadcast(); - return OK; -} - -status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) -{ - ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); - if (!w || !h) { - ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", - w, h); - return BAD_VALUE; - } - - Mutex::Autolock lock(mMutex); - mDefaultWidth = w; - mDefaultHeight = h; - return OK; -} - -status_t BufferQueue::setBufferCountServer(int bufferCount) { - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - return setBufferCountServerLocked(bufferCount); -} - -void BufferQueue::freeAllBuffersExceptHeadLocked() { - ALOGW_IF(!mQueue.isEmpty(), - "freeAllBuffersExceptCurrentLocked called but mQueue is not empty"); - int head = -1; - if (!mQueue.empty()) { - Fifo::iterator front(mQueue.begin()); - head = *front; - } - mBufferHasBeenQueued = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (i != head) { - freeBufferLocked(i); - } - } -} - -status_t BufferQueue::drainQueueLocked() { - while (mSynchronousMode && !mQueue.isEmpty()) { - mDequeueCondition.wait(mMutex); - if (mAbandoned) { - ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!"); - return NO_INIT; - } - if (mConnectedApi == NO_CONNECTED_API) { - ST_LOGE("drainQueueLocked: BufferQueue is not connected!"); - return NO_INIT; - } - } - return NO_ERROR; -} - -status_t BufferQueue::drainQueueAndFreeBuffersLocked() { - status_t err = drainQueueLocked(); - if (err == NO_ERROR) { - if (mSynchronousMode) { - freeAllBuffersLocked(); - } else { - freeAllBuffersExceptHeadLocked(); - } - } - return err; -} - -}; // namespace android diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp deleted file mode 100644 index a6790ad..0000000 --- a/libs/gui/DisplayEventReceiver.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#include <string.h> - -#include <utils/Errors.h> - -#include <gui/BitTube.h> -#include <gui/DisplayEventReceiver.h> -#include <gui/IDisplayEventConnection.h> -#include <gui/ISurfaceComposer.h> - -#include <private/gui/ComposerService.h> - -// --------------------------------------------------------------------------- - -namespace android { - -// --------------------------------------------------------------------------- - -DisplayEventReceiver::DisplayEventReceiver() { - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - if (sf != NULL) { - mEventConnection = sf->createDisplayEventConnection(); - if (mEventConnection != NULL) { - mDataChannel = mEventConnection->getDataChannel(); - } - } -} - -DisplayEventReceiver::~DisplayEventReceiver() { -} - -status_t DisplayEventReceiver::initCheck() const { - if (mDataChannel != NULL) - return NO_ERROR; - return NO_INIT; -} - -int DisplayEventReceiver::getFd() const { - if (mDataChannel == NULL) - return NO_INIT; - - return mDataChannel->getFd(); -} - -status_t DisplayEventReceiver::setVsyncRate(uint32_t count) { - if (int32_t(count) < 0) - return BAD_VALUE; - - if (mEventConnection != NULL) { - mEventConnection->setVsyncRate(count); - return NO_ERROR; - } - return NO_INIT; -} - -status_t DisplayEventReceiver::requestNextVsync() { - if (mEventConnection != NULL) { - mEventConnection->requestNextVsync(); - return NO_ERROR; - } - return NO_INIT; -} - - -ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, - size_t count) { - return DisplayEventReceiver::getEvents(mDataChannel, events, count); -} - -ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel, - Event* events, size_t count) -{ - ssize_t size = dataChannel->read(events, sizeof(events[0])*count); - ALOGE_IF(size<0, - "DisplayEventReceiver::getEvents error (%s)", - strerror(-size)); - if (size >= 0) { - // Note: if (size % sizeof(events[0])) != 0, we've got a - // partial read. This can happen if the queue filed up (ie: if we - // didn't pull from it fast enough). - // We discard the partial event and rely on the sender to - // re-send the event if appropriate (some events, like VSYNC - // can be lost forever). - - // returns number of events read - size /= sizeof(events[0]); - } - return size; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp deleted file mode 100644 index 887d176..0000000 --- a/libs/gui/IDisplayEventConnection.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Timers.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/IDisplayEventConnection.h> -#include <gui/BitTube.h> - -namespace android { -// ---------------------------------------------------------------------------- - -enum { - GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, - SET_VSYNC_RATE, - REQUEST_NEXT_VSYNC -}; - -class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection> -{ -public: - BpDisplayEventConnection(const sp<IBinder>& impl) - : BpInterface<IDisplayEventConnection>(impl) - { - } - - virtual sp<BitTube> getDataChannel() const - { - Parcel data, reply; - data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor()); - remote()->transact(GET_DATA_CHANNEL, data, &reply); - return new BitTube(reply); - } - - virtual void setVsyncRate(uint32_t count) { - Parcel data, reply; - data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor()); - data.writeInt32(count); - remote()->transact(SET_VSYNC_RATE, data, &reply); - } - - virtual void requestNextVsync() { - Parcel data, reply; - data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor()); - remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection"); - -// ---------------------------------------------------------------------------- - -status_t BnDisplayEventConnection::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_DATA_CHANNEL: { - CHECK_INTERFACE(IDisplayEventConnection, data, reply); - sp<BitTube> channel(getDataChannel()); - channel->writeToParcel(reply); - return NO_ERROR; - } break; - case SET_VSYNC_RATE: { - CHECK_INTERFACE(IDisplayEventConnection, data, reply); - setVsyncRate(data.readInt32()); - return NO_ERROR; - } break; - case REQUEST_NEXT_VSYNC: { - CHECK_INTERFACE(IDisplayEventConnection, data, reply); - requestNextVsync(); - return NO_ERROR; - } break; - } - return BBinder::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp deleted file mode 100644 index a70a5e8..0000000 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -// tag as surfaceflinger -#define LOG_TAG "SurfaceFlinger" - -#include <stdint.h> -#include <sys/types.h> - -#include <binder/Parcel.h> - -#include <ui/GraphicBuffer.h> - -#include <gui/IGraphicBufferAlloc.h> - -// --------------------------------------------------------------------------- - -namespace android { - -enum { - CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION, -}; - -class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc> -{ -public: - BpGraphicBufferAlloc(const sp<IBinder>& impl) - : BpInterface<IGraphicBufferAlloc>(impl) - { - } - - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { - Parcel data, reply; - data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(usage); - remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply); - sp<GraphicBuffer> graphicBuffer; - status_t result = reply.readInt32(); - if (result == NO_ERROR) { - graphicBuffer = new GraphicBuffer(); - reply.read(*graphicBuffer); - // reply.readStrongBinder(); - // here we don't even have to read the BufferReference from - // the parcel, it'll die with the parcel. - } - *error = result; - return graphicBuffer; - } -}; - -IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc"); - -// ---------------------------------------------------------------------- - -status_t BnGraphicBufferAlloc::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - // codes that don't require permission check - - /* BufferReference just keeps a strong reference to a - * GraphicBuffer until it is destroyed (that is, until - * no local or remote process have a reference to it). - */ - class BufferReference : public BBinder { - sp<GraphicBuffer> buffer; - public: - BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { } - }; - - - switch(code) { - case CREATE_GRAPHIC_BUFFER: { - CHECK_INTERFACE(IGraphicBufferAlloc, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t usage = data.readInt32(); - status_t error; - sp<GraphicBuffer> result = - createGraphicBuffer(w, h, format, usage, &error); - reply->writeInt32(error); - if (result != 0) { - reply->write(*result); - // We add a BufferReference to this parcel to make sure the - // buffer stays alive until the GraphicBuffer object on - // the other side has been created. - // This is needed so that the buffer handle can be - // registered before the buffer is destroyed on implementations - // that do not use file-descriptors to track their buffers. - reply->writeStrongBinder( new BufferReference(result) ); - } - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp deleted file mode 100644 index 0e51e8e..0000000 --- a/libs/gui/ISensorEventConnection.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Timers.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/ISensorEventConnection.h> -#include <gui/BitTube.h> - -namespace android { -// ---------------------------------------------------------------------------- - -enum { - GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, - ENABLE_DISABLE, - SET_EVENT_RATE -}; - -class BpSensorEventConnection : public BpInterface<ISensorEventConnection> -{ -public: - BpSensorEventConnection(const sp<IBinder>& impl) - : BpInterface<ISensorEventConnection>(impl) - { - } - - virtual sp<BitTube> getSensorChannel() const - { - Parcel data, reply; - data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); - remote()->transact(GET_SENSOR_CHANNEL, data, &reply); - return new BitTube(reply); - } - - virtual status_t enableDisable(int handle, bool enabled) - { - Parcel data, reply; - data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); - data.writeInt32(handle); - data.writeInt32(enabled); - remote()->transact(ENABLE_DISABLE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setEventRate(int handle, nsecs_t ns) - { - Parcel data, reply; - data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); - data.writeInt32(handle); - data.writeInt64(ns); - remote()->transact(SET_EVENT_RATE, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection"); - -// ---------------------------------------------------------------------------- - -status_t BnSensorEventConnection::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_SENSOR_CHANNEL: { - CHECK_INTERFACE(ISensorEventConnection, data, reply); - sp<BitTube> channel(getSensorChannel()); - channel->writeToParcel(reply); - return NO_ERROR; - } break; - case ENABLE_DISABLE: { - CHECK_INTERFACE(ISensorEventConnection, data, reply); - int handle = data.readInt32(); - int enabled = data.readInt32(); - status_t result = enableDisable(handle, enabled); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_EVENT_RATE: { - CHECK_INTERFACE(ISensorEventConnection, data, reply); - int handle = data.readInt32(); - int ns = data.readInt64(); - status_t result = setEventRate(handle, ns); - reply->writeInt32(result); - return NO_ERROR; - } break; - } - return BBinder::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp deleted file mode 100644 index 7111092..0000000 --- a/libs/gui/ISensorServer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Vector.h> -#include <utils/Timers.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/Sensor.h> -#include <gui/ISensorServer.h> -#include <gui/ISensorEventConnection.h> - -namespace android { -// ---------------------------------------------------------------------------- - -enum { - GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION, - CREATE_SENSOR_EVENT_CONNECTION, -}; - -class BpSensorServer : public BpInterface<ISensorServer> -{ -public: - BpSensorServer(const sp<IBinder>& impl) - : BpInterface<ISensorServer>(impl) - { - } - - virtual Vector<Sensor> getSensorList() - { - Parcel data, reply; - data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); - remote()->transact(GET_SENSOR_LIST, data, &reply); - Sensor s; - Vector<Sensor> v; - int32_t n = reply.readInt32(); - v.setCapacity(n); - while (n--) { - reply.read(static_cast<Flattenable&>(s)); - v.add(s); - } - return v; - } - - virtual sp<ISensorEventConnection> createSensorEventConnection() - { - Parcel data, reply; - data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); - remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply); - return interface_cast<ISensorEventConnection>(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(SensorServer, "android.gui.SensorServer"); - -// ---------------------------------------------------------------------- - -status_t BnSensorServer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_SENSOR_LIST: { - CHECK_INTERFACE(ISensorServer, data, reply); - Vector<Sensor> v(getSensorList()); - size_t n = v.size(); - reply->writeInt32(n); - for (size_t i=0 ; i<n ; i++) { - reply->write(static_cast<const Flattenable&>(v[i])); - } - return NO_ERROR; - } break; - case CREATE_SENSOR_EVENT_CONNECTION: { - CHECK_INTERFACE(ISensorServer, data, reply); - sp<ISensorEventConnection> connection(createSensorEventConnection()); - reply->writeStrongBinder(connection->asBinder()); - return NO_ERROR; - } break; - } - return BBinder::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/ISurface.cpp b/libs/gui/ISurface.cpp deleted file mode 100644 index c2ea183..0000000 --- a/libs/gui/ISurface.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007 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 "ISurface" - -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> - -#include <binder/Parcel.h> - -#include <gui/ISurface.h> -#include <gui/ISurfaceTexture.h> - -namespace android { - -// ---------------------------------------------------------------------- - -class BpSurface : public BpInterface<ISurface> -{ -public: - BpSurface(const sp<IBinder>& impl) - : BpInterface<ISurface>(impl) - { - } - - virtual sp<ISurfaceTexture> getSurfaceTexture() const { - Parcel data, reply; - data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - remote()->transact(GET_SURFACE_TEXTURE, data, &reply); - return interface_cast<ISurfaceTexture>(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(Surface, "android.ui.ISurface"); - -// ---------------------------------------------------------------------- - -status_t BnSurface::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_SURFACE_TEXTURE: { - CHECK_INTERFACE(ISurface, data, reply); - reply->writeStrongBinder( getSurfaceTexture()->asBinder() ); - return NO_ERROR; - } - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp deleted file mode 100644 index 1f1794c..0000000 --- a/libs/gui/ISurfaceComposer.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -// tag as surfaceflinger -#define LOG_TAG "SurfaceFlinger" - -#include <stdint.h> -#include <sys/types.h> - -#include <binder/Parcel.h> -#include <binder/IMemory.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> - -#include <gui/BitTube.h> -#include <gui/IDisplayEventConnection.h> -#include <gui/ISurfaceComposer.h> -#include <gui/ISurfaceTexture.h> - -#include <private/gui/LayerState.h> - -#include <ui/DisplayInfo.h> - -#include <utils/Log.h> - -// --------------------------------------------------------------------------- - -namespace android { - -class IDisplayEventConnection; - -class BpSurfaceComposer : public BpInterface<ISurfaceComposer> -{ -public: - BpSurfaceComposer(const sp<IBinder>& impl) - : BpInterface<ISurfaceComposer>(impl) - { - } - - virtual sp<ISurfaceComposerClient> createConnection() - { - uint32_t n; - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); - return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder()); - } - - virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() - { - uint32_t n; - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply); - return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder()); - } - - virtual sp<IMemoryHeap> getCblk() const - { - 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); - } - data.writeInt32(orientation); - data.writeInt32(flags); - remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); - } - - virtual void bootFinished() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); - } - - virtual status_t captureScreen(DisplayID dpy, - sp<IMemoryHeap>* heap, - uint32_t* width, uint32_t* height, PixelFormat* format, - uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(dpy); - data.writeInt32(reqWidth); - data.writeInt32(reqHeight); - data.writeInt32(minLayerZ); - data.writeInt32(maxLayerZ); - remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder()); - *width = reply.readInt32(); - *height = reply.readInt32(); - *format = reply.readInt32(); - 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 - { - Parcel data, reply; - int err = NO_ERROR; - err = data.writeInterfaceToken( - ISurfaceComposer::getInterfaceDescriptor()); - if (err != NO_ERROR) { - ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing " - "interface descriptor: %s (%d)", strerror(-err), -err); - return false; - } - err = data.writeStrongBinder(surfaceTexture->asBinder()); - if (err != NO_ERROR) { - ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing " - "strong binder to parcel: %s (%d)", strerror(-err), -err); - return false; - } - err = remote()->transact(BnSurfaceComposer::AUTHENTICATE_SURFACE, data, - &reply); - if (err != NO_ERROR) { - ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error " - "performing transaction: %s (%d)", strerror(-err), -err); - return false; - } - int32_t result = 0; - err = reply.readInt32(&result); - if (err != NO_ERROR) { - ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error " - "retrieving result: %s (%d)", strerror(-err), -err); - return false; - } - return result != 0; - } - - virtual sp<IDisplayEventConnection> createDisplayEventConnection() - { - Parcel data, reply; - sp<IDisplayEventConnection> result; - int err = data.writeInterfaceToken( - ISurfaceComposer::getInterfaceDescriptor()); - if (err != NO_ERROR) { - return result; - } - err = remote()->transact( - BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION, - data, &reply); - if (err != NO_ERROR) { - ALOGE("ISurfaceComposer::createDisplayEventConnection: error performing " - "transaction: %s (%d)", strerror(-err), -err); - return result; - } - result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder()); - return result; - } -}; - -IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); - -// ---------------------------------------------------------------------- - -status_t BnSurfaceComposer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case CREATE_CONNECTION: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> b = createConnection()->asBinder(); - reply->writeStrongBinder(b); - } break; - case CREATE_GRAPHIC_BUFFER_ALLOC: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> b = createGraphicBufferAlloc()->asBinder(); - reply->writeStrongBinder(b); - } break; - case SET_TRANSACTION_STATE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - size_t count = data.readInt32(); - ComposerState s; - Vector<ComposerState> state; - state.setCapacity(count); - for (size_t i=0 ; i<count ; i++) { - s.read(data); - state.add(s); - } - int orientation = data.readInt32(); - uint32_t flags = data.readInt32(); - setTransactionState(state, orientation, 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(); - uint32_t reqWidth = data.readInt32(); - uint32_t reqHeight = data.readInt32(); - uint32_t minLayerZ = data.readInt32(); - uint32_t maxLayerZ = data.readInt32(); - sp<IMemoryHeap> heap; - uint32_t w, h; - PixelFormat f; - status_t res = captureScreen(dpy, &heap, &w, &h, &f, - reqWidth, reqHeight, minLayerZ, maxLayerZ); - reply->writeStrongBinder(heap->asBinder()); - reply->writeInt32(w); - reply->writeInt32(h); - 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 = - interface_cast<ISurfaceTexture>(data.readStrongBinder()); - int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0; - reply->writeInt32(result); - } break; - case CREATE_DISPLAY_EVENT_CONNECTION: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IDisplayEventConnection> connection(createDisplayEventConnection()); - reply->writeStrongBinder(connection->asBinder()); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp deleted file mode 100644 index ca9ed5b..0000000 --- a/libs/gui/ISurfaceComposerClient.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -// tag as surfaceflinger -#define LOG_TAG "SurfaceFlinger" - -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> - -#include <binder/Parcel.h> -#include <binder/IMemory.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> - -#include <ui/Point.h> -#include <ui/Rect.h> - -#include <gui/ISurface.h> -#include <gui/ISurfaceComposerClient.h> -#include <private/gui/LayerState.h> - -// --------------------------------------------------------------------------- - -namespace android { - -enum { - CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, - DESTROY_SURFACE -}; - -class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient> -{ -public: - BpSurfaceComposerClient(const sp<IBinder>& impl) - : BpInterface<ISurfaceComposerClient>(impl) - { - } - - virtual sp<ISurface> createSurface( surface_data_t* params, - const String8& name, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); - data.writeString8(name); - data.writeInt32(display); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(flags); - remote()->transact(CREATE_SURFACE, data, &reply); - params->readFromParcel(reply); - return interface_cast<ISurface>(reply.readStrongBinder()); - } - - virtual status_t destroySurface(SurfaceID sid) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); - data.writeInt32(sid); - remote()->transact(DESTROY_SURFACE, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient"); - -// ---------------------------------------------------------------------- - -status_t BnSurfaceComposerClient::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case CREATE_SURFACE: { - CHECK_INTERFACE(ISurfaceComposerClient, data, reply); - surface_data_t params; - String8 name = data.readString8(); - DisplayID display = data.readInt32(); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t flags = data.readInt32(); - sp<ISurface> s = createSurface(¶ms, name, display, w, h, - format, flags); - params.writeToParcel(reply); - reply->writeStrongBinder(s->asBinder()); - return NO_ERROR; - } break; - case DESTROY_SURFACE: { - CHECK_INTERFACE(ISurfaceComposerClient, data, reply); - reply->writeInt32( destroySurface( data.readInt32() ) ); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------- - -status_t ISurfaceComposerClient::surface_data_t::readFromParcel(const Parcel& parcel) -{ - token = parcel.readInt32(); - identity = parcel.readInt32(); - return NO_ERROR; -} - -status_t ISurfaceComposerClient::surface_data_t::writeToParcel(Parcel* parcel) const -{ - parcel->writeInt32(token); - parcel->writeInt32(identity); - return NO_ERROR; -} - -}; // namespace android diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp deleted file mode 100644 index d2e5627..0000000 --- a/libs/gui/ISurfaceTexture.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Vector.h> -#include <utils/Timers.h> - -#include <binder/Parcel.h> -#include <binder/IInterface.h> - -#include <gui/ISurfaceTexture.h> - -namespace android { -// ---------------------------------------------------------------------------- - -enum { - REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION, - SET_BUFFER_COUNT, - DEQUEUE_BUFFER, - QUEUE_BUFFER, - CANCEL_BUFFER, - SET_CROP, - SET_TRANSFORM, - QUERY, - SET_SYNCHRONOUS_MODE, - CONNECT, - DISCONNECT, - SET_SCALING_MODE, -}; - - -class BpSurfaceTexture : public BpInterface<ISurfaceTexture> -{ -public: - BpSurfaceTexture(const sp<IBinder>& impl) - : BpInterface<ISurfaceTexture>(impl) - { - } - - virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(bufferIdx); - status_t result =remote()->transact(REQUEST_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - bool nonNull = reply.readInt32(); - if (nonNull) { - *buf = new GraphicBuffer(); - reply.read(**buf); - } - result = reply.readInt32(); - return result; - } - - virtual status_t setBufferCount(int bufferCount) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(bufferCount); - status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, - uint32_t format, uint32_t usage) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(usage); - status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - *buf = reply.readInt32(); - result = reply.readInt32(); - return result; - } - - virtual status_t queueBuffer(int buf, int64_t timestamp, - uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(buf); - data.writeInt64(timestamp); - status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); - if (result != NO_ERROR) { - return result; - } - *outWidth = reply.readInt32(); - *outHeight = reply.readInt32(); - *outTransform = reply.readInt32(); - result = reply.readInt32(); - return result; - } - - virtual void cancelBuffer(int buf) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(buf); - remote()->transact(CANCEL_BUFFER, data, &reply); - } - - virtual status_t setCrop(const Rect& reg) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeFloat(reg.left); - data.writeFloat(reg.top); - data.writeFloat(reg.right); - data.writeFloat(reg.bottom); - status_t result = remote()->transact(SET_CROP, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t setTransform(uint32_t transform) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(transform); - status_t result = remote()->transact(SET_TRANSFORM, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t setScalingMode(int mode) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(mode); - status_t result = remote()->transact(SET_SCALING_MODE, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual int query(int what, int* value) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(what); - status_t result = remote()->transact(QUERY, data, &reply); - if (result != NO_ERROR) { - return result; - } - value[0] = reply.readInt32(); - result = reply.readInt32(); - return result; - } - - virtual status_t setSynchronousMode(bool enabled) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(enabled); - status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t connect(int api, - uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(api); - status_t result = remote()->transact(CONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - *outWidth = reply.readInt32(); - *outHeight = reply.readInt32(); - *outTransform = reply.readInt32(); - result = reply.readInt32(); - return result; - } - - virtual status_t disconnect(int api) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - data.writeInt32(api); - status_t result =remote()->transact(DISCONNECT, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } -}; - -IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture"); - -// ---------------------------------------------------------------------- - -status_t BnSurfaceTexture::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case REQUEST_BUFFER: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int bufferIdx = data.readInt32(); - sp<GraphicBuffer> buffer; - int result = requestBuffer(bufferIdx, &buffer); - reply->writeInt32(buffer != 0); - if (buffer != 0) { - reply->write(*buffer); - } - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_BUFFER_COUNT: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int bufferCount = data.readInt32(); - int result = setBufferCount(bufferCount); - reply->writeInt32(result); - return NO_ERROR; - } break; - case DEQUEUE_BUFFER: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - uint32_t format = data.readInt32(); - uint32_t usage = data.readInt32(); - int buf; - int result = dequeueBuffer(&buf, w, h, format, usage); - reply->writeInt32(buf); - reply->writeInt32(result); - return NO_ERROR; - } break; - case QUEUE_BUFFER: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int buf = data.readInt32(); - int64_t timestamp = data.readInt64(); - uint32_t outWidth, outHeight, outTransform; - status_t result = queueBuffer(buf, timestamp, - &outWidth, &outHeight, &outTransform); - reply->writeInt32(outWidth); - reply->writeInt32(outHeight); - reply->writeInt32(outTransform); - reply->writeInt32(result); - return NO_ERROR; - } break; - case CANCEL_BUFFER: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int buf = data.readInt32(); - cancelBuffer(buf); - return NO_ERROR; - } break; - case SET_CROP: { - Rect reg; - CHECK_INTERFACE(ISurfaceTexture, data, reply); - reg.left = data.readFloat(); - reg.top = data.readFloat(); - reg.right = data.readFloat(); - reg.bottom = data.readFloat(); - status_t result = setCrop(reg); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_TRANSFORM: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - uint32_t transform = data.readInt32(); - status_t result = setTransform(transform); - reply->writeInt32(result); - return NO_ERROR; - } break; - case SET_SCALING_MODE: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int mode = data.readInt32(); - status_t result = setScalingMode(mode); - reply->writeInt32(result); - return NO_ERROR; - } break; - case QUERY: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int value; - int what = data.readInt32(); - int res = query(what, &value); - reply->writeInt32(value); - reply->writeInt32(res); - return NO_ERROR; - } break; - case SET_SYNCHRONOUS_MODE: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - bool enabled = data.readInt32(); - status_t res = setSynchronousMode(enabled); - reply->writeInt32(res); - return NO_ERROR; - } break; - case CONNECT: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int api = data.readInt32(); - uint32_t outWidth, outHeight, outTransform; - status_t res = connect(api, - &outWidth, &outHeight, &outTransform); - reply->writeInt32(outWidth); - reply->writeInt32(outHeight); - reply->writeInt32(outTransform); - reply->writeInt32(res); - return NO_ERROR; - } break; - case DISCONNECT: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - int api = data.readInt32(); - status_t res = disconnect(api); - reply->writeInt32(res); - return NO_ERROR; - } break; - } - return BBinder::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp deleted file mode 100644 index 224c305..0000000 --- a/libs/gui/LayerState.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include <utils/Errors.h> -#include <binder/Parcel.h> -#include <gui/ISurfaceComposerClient.h> -#include <private/gui/LayerState.h> - -namespace android { - -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); - if (err < NO_ERROR) return err; - - // NOTE: regions are at the end of the structure - size_t size = sizeof(layer_state_t); - size -= sizeof(transparentRegion); - err = output.write(this, size); - return err; -} - -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); - if (err < NO_ERROR) return err; - - // NOTE: regions are at the end of the structure - size_t size = sizeof(layer_state_t); - size -= sizeof(transparentRegion); - input.read(this, size); - return NO_ERROR; -} - -status_t ComposerState::write(Parcel& output) const { - output.writeStrongBinder(client->asBinder()); - return state.write(output); -} - -status_t ComposerState::read(const Parcel& input) { - client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder()); - return state.read(input); -} - -}; // namespace android diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp deleted file mode 100644 index f9a2c04..0000000 --- a/libs/gui/Sensor.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/String8.h> -#include <utils/Flattenable.h> - -#include <hardware/sensors.h> - -#include <gui/Sensor.h> - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -Sensor::Sensor() - : mHandle(0), mType(0), - mMinValue(0), mMaxValue(0), mResolution(0), - mPower(0), mMinDelay(0) -{ -} - -Sensor::Sensor(struct sensor_t const* hwSensor) -{ - mName = hwSensor->name; - mVendor = hwSensor->vendor; - mHandle = hwSensor->handle; - mType = hwSensor->type; - mMinValue = 0; // FIXME: minValue - mMaxValue = hwSensor->maxRange; // FIXME: maxValue - mResolution = hwSensor->resolution; - mPower = hwSensor->power; - mMinDelay = hwSensor->minDelay; -} - -Sensor::~Sensor() -{ -} - -const String8& Sensor::getName() const { - return mName; -} - -const String8& Sensor::getVendor() const { - return mVendor; -} - -int32_t Sensor::getHandle() const { - return mHandle; -} - -int32_t Sensor::getType() const { - return mType; -} - -float Sensor::getMinValue() const { - return mMinValue; -} - -float Sensor::getMaxValue() const { - return mMaxValue; -} - -float Sensor::getResolution() const { - return mResolution; -} - -float Sensor::getPowerUsage() const { - return mPower; -} - -int32_t Sensor::getMinDelay() const { - return mMinDelay; -} - -nsecs_t Sensor::getMinDelayNs() const { - return getMinDelay() * 1000; -} - -int32_t Sensor::getVersion() const { - return mVersion; -} - -size_t Sensor::getFlattenedSize() const -{ - return sizeof(int32_t) + ((mName.length() + 3) & ~3) + - sizeof(int32_t) + ((mVendor.length() + 3) & ~3) + - sizeof(int32_t) * 2 + - sizeof(float) * 4 + - 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()); - return (value.length() + 3) & ~3; -} - -static inline -size_t write(void* buffer, size_t offset, float value) { - *reinterpret_cast<float*>(static_cast<char*>(buffer) + offset) = value; - return sizeof(float); -} - -static inline -size_t write(void* buffer, size_t offset, int32_t value) { - *reinterpret_cast<int32_t*>(static_cast<char*>(buffer) + offset) = value; - return sizeof(int32_t); -} - -status_t Sensor::flatten(void* buffer, size_t size, - int fds[], size_t count) const -{ - if (size < Sensor::getFlattenedSize()) - return -ENOMEM; - - size_t offset = 0; - offset += write(buffer, offset, int32_t(mName.length())); - offset += write(buffer, offset, mName); - offset += write(buffer, offset, int32_t(mVendor.length())); - offset += write(buffer, offset, mVendor); - offset += write(buffer, offset, mHandle); - offset += write(buffer, offset, mType); - offset += write(buffer, offset, mMinValue); - offset += write(buffer, offset, mMaxValue); - offset += write(buffer, offset, mResolution); - offset += write(buffer, offset, mPower); - offset += write(buffer, offset, mMinDelay); - - return NO_ERROR; -} - -static inline -size_t read(void const* buffer, size_t offset, String8* value, int32_t len) { - value->setTo(static_cast<char const*>(buffer) + offset, len); - return (len + 3) & ~3; -} - -static inline -size_t read(void const* buffer, size_t offset, float* value) { - *value = *reinterpret_cast<float const*>(static_cast<char const*>(buffer) + offset); - return sizeof(float); -} - -static inline -size_t read(void const* buffer, size_t offset, int32_t* value) { - *value = *reinterpret_cast<int32_t const*>(static_cast<char const*>(buffer) + offset); - return sizeof(int32_t); -} - -status_t Sensor::unflatten(void const* buffer, size_t size, - int fds[], size_t count) -{ - int32_t len; - size_t offset = 0; - offset += read(buffer, offset, &len); - offset += read(buffer, offset, &mName, len); - offset += read(buffer, offset, &len); - offset += read(buffer, offset, &mVendor, len); - offset += read(buffer, offset, &mHandle); - offset += read(buffer, offset, &mType); - offset += read(buffer, offset, &mMinValue); - offset += read(buffer, offset, &mMaxValue); - offset += read(buffer, offset, &mResolution); - offset += read(buffer, offset, &mPower); - offset += read(buffer, offset, &mMinDelay); - - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp deleted file mode 100644 index b95dd90..0000000 --- a/libs/gui/SensorEventQueue.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 "Sensors" - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Looper.h> - -#include <gui/Sensor.h> -#include <gui/BitTube.h> -#include <gui/SensorEventQueue.h> -#include <gui/ISensorEventConnection.h> - -#include <android/sensor.h> - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection) - : mSensorEventConnection(connection) -{ -} - -SensorEventQueue::~SensorEventQueue() -{ -} - -void SensorEventQueue::onFirstRef() -{ - mSensorChannel = mSensorEventConnection->getSensorChannel(); -} - -int SensorEventQueue::getFd() const -{ - return mSensorChannel->getFd(); -} - -ssize_t SensorEventQueue::write(ASensorEvent const* events, size_t numEvents) -{ - ssize_t size = mSensorChannel->write(events, numEvents * sizeof(events[0])); - if (size >= 0) { - if (size % sizeof(events[0])) { - // partial write!!! should never happen. - return -EINVAL; - } - // returns number of events written - size /= sizeof(events[0]); - } - return size; -} - -ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) -{ - ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0])); - ALOGE_IF(size<0 && size!=-EAGAIN, - "SensorChannel::read error (%s)", strerror(-size)); - if (size >= 0) { - if (size % sizeof(events[0])) { - // partial read!!! should never happen. - ALOGE("SensorEventQueue partial read (event-size=%u, read=%d)", - sizeof(events[0]), int(size)); - return -EINVAL; - } - // returns number of events read - size /= sizeof(events[0]); - } - return size; -} - -sp<Looper> SensorEventQueue::getLooper() const -{ - Mutex::Autolock _l(mLock); - if (mLooper == 0) { - mLooper = new Looper(true); - mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); - } - return mLooper; -} - -status_t SensorEventQueue::waitForEvent() const -{ - const int fd = getFd(); - sp<Looper> looper(getLooper()); - - int32_t result; - do { - result = looper->pollOnce(-1); - if (result == ALOOPER_EVENT_ERROR) { - ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno); - result = -EPIPE; // unknown error, so we make up one - break; - } - } while (result != fd); - - return (result == fd) ? status_t(NO_ERROR) : result; -} - -status_t SensorEventQueue::wake() const -{ - sp<Looper> looper(getLooper()); - looper->wake(); - return NO_ERROR; -} - -status_t SensorEventQueue::enableSensor(Sensor const* sensor) const { - return mSensorEventConnection->enableDisable(sensor->getHandle(), true); -} - -status_t SensorEventQueue::disableSensor(Sensor const* sensor) const { - return mSensorEventConnection->enableDisable(sensor->getHandle(), false); -} - -status_t SensorEventQueue::enableSensor(int32_t handle, int32_t us) const { - status_t err = mSensorEventConnection->enableDisable(handle, true); - if (err == NO_ERROR) { - mSensorEventConnection->setEventRate(handle, us2ns(us)); - } - return err; -} - -status_t SensorEventQueue::disableSensor(int32_t handle) const { - return mSensorEventConnection->enableDisable(handle, false); -} - -status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const { - return mSensorEventConnection->setEventRate(sensor->getHandle(), ns); -} - -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp deleted file mode 100644 index b80da56..0000000 --- a/libs/gui/SensorManager.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 "Sensors" - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/RefBase.h> -#include <utils/Singleton.h> - -#include <binder/IBinder.h> -#include <binder/IServiceManager.h> - -#include <gui/ISensorServer.h> -#include <gui/ISensorEventConnection.h> -#include <gui/Sensor.h> -#include <gui/SensorManager.h> -#include <gui/SensorEventQueue.h> - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager) - -SensorManager::SensorManager() - : mSensorList(0) -{ - // okay we're not locked here, but it's not needed during construction - assertStateLocked(); -} - -SensorManager::~SensorManager() -{ - free(mSensorList); -} - -void SensorManager::sensorManagerDied() -{ - Mutex::Autolock _l(mLock); - mSensorServer.clear(); - free(mSensorList); - mSensorList = NULL; - mSensors.clear(); -} - -status_t SensorManager::assertStateLocked() const { - if (mSensorServer == NULL) { - // try for one second - const String16 name("sensorservice"); - for (int i=0 ; i<4 ; i++) { - status_t err = getService(name, &mSensorServer); - if (err == NAME_NOT_FOUND) { - usleep(250000); - continue; - } - if (err != NO_ERROR) { - return err; - } - break; - } - - class DeathObserver : public IBinder::DeathRecipient { - SensorManager& mSensorManger; - virtual void binderDied(const wp<IBinder>& who) { - ALOGW("sensorservice died [%p]", who.unsafe_get()); - mSensorManger.sensorManagerDied(); - } - public: - DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { } - }; - - mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this)); - mSensorServer->asBinder()->linkToDeath(mDeathObserver); - - mSensors = mSensorServer->getSensorList(); - size_t count = mSensors.size(); - mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*)); - for (size_t i=0 ; i<count ; i++) { - mSensorList[i] = mSensors.array() + i; - } - } - - return NO_ERROR; -} - - - -ssize_t SensorManager::getSensorList(Sensor const* const** list) const -{ - Mutex::Autolock _l(mLock); - status_t err = assertStateLocked(); - if (err < 0) { - return ssize_t(err); - } - *list = mSensorList; - return mSensors.size(); -} - -Sensor const* SensorManager::getDefaultSensor(int type) -{ - Mutex::Autolock _l(mLock); - if (assertStateLocked() == NO_ERROR) { - // For now we just return the first sensor of that type we find. - // in the future it will make sense to let the SensorService make - // that decision. - for (size_t i=0 ; i<mSensors.size() ; i++) { - if (mSensorList[i]->getType() == type) - return mSensorList[i]; - } - } - return NULL; -} - -sp<SensorEventQueue> SensorManager::createEventQueue() -{ - sp<SensorEventQueue> queue; - - Mutex::Autolock _l(mLock); - while (assertStateLocked() == NO_ERROR) { - sp<ISensorEventConnection> connection = - mSensorServer->createSensorEventConnection(); - if (connection == NULL) { - // SensorService just died. - ALOGE("createEventQueue: connection is NULL. SensorService died."); - continue; - } - queue = new SensorEventQueue(connection); - break; - } - return queue; -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp deleted file mode 100644 index 72b27ed..0000000 --- a/libs/gui/Surface.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2007 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 "Surface" - -#include <stdint.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <utils/CallStack.h> -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/threads.h> - -#include <binder/IPCThreadState.h> - -#include <ui/DisplayInfo.h> -#include <ui/GraphicBuffer.h> -#include <ui/Rect.h> - -#include <gui/ISurface.h> -#include <gui/ISurfaceComposer.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> -#include <gui/SurfaceTextureClient.h> - -namespace android { - -// ============================================================================ -// SurfaceControl -// ============================================================================ - -SurfaceControl::SurfaceControl( - const sp<SurfaceComposerClient>& client, - const sp<ISurface>& surface, - const ISurfaceComposerClient::surface_data_t& data) - : mClient(client), mSurface(surface), - mToken(data.token), mIdentity(data.identity) -{ -} - -SurfaceControl::~SurfaceControl() -{ - destroy(); -} - -void SurfaceControl::destroy() -{ - if (isValid()) { - mClient->destroySurface(mToken); - } - - // clear all references and trigger an IPC now, to make sure things - // happen without delay, since these resources are quite heavy. - mClient.clear(); - mSurface.clear(); - IPCThreadState::self()->flushCommands(); -} - -void SurfaceControl::clear() -{ - // here, the window manager tells us explicitly that we should destroy - // the surface's resource. Soon after this call, it will also release - // its last reference (which will call the dtor); however, it is possible - // that a client living in the same process still holds references which - // would delay the call to the dtor -- that is why we need this explicit - // "clear()" call. - destroy(); -} - -bool SurfaceControl::isSameSurface( - const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) -{ - if (lhs == 0 || rhs == 0) - return false; - return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); -} - -status_t SurfaceControl::setLayer(int32_t layer) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setLayer(mToken, layer); -} -status_t SurfaceControl::setPosition(int32_t x, int32_t y) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setPosition(mToken, x, y); -} -status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setSize(mToken, w, h); -} -status_t SurfaceControl::hide() { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->hide(mToken); -} -status_t SurfaceControl::show(int32_t layer) { - status_t err = validate(); - if (err < 0) return err; - 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; - const sp<SurfaceComposerClient>& client(mClient); - return client->setFlags(mToken, flags, mask); -} -status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setTransparentRegionHint(mToken, transparent); -} -status_t SurfaceControl::setAlpha(float alpha) { - status_t err = validate(); - if (err < 0) return err; - const sp<SurfaceComposerClient>& client(mClient); - return client->setAlpha(mToken, alpha); -} -status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - status_t err = validate(); - if (err < 0) return err; - 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::validate() const -{ - if (mToken<0 || mClient==0) { - ALOGE("invalid token (%d, identity=%u) or client (%p)", - mToken, mIdentity, mClient.get()); - return NO_INIT; - } - return NO_ERROR; -} - -status_t SurfaceControl::writeSurfaceToParcel( - const sp<SurfaceControl>& control, Parcel* parcel) -{ - sp<ISurface> sur; - uint32_t identity = 0; - if (SurfaceControl::isValid(control)) { - sur = control->mSurface; - identity = control->mIdentity; - } - parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); - parcel->writeStrongBinder(NULL); // NULL ISurfaceTexture in this case. - parcel->writeInt32(identity); - return NO_ERROR; -} - -sp<Surface> SurfaceControl::getSurface() const -{ - Mutex::Autolock _l(mLock); - if (mSurfaceData == 0) { - sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this)); - mSurfaceData = new Surface(surface_control); - } - return mSurfaceData; -} - -// ============================================================================ -// Surface -// ============================================================================ - -// --------------------------------------------------------------------------- - -Surface::Surface(const sp<SurfaceControl>& surface) - : SurfaceTextureClient(), - mSurface(surface->mSurface), - mIdentity(surface->mIdentity) -{ - sp<ISurfaceTexture> st; - if (mSurface != NULL) { - st = mSurface->getSurfaceTexture(); - } - init(st); -} - -Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) - : SurfaceTextureClient() -{ - mSurface = interface_cast<ISurface>(ref); - sp<IBinder> st_binder(parcel.readStrongBinder()); - sp<ISurfaceTexture> st; - if (st_binder != NULL) { - st = interface_cast<ISurfaceTexture>(st_binder); - } else if (mSurface != NULL) { - st = mSurface->getSurfaceTexture(); - } - - mIdentity = parcel.readInt32(); - init(st); -} - -Surface::Surface(const sp<ISurfaceTexture>& st) - : SurfaceTextureClient(), - mSurface(NULL), - mIdentity(0) -{ - init(st); -} - -status_t Surface::writeToParcel( - const sp<Surface>& surface, Parcel* parcel) -{ - sp<ISurface> sur; - sp<ISurfaceTexture> st; - uint32_t identity = 0; - if (Surface::isValid(surface)) { - sur = surface->mSurface; - st = surface->getISurfaceTexture(); - identity = surface->mIdentity; - } else if (surface != 0 && - (surface->mSurface != NULL || - surface->getISurfaceTexture() != NULL)) { - ALOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: " - "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ", - surface->mSurface.get(), surface->getISurfaceTexture().get(), - surface->mIdentity); - } - - parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL); - parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL); - parcel->writeInt32(identity); - return NO_ERROR; - -} - -Mutex Surface::sCachedSurfacesLock; -DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces; - -sp<Surface> Surface::readFromParcel(const Parcel& data) { - Mutex::Autolock _l(sCachedSurfacesLock); - sp<IBinder> binder(data.readStrongBinder()); - sp<Surface> surface = sCachedSurfaces.valueFor(binder).promote(); - if (surface == 0) { - surface = new Surface(data, binder); - sCachedSurfaces.add(binder, surface); - } else { - // The Surface was found in the cache, but we still should clear any - // remaining data from the parcel. - data.readStrongBinder(); // ISurfaceTexture - data.readInt32(); // identity - } - if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) { - surface = 0; - } - cleanCachedSurfacesLocked(); - return surface; -} - -// Remove the stale entries from the surface cache. This should only be called -// with sCachedSurfacesLock held. -void Surface::cleanCachedSurfacesLocked() { - for (int i = sCachedSurfaces.size()-1; i >= 0; --i) { - wp<Surface> s(sCachedSurfaces.valueAt(i)); - if (s == 0 || s.promote() == 0) { - sCachedSurfaces.removeItemsAt(i); - } - } -} - -void Surface::init(const sp<ISurfaceTexture>& surfaceTexture) -{ - if (mSurface != NULL || surfaceTexture != NULL) { - ALOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); - if (surfaceTexture != NULL) { - setISurfaceTexture(surfaceTexture); - setUsage(GraphicBuffer::USAGE_HW_RENDER); - } - - DisplayInfo dinfo; - SurfaceComposerClient::getDisplayInfo(0, &dinfo); - const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; - const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; - const_cast<uint32_t&>(ANativeWindow::flags) = 0; - } -} - -Surface::~Surface() -{ - // clear all references and trigger an IPC now, to make sure things - // happen without delay, since these resources are quite heavy. - mSurface.clear(); - IPCThreadState::self()->flushCommands(); -} - -bool Surface::isValid() { - return getISurfaceTexture() != NULL; -} - -sp<ISurfaceTexture> Surface::getSurfaceTexture() { - return getISurfaceTexture(); -} - -sp<IBinder> Surface::asBinder() const { - return mSurface!=0 ? mSurface->asBinder() : 0; -} - -// ---------------------------------------------------------------------------- - -int Surface::query(int what, int* value) const { - switch (what) { - case NATIVE_WINDOW_CONCRETE_TYPE: - *value = NATIVE_WINDOW_SURFACE; - return NO_ERROR; - } - return SurfaceTextureClient::query(what, value); -} - -// ---------------------------------------------------------------------------- - -status_t Surface::lock(SurfaceInfo* other, Region* inOutDirtyRegion) { - ANativeWindow_Buffer outBuffer; - - ARect temp; - ARect* inOutDirtyBounds = NULL; - if (inOutDirtyRegion) { - temp = inOutDirtyRegion->getBounds(); - inOutDirtyBounds = &temp; - } - - status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds); - - if (err == NO_ERROR) { - other->w = uint32_t(outBuffer.width); - other->h = uint32_t(outBuffer.height); - other->s = uint32_t(outBuffer.stride); - other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; - other->format = uint32_t(outBuffer.format); - other->bits = outBuffer.bits; - } - - if (inOutDirtyRegion) { - inOutDirtyRegion->set( static_cast<Rect const&>(temp) ); - } - - return err; -} - -status_t Surface::unlockAndPost() { - return SurfaceTextureClient::unlockAndPost(); -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp deleted file mode 100644 index ceb1ba6..0000000 --- a/libs/gui/SurfaceComposerClient.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (C) 2007 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 "SurfaceComposerClient" - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> -#include <utils/Singleton.h> -#include <utils/SortedVector.h> -#include <utils/String8.h> -#include <utils/threads.h> - -#include <binder/IMemory.h> -#include <binder/IServiceManager.h> - -#include <ui/DisplayInfo.h> - -#include <gui/ISurface.h> -#include <gui/ISurfaceComposer.h> -#include <gui/ISurfaceComposerClient.h> -#include <gui/SurfaceComposerClient.h> - -#include <private/gui/ComposerService.h> -#include <private/gui/LayerState.h> -#include <private/gui/SharedBufferStack.h> - -namespace android { -// --------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); - -ComposerService::ComposerService() -: Singleton<ComposerService>() { - const String16 name("SurfaceFlinger"); - 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) { - if (lhs.client < rhs.client) return -1; - if (lhs.client > rhs.client) return 1; - if (lhs.state.surface < rhs.state.surface) return -1; - if (lhs.state.surface > rhs.state.surface) return 1; - return 0; -} - -class Composer : public Singleton<Composer> -{ - friend class Singleton<Composer>; - - mutable Mutex mLock; - SortedVector<ComposerState> mStates; - int mOrientation; - uint32_t mForceSynchronous; - - Composer() : Singleton<Composer>(), - mOrientation(ISurfaceComposer::eOrientationUnchanged), - mForceSynchronous(0) - { } - - void closeGlobalTransactionImpl(bool synchronous); - - layer_state_t* getLayerStateLocked( - const sp<SurfaceComposerClient>& client, SurfaceID id); - -public: - - status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id, - float x, float y); - status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id, - uint32_t w, uint32_t h); - status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id, - int32_t z); - status_t setFlags(const sp<SurfaceComposerClient>& client, SurfaceID id, - uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint( - const sp<SurfaceComposerClient>& client, SurfaceID id, - const Region& transparentRegion); - status_t setAlpha(const sp<SurfaceComposerClient>& client, SurfaceID id, - 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); - - static void closeGlobalTransaction(bool synchronous) { - Composer::getInstance().closeGlobalTransactionImpl(synchronous); - } -}; - -ANDROID_SINGLETON_STATIC_INSTANCE(Composer); - -// --------------------------------------------------------------------------- - -void Composer::closeGlobalTransactionImpl(bool synchronous) { - sp<ISurfaceComposer> sm(getComposerService()); - - Vector<ComposerState> transaction; - int orientation; - uint32_t flags = 0; - - { // scope for the lock - Mutex::Autolock _l(mLock); - transaction = mStates; - mStates.clear(); - - orientation = mOrientation; - mOrientation = ISurfaceComposer::eOrientationUnchanged; - - if (synchronous || mForceSynchronous) { - flags |= ISurfaceComposer::eSynchronous; - } - mForceSynchronous = false; - } - - sm->setTransactionState(transaction, orientation, flags); -} - -layer_state_t* Composer::getLayerStateLocked( - const sp<SurfaceComposerClient>& client, SurfaceID id) { - - ComposerState s; - s.client = client->mClient; - s.state.surface = id; - - ssize_t index = mStates.indexOf(s); - if (index < 0) { - // we don't have it, add an initialized layer_state to our list - index = mStates.add(s); - } - - ComposerState* const out = mStates.editArray(); - return &(out[index].state); -} - -status_t Composer::setPosition(const sp<SurfaceComposerClient>& client, - SurfaceID id, float x, float y) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::ePositionChanged; - s->x = x; - s->y = y; - return NO_ERROR; -} - -status_t Composer::setSize(const sp<SurfaceComposerClient>& client, - SurfaceID id, uint32_t w, uint32_t h) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eSizeChanged; - s->w = w; - s->h = h; - - // Resizing a surface makes the transaction synchronous. - mForceSynchronous = true; - - return NO_ERROR; -} - -status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, - SurfaceID id, int32_t z) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eLayerChanged; - s->z = z; - return NO_ERROR; -} - -status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, - SurfaceID id, uint32_t flags, - uint32_t mask) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eVisibilityChanged; - s->flags &= ~mask; - s->flags |= (flags & mask); - s->mask |= mask; - return NO_ERROR; -} - -status_t Composer::setTransparentRegionHint( - const sp<SurfaceComposerClient>& client, SurfaceID id, - const Region& transparentRegion) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eTransparentRegionChanged; - s->transparentRegion = transparentRegion; - return NO_ERROR; -} - -status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client, - SurfaceID id, float alpha) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eAlphaChanged; - s->alpha = alpha; - return NO_ERROR; -} - -status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client, - SurfaceID id, float dsdx, float dtdx, - float dsdy, float dtdy) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eMatrixChanged; - layer_state_t::matrix22_t matrix; - matrix.dsdx = dsdx; - matrix.dtdx = dtdx; - matrix.dsdy = dsdy; - matrix.dtdy = dtdy; - s->matrix = matrix; - return NO_ERROR; -} - -status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client, - SurfaceID id, uint32_t tint) { - Mutex::Autolock _l(mLock); - layer_state_t* s = getLayerStateLocked(client, id); - if (!s) - return BAD_INDEX; - s->what |= ISurfaceComposer::eFreezeTintChanged; - s->tint = tint; - return NO_ERROR; -} - -status_t Composer::setOrientation(int orientation) { - Mutex::Autolock _l(mLock); - mOrientation = orientation; - - // Changing the orientation makes the transaction synchronous. - mForceSynchronous = true; - - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -SurfaceComposerClient::SurfaceComposerClient() - : mStatus(NO_INIT), mComposer(Composer::getInstance()) -{ -} - -void SurfaceComposerClient::onFirstRef() { - sp<ISurfaceComposer> sm(getComposerService()); - if (sm != 0) { - sp<ISurfaceComposerClient> conn = sm->createConnection(); - if (conn != 0) { - mClient = conn; - mStatus = NO_ERROR; - } - } -} - -SurfaceComposerClient::~SurfaceComposerClient() { - dispose(); -} - -status_t SurfaceComposerClient::initCheck() const { - return mStatus; -} - -sp<IBinder> SurfaceComposerClient::connection() const { - return (mClient != 0) ? mClient->asBinder() : 0; -} - -status_t SurfaceComposerClient::linkToComposerDeath( - const sp<IBinder::DeathRecipient>& recipient, - void* cookie, uint32_t flags) { - sp<ISurfaceComposer> sm(getComposerService()); - return sm->asBinder()->linkToDeath(recipient, cookie, flags); -} - -void SurfaceComposerClient::dispose() { - // this can be called more than once. - sp<ISurfaceComposerClient> client; - Mutex::Autolock _lm(mLock); - if (mClient != 0) { - client = mClient; // hold ref while lock is held - mClient.clear(); - } - mStatus = NO_INIT; -} - -sp<SurfaceControl> SurfaceComposerClient::createSurface( - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - String8 name; - const size_t SIZE = 128; - char buffer[SIZE]; - snprintf(buffer, SIZE, "<pid_%d>", getpid()); - name.append(buffer); - - return SurfaceComposerClient::createSurface(name, display, - w, h, format, flags); -} - -sp<SurfaceControl> SurfaceComposerClient::createSurface( - const String8& name, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - sp<SurfaceControl> result; - if (mStatus == NO_ERROR) { - ISurfaceComposerClient::surface_data_t data; - sp<ISurface> surface = mClient->createSurface(&data, name, - display, w, h, format, flags); - if (surface != 0) { - result = new SurfaceControl(this, surface, data); - } - } - return result; -} - -status_t SurfaceComposerClient::destroySurface(SurfaceID sid) { - if (mStatus != NO_ERROR) - return mStatus; - status_t err = mClient->destroySurface(sid); - return err; -} - -inline Composer& SurfaceComposerClient::getComposer() { - return mComposer; -} - -// ---------------------------------------------------------------------------- - -void SurfaceComposerClient::openGlobalTransaction() { - // Currently a no-op -} - -void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { - Composer::closeGlobalTransaction(synchronous); -} - -// ---------------------------------------------------------------------------- - -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); -} - -status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) { - return getComposer().setSize(this, id, w, h); -} - -status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { - return getComposer().setLayer(this, id, z); -} - -status_t SurfaceComposerClient::hide(SurfaceID id) { - return getComposer().setFlags(this, id, - ISurfaceComposer::eLayerHidden, - ISurfaceComposer::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); -} - -status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, - uint32_t mask) { - return getComposer().setFlags(this, id, flags, mask); -} - -status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id, - const Region& transparentRegion) { - return getComposer().setTransparentRegionHint(this, id, transparentRegion); -} - -status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { - return getComposer().setAlpha(this, id, alpha); -} - -status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx, - float dsdy, float dtdy) { - return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy); -} - -status_t SurfaceComposerClient::setOrientation(DisplayID dpy, - int orientation, uint32_t flags) -{ - return Composer::getInstance().setOrientation(orientation); -} - -// ---------------------------------------------------------------------------- - -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)); -} - -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; -} - -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; -} - -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; -} - -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; -} - -// ---------------------------------------------------------------------------- - -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) -{ - // This has been made a no-op because it can cause Gralloc buffer deadlocks. - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -ScreenshotClient::ScreenshotClient() - : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) { -} - -status_t ScreenshotClient::update() { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - mHeap = 0; - return s->captureScreen(0, &mHeap, - &mWidth, &mHeight, &mFormat, 0, 0, - 0, -1UL); -} - -status_t ScreenshotClient::update(uint32_t reqWidth, uint32_t reqHeight) { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - mHeap = 0; - return s->captureScreen(0, &mHeap, - &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, - 0, -1UL); -} - -status_t ScreenshotClient::update(uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ) { - sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - mHeap = 0; - return s->captureScreen(0, &mHeap, - &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, - minLayerZ, maxLayerZ); -} - -void ScreenshotClient::release() { - mHeap = 0; -} - -void const* ScreenshotClient::getPixels() const { - return mHeap->getBase(); -} - -uint32_t ScreenshotClient::getWidth() const { - return mWidth; -} - -uint32_t ScreenshotClient::getHeight() const { - return mHeight; -} - -PixelFormat ScreenshotClient::getFormat() const { - return mFormat; -} - -uint32_t ScreenshotClient::getStride() const { - return mWidth; -} - -size_t ScreenshotClient::getSize() const { - return mHeap->getSize(); -} - -// ---------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp deleted file mode 100644 index b42aa34..0000000 --- a/libs/gui/SurfaceTexture.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - * 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 "SurfaceTexture" -#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 <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <hardware/hardware.h> - -#include <gui/IGraphicBufferAlloc.h> -#include <gui/ISurfaceComposer.h> -#include <gui/SurfaceComposerClient.h> -#include <gui/SurfaceTexture.h> - -#include <private/gui/ComposerService.h> - -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/Trace.h> - -// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension -// to synchronize access to the buffers. It will cause dequeueBuffer to stall, -// waiting for the GL reads for the buffer being dequeued to complete before -// allowing the buffer to be dequeued. -#ifdef USE_FENCE_SYNC -#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER -#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible" -#endif -#endif - -// Macros for including the SurfaceTexture name in log messages -#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) - -namespace android { - -// Transform matrices -static float mtxIdentity[16] = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, -}; -static float mtxFlipH[16] = { - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 1, 0, 0, 1, -}; -static float mtxFlipV[16] = { - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0, - 0, 1, 0, 1, -}; -static float mtxRot90[16] = { - 0, 1, 0, 0, - -1, 0, 0, 0, - 0, 0, 1, 0, - 1, 0, 0, 1, -}; -static float mtxRot180[16] = { - -1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0, - 1, 1, 0, 1, -}; -static float mtxRot270[16] = { - 0, -1, 0, 0, - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 1, 0, 1, -}; - -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) : - BufferQueue(allowSynchronousMode), - mCurrentTransform(0), - mCurrentTimestamp(0), - mTexName(tex), -#ifdef USE_FENCE_SYNC - mUseFenceSync(useFenceSync), -#else - mUseFenceSync(false), -#endif - mTexTarget(texTarget), - mAbandoned(false), - mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) -{ - // Choose a name using the PID and a process-unique ID. - mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); - BufferQueue::setConsumerName(mName); - - ST_LOGV("SurfaceTexture"); - memcpy(mCurrentTransformMatrix, mtxIdentity, - sizeof(mCurrentTransformMatrix)); -} - -SurfaceTexture::~SurfaceTexture() { - ST_LOGV("~SurfaceTexture"); - abandon(); -} - -status_t SurfaceTexture::setBufferCountServer(int bufferCount) { - Mutex::Autolock lock(mMutex); - return BufferQueue::setBufferCountServer(bufferCount); -} - - -status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) -{ - return BufferQueue::setDefaultBufferSize(w, h); -} - -status_t SurfaceTexture::updateTexImage() { - ATRACE_CALL(); - ST_LOGV("updateTexImage"); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); - return NO_INIT; - } - - BufferItem item; - - // In asynchronous mode the list is guaranteed to be one buffer - // deep, while in synchronous mode we use the oldest buffer. - if (acquire(&item) == 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(mEGLSlots[buf].mEglDisplay, - mEGLSlots[buf].mEglImage); - mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; - mEGLSlots[buf].mEglDisplay = EGL_NO_DISPLAY; - } - mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer; - } - - // Update the GL texture object. - EGLImageKHR image = mEGLSlots[buf].mEglImage; - EGLDisplay dpy = eglGetCurrentDisplay(); - if (image == EGL_NO_IMAGE_KHR) { - if (item.mGraphicBuffer == 0) { - ST_LOGE("buffer at slot %d is null", buf); - return BAD_VALUE; - } - image = createImage(dpy, item.mGraphicBuffer); - mEGLSlots[buf].mEglImage = image; - mEGLSlots[buf].mEglDisplay = dpy; - if (image == EGL_NO_IMAGE_KHR) { - // NOTE: if dpy was invalid, createImage() is guaranteed to - // fail. so we'd end up here. - return -EINVAL; - } - } - - GLint error; - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGW("updateTexImage: clearing GL error: %#04x", error); - } - - glBindTexture(mTexTarget, mTexName); - glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); - - bool failed = false; - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGE("error binding external texture image %p (slot %d): %#04x", - image, buf, error); - failed = true; - } - if (failed) { - releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, - mEGLSlots[buf].mFence); - return -EINVAL; - } - - if (mCurrentTexture != INVALID_BUFFER_SLOT) { - if (mUseFenceSync) { - EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, - NULL); - if (fence == EGL_NO_SYNC_KHR) { - ALOGE("updateTexImage: error creating fence: %#x", - eglGetError()); - releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, - mEGLSlots[buf].mFence); - return -EINVAL; - } - glFlush(); - mEGLSlots[mCurrentTexture].mFence = fence; - } - } - - 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); - - // release old buffer - releaseBuffer(mCurrentTexture, - mEGLSlots[mCurrentTexture].mEglDisplay, - mEGLSlots[mCurrentTexture].mFence); - - // Update the SurfaceTexture state. - mCurrentTexture = buf; - mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer; - mCurrentCrop = item.mCrop; - mCurrentTransform = item.mTransform; - mCurrentScalingMode = item.mScalingMode; - mCurrentTimestamp = item.mTimestamp; - computeCurrentTransformMatrix(); - - // Now that we've passed the point at which failures can happen, - // it's safe to remove the buffer from the front of the queue. - - } else { - // We always bind the texture even if we don't update its contents. - glBindTexture(mTexTarget, mTexName); - } - - return OK; -} - -bool SurfaceTexture::isExternalFormat(uint32_t format) -{ - switch (format) { - // supported YUV formats - case HAL_PIXEL_FORMAT_YV12: - // Legacy/deprecated YUV formats - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - case HAL_PIXEL_FORMAT_YCbCr_422_I: - return true; - } - - // Any OEM format needs to be considered - if (format>=0x100 && format<=0x1FF) - return true; - - return false; -} - -GLenum SurfaceTexture::getCurrentTextureTarget() const { - return mTexTarget; -} - -void SurfaceTexture::getTransformMatrix(float mtx[16]) { - Mutex::Autolock lock(mMutex); - memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); -} - -void SurfaceTexture::computeCurrentTransformMatrix() { - ST_LOGV("computeCurrentTransformMatrix"); - - float xform[16]; - for (int i = 0; i < 16; i++) { - xform[i] = mtxIdentity[i]; - } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { - float result[16]; - mtxMul(result, xform, mtxFlipH); - for (int i = 0; i < 16; i++) { - xform[i] = result[i]; - } - } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { - float result[16]; - mtxMul(result, xform, mtxFlipV); - for (int i = 0; i < 16; i++) { - xform[i] = result[i]; - } - } - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { - float result[16]; - mtxMul(result, xform, mtxRot90); - for (int i = 0; i < 16; i++) { - xform[i] = result[i]; - } - } - - sp<GraphicBuffer>& buf(mCurrentTextureBuf); - float tx, ty, sx, sy; - if (!mCurrentCrop.isEmpty()) { - // In order to prevent bilinear sampling at the of the crop rectangle we - // may need to shrink it by 2 texels in each direction. Normally this - // would just need to take 1/2 a texel off each end, but because the - // chroma channels will likely be subsampled we need to chop off a whole - // texel. This will cause artifacts if someone does nearest sampling - // with 1:1 pixel:texel ratio, but it's impossible to simultaneously - // accomodate the bilinear and nearest sampling uses. - // - // If nearest sampling turns out to be a desirable usage of these - // textures then we could add the ability to switch a SurfaceTexture to - // nearest-mode. Preferably, however, the image producers (video - // decoder, camera, etc.) would simply not use a crop rectangle (or at - // least not tell the framework about it) so that the GPU can do the - // correct edge behavior. - int xshrink = 0, yshrink = 0; - if (mCurrentCrop.left > 0) { - tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); - xshrink++; - } else { - tx = 0.0f; - } - if (mCurrentCrop.right < int32_t(buf->getWidth())) { - xshrink++; - } - if (mCurrentCrop.bottom < int32_t(buf->getHeight())) { - ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / - float(buf->getHeight()); - yshrink++; - } else { - ty = 0.0f; - } - if (mCurrentCrop.top > 0) { - yshrink++; - } - sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); - sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); - } else { - tx = 0.0f; - ty = 0.0f; - sx = 1.0f; - sy = 1.0f; - } - float crop[16] = { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, 1, 0, - tx, ty, 0, 1, - }; - - float mtxBeforeFlipV[16]; - mtxMul(mtxBeforeFlipV, crop, xform); - - // SurfaceFlinger expects the top of its window textures to be at a Y - // coordinate of 0, so SurfaceTexture must behave the same way. We don't - // want to expose this to applications, however, so we must add an - // additional vertical flip to the transform after all the other transforms. - mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV); -} - -nsecs_t SurfaceTexture::getTimestamp() { - ST_LOGV("getTimestamp"); - Mutex::Autolock lock(mMutex); - return mCurrentTimestamp; -} - -void SurfaceTexture::setFrameAvailableListener( - const sp<FrameAvailableListener>& listener) { - ST_LOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - BufferQueue::setFrameAvailableListener(listener); -} - -EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, - const sp<GraphicBuffer>& graphicBuffer) { - EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); - EGLint attrs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE, - }; - EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, - EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); - if (image == EGL_NO_IMAGE_KHR) { - EGLint error = eglGetError(); - ST_LOGE("error creating EGLImage: %#x", error); - } - return image; -} - -sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { - Mutex::Autolock lock(mMutex); - return mCurrentTextureBuf; -} - -Rect SurfaceTexture::getCurrentCrop() const { - Mutex::Autolock lock(mMutex); - return mCurrentCrop; -} - -uint32_t SurfaceTexture::getCurrentTransform() const { - Mutex::Autolock lock(mMutex); - return mCurrentTransform; -} - -uint32_t SurfaceTexture::getCurrentScalingMode() const { - Mutex::Autolock lock(mMutex); - return mCurrentScalingMode; -} - -bool SurfaceTexture::isSynchronousMode() const { - Mutex::Autolock lock(mMutex); - return BufferQueue::isSynchronousMode(); -} - -void SurfaceTexture::abandon() { - Mutex::Autolock lock(mMutex); - mAbandoned = true; - mCurrentTextureBuf.clear(); - - // destroy all egl buffers - for (int i =0; i < NUM_BUFFER_SLOTS; i++) { - mEGLSlots[i].mGraphicBuffer = 0; - if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(mEGLSlots[i].mEglDisplay, - mEGLSlots[i].mEglImage); - mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR; - mEGLSlots[i].mEglDisplay = EGL_NO_DISPLAY; - } - } - - // disconnect from the BufferQueue - BufferQueue::consumerDisconnect(); -} - -void SurfaceTexture::setName(const String8& name) { - Mutex::Autolock _l(mMutex); - mName = name; - BufferQueue::setConsumerName(name); -} - -void SurfaceTexture::dump(String8& result) 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\n", prefix, mTexName); - 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); - - - BufferQueue::dump(result, prefix, buffer, SIZE); -} - -static void mtxMul(float out[16], const float a[16], const float b[16]) { - out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; - out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; - out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; - out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; - - out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; - out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; - out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; - out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; - - out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; - out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; - out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; - out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; - - out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; - out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; - out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; - out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; -} - -}; // namespace android diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp deleted file mode 100644 index f88dcaf..0000000 --- a/libs/gui/SurfaceTextureClient.cpp +++ /dev/null @@ -1,713 +0,0 @@ -/* - * 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 "SurfaceTextureClient" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -//#define LOG_NDEBUG 0 - -#include <utils/Log.h> -#include <utils/Trace.h> - -#include <gui/ISurfaceComposer.h> -#include <gui/SurfaceComposerClient.h> -#include <gui/SurfaceTextureClient.h> - -#include <private/gui/ComposerService.h> - -namespace android { - -SurfaceTextureClient::SurfaceTextureClient( - const sp<ISurfaceTexture>& surfaceTexture) -{ - SurfaceTextureClient::init(); - SurfaceTextureClient::setISurfaceTexture(surfaceTexture); -} - -SurfaceTextureClient::SurfaceTextureClient() { - SurfaceTextureClient::init(); -} - -SurfaceTextureClient::~SurfaceTextureClient() { - if (mConnectedToCpu) { - SurfaceTextureClient::disconnect(NATIVE_WINDOW_API_CPU); - } -} - -void SurfaceTextureClient::init() { - // Initialize the ANativeWindow function pointers. - 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; - - const_cast<int&>(ANativeWindow::minSwapInterval) = 0; - const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; - - mReqWidth = 0; - mReqHeight = 0; - mReqFormat = 0; - mReqUsage = 0; - mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; - mDefaultWidth = 0; - mDefaultHeight = 0; - mTransformHint = 0; - mConnectedToCpu = false; -} - -void SurfaceTextureClient::setISurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) -{ - mSurfaceTexture = surfaceTexture; -} - -sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const { - return mSurfaceTexture; -} - -int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interval) { - SurfaceTextureClient* c = getSelf(window); - return c->setSwapInterval(interval); -} - -int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window, - ANativeWindowBuffer** buffer) { - SurfaceTextureClient* c = getSelf(window); - return c->dequeueBuffer(buffer); -} - -int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - SurfaceTextureClient* c = getSelf(window); - return c->cancelBuffer(buffer); -} - -int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - SurfaceTextureClient* c = getSelf(window); - return c->lockBuffer(buffer); -} - -int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - SurfaceTextureClient* c = getSelf(window); - return c->queueBuffer(buffer); -} - -int SurfaceTextureClient::hook_query(const ANativeWindow* window, - int what, int* value) { - const SurfaceTextureClient* c = getSelf(window); - return c->query(what, value); -} - -int SurfaceTextureClient::hook_perform(ANativeWindow* window, int operation, ...) { - va_list args; - va_start(args, operation); - SurfaceTextureClient* c = getSelf(window); - return c->perform(operation, args); -} - -int SurfaceTextureClient::setSwapInterval(int interval) { - ATRACE_CALL(); - // EGL specification states: - // interval is silently clamped to minimum and maximum implementation - // dependent values before being stored. - // Although we don't have to, we apply the same logic here. - - if (interval < minSwapInterval) - interval = minSwapInterval; - - if (interval > maxSwapInterval) - interval = maxSwapInterval; - - status_t res = mSurfaceTexture->setSynchronousMode(interval ? true : false); - - return res; -} - -int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::dequeueBuffer"); - Mutex::Autolock lock(mMutex); - int buf = -1; - status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight, - mReqFormat, mReqUsage); - if (result < 0) { - ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" - "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage, - result); - return result; - } - sp<GraphicBuffer>& gbuf(mSlots[buf]); - if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) { - freeAllBuffers(); - } - - if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { - result = mSurfaceTexture->requestBuffer(buf, &gbuf); - if (result != NO_ERROR) { - ALOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d", - result); - return result; - } - } - *buffer = gbuf.get(); - return OK; -} - -int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::cancelBuffer"); - Mutex::Autolock lock(mMutex); - int i = getSlotFromBufferLocked(buffer); - if (i < 0) { - return i; - } - mSurfaceTexture->cancelBuffer(i); - return OK; -} - -int SurfaceTextureClient::getSlotFromBufferLocked( - android_native_buffer_t* buffer) const { - bool dumpedState = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - // XXX: Dump the slots whenever we hit a NULL entry while searching for - // a buffer. - if (mSlots[i] == NULL) { - if (!dumpedState) { - ALOGD("getSlotFromBufferLocked: encountered NULL buffer in slot %d " - "looking for buffer %p", i, buffer->handle); - for (int j = 0; j < NUM_BUFFER_SLOTS; j++) { - if (mSlots[j] == NULL) { - ALOGD("getSlotFromBufferLocked: %02d: NULL", j); - } else { - ALOGD("getSlotFromBufferLocked: %02d: %p", j, mSlots[j]->handle); - } - } - dumpedState = true; - } - } - - if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) { - return i; - } - } - ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); - return BAD_VALUE; -} - -int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { - ALOGV("SurfaceTextureClient::lockBuffer"); - Mutex::Autolock lock(mMutex); - return OK; -} - -int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::queueBuffer"); - Mutex::Autolock lock(mMutex); - int64_t timestamp; - if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { - timestamp = systemTime(SYSTEM_TIME_MONOTONIC); - ALOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms", - timestamp / 1000000.f); - } else { - timestamp = mTimestamp; - } - int i = getSlotFromBufferLocked(buffer); - if (i < 0) { - return i; - } - status_t err = mSurfaceTexture->queueBuffer(i, timestamp, - &mDefaultWidth, &mDefaultHeight, &mTransformHint); - if (err != OK) { - ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); - } - return err; -} - -int SurfaceTextureClient::query(int what, int* value) const { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::query"); - { // scope for the lock - Mutex::Autolock lock(mMutex); - switch (what) { - case NATIVE_WINDOW_FORMAT: - if (mReqFormat) { - *value = mReqFormat; - return NO_ERROR; - } - break; - case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: - { - sp<ISurfaceComposer> composer( - ComposerService::getComposerService()); - if (composer->authenticateSurfaceTexture(mSurfaceTexture)) { - *value = 1; - } else { - *value = 0; - } - } - return NO_ERROR; - case NATIVE_WINDOW_CONCRETE_TYPE: - *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; - return NO_ERROR; - case NATIVE_WINDOW_DEFAULT_WIDTH: - *value = mDefaultWidth; - return NO_ERROR; - case NATIVE_WINDOW_DEFAULT_HEIGHT: - *value = mDefaultHeight; - return NO_ERROR; - case NATIVE_WINDOW_TRANSFORM_HINT: - *value = mTransformHint; - return NO_ERROR; - } - } - return mSurfaceTexture->query(what, value); -} - -int SurfaceTextureClient::perform(int operation, va_list args) -{ - int res = NO_ERROR; - switch (operation) { - case NATIVE_WINDOW_CONNECT: - // deprecated. must return NO_ERROR. - break; - case NATIVE_WINDOW_DISCONNECT: - // deprecated. must return NO_ERROR. - break; - case NATIVE_WINDOW_SET_USAGE: - res = dispatchSetUsage(args); - break; - case NATIVE_WINDOW_SET_CROP: - res = dispatchSetCrop(args); - break; - case NATIVE_WINDOW_SET_BUFFER_COUNT: - res = dispatchSetBufferCount(args); - break; - case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: - res = dispatchSetBuffersGeometry(args); - break; - case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: - res = dispatchSetBuffersTransform(args); - break; - case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: - res = dispatchSetBuffersTimestamp(args); - break; - case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: - res = dispatchSetBuffersDimensions(args); - break; - case NATIVE_WINDOW_SET_BUFFERS_FORMAT: - res = dispatchSetBuffersFormat(args); - break; - case NATIVE_WINDOW_LOCK: - res = dispatchLock(args); - break; - case NATIVE_WINDOW_UNLOCK_AND_POST: - res = dispatchUnlockAndPost(args); - break; - case NATIVE_WINDOW_SET_SCALING_MODE: - res = dispatchSetScalingMode(args); - break; - case NATIVE_WINDOW_API_CONNECT: - res = dispatchConnect(args); - break; - case NATIVE_WINDOW_API_DISCONNECT: - res = dispatchDisconnect(args); - break; - default: - res = NAME_NOT_FOUND; - break; - } - return res; -} - -int SurfaceTextureClient::dispatchConnect(va_list args) { - int api = va_arg(args, int); - return connect(api); -} - -int SurfaceTextureClient::dispatchDisconnect(va_list args) { - int api = va_arg(args, int); - return disconnect(api); -} - -int SurfaceTextureClient::dispatchSetUsage(va_list args) { - int usage = va_arg(args, int); - return setUsage(usage); -} - -int SurfaceTextureClient::dispatchSetCrop(va_list args) { - android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); - return setCrop(reinterpret_cast<Rect const*>(rect)); -} - -int SurfaceTextureClient::dispatchSetBufferCount(va_list args) { - size_t bufferCount = va_arg(args, size_t); - return setBufferCount(bufferCount); -} - -int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - int f = va_arg(args, int); - int err = setBuffersDimensions(w, h); - if (err != 0) { - return err; - } - return setBuffersFormat(f); -} - -int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - return setBuffersDimensions(w, h); -} - -int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) { - int f = va_arg(args, int); - return setBuffersFormat(f); -} - -int SurfaceTextureClient::dispatchSetScalingMode(va_list args) { - int m = va_arg(args, int); - return setScalingMode(m); -} - -int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { - int transform = va_arg(args, int); - return setBuffersTransform(transform); -} - -int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { - int64_t timestamp = va_arg(args, int64_t); - return setBuffersTimestamp(timestamp); -} - -int SurfaceTextureClient::dispatchLock(va_list args) { - ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*); - ARect* inOutDirtyBounds = va_arg(args, ARect*); - return lock(outBuffer, inOutDirtyBounds); -} - -int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) { - return unlockAndPost(); -} - - -int SurfaceTextureClient::connect(int api) { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::connect"); - Mutex::Autolock lock(mMutex); - int err = mSurfaceTexture->connect(api, - &mDefaultWidth, &mDefaultHeight, &mTransformHint); - if (!err && api == NATIVE_WINDOW_API_CPU) { - mConnectedToCpu = true; - } - return err; -} - -int SurfaceTextureClient::disconnect(int api) { - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::disconnect"); - Mutex::Autolock lock(mMutex); - freeAllBuffers(); - int err = mSurfaceTexture->disconnect(api); - if (!err) { - mReqFormat = 0; - mReqWidth = 0; - mReqHeight = 0; - mReqUsage = 0; - if (api == NATIVE_WINDOW_API_CPU) { - mConnectedToCpu = false; - } - } - return err; -} - -int SurfaceTextureClient::setUsage(uint32_t reqUsage) -{ - ALOGV("SurfaceTextureClient::setUsage"); - Mutex::Autolock lock(mMutex); - mReqUsage = reqUsage; - return OK; -} - -int SurfaceTextureClient::setCrop(Rect const* rect) -{ - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::setCrop"); - Mutex::Autolock lock(mMutex); - - Rect realRect; - if (rect == NULL || rect->isEmpty()) { - realRect = Rect(0, 0); - } else { - realRect = *rect; - } - - status_t err = mSurfaceTexture->setCrop(*rect); - ALOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err)); - - return err; -} - -int SurfaceTextureClient::setBufferCount(int bufferCount) -{ - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::setBufferCount"); - Mutex::Autolock lock(mMutex); - - status_t err = mSurfaceTexture->setBufferCount(bufferCount); - ALOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s", - bufferCount, strerror(-err)); - - if (err == NO_ERROR) { - freeAllBuffers(); - } - - return err; -} - -int SurfaceTextureClient::setBuffersDimensions(int w, int h) -{ - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::setBuffersDimensions"); - Mutex::Autolock lock(mMutex); - - if (w<0 || h<0) - return BAD_VALUE; - - if ((w && !h) || (!w && h)) - return BAD_VALUE; - - mReqWidth = w; - mReqHeight = h; - - status_t err = mSurfaceTexture->setCrop(Rect(0, 0)); - ALOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err)); - - return err; -} - -int SurfaceTextureClient::setBuffersFormat(int format) -{ - ALOGV("SurfaceTextureClient::setBuffersFormat"); - Mutex::Autolock lock(mMutex); - - if (format<0) - return BAD_VALUE; - - mReqFormat = format; - - return NO_ERROR; -} - -int SurfaceTextureClient::setScalingMode(int mode) -{ - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::setScalingMode(%d)", mode); - Mutex::Autolock lock(mMutex); - // mode is validated on the server - status_t err = mSurfaceTexture->setScalingMode(mode); - ALOGE_IF(err, "ISurfaceTexture::setScalingMode(%d) returned %s", - mode, strerror(-err)); - - return err; -} - -int SurfaceTextureClient::setBuffersTransform(int transform) -{ - ATRACE_CALL(); - ALOGV("SurfaceTextureClient::setBuffersTransform"); - Mutex::Autolock lock(mMutex); - status_t err = mSurfaceTexture->setTransform(transform); - return err; -} - -int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp) -{ - ALOGV("SurfaceTextureClient::setBuffersTimestamp"); - Mutex::Autolock lock(mMutex); - mTimestamp = timestamp; - return NO_ERROR; -} - -void SurfaceTextureClient::freeAllBuffers() { - for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i] = 0; - } -} - -// ---------------------------------------------------------------------- -// the lock/unlock APIs must be used from the same thread - -static status_t copyBlt( - const sp<GraphicBuffer>& dst, - const sp<GraphicBuffer>& src, - const Region& reg) -{ - // src and dst with, height and format must be identical. no verification - // is done here. - status_t err; - uint8_t const * src_bits = NULL; - err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); - ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); - - uint8_t* dst_bits = NULL; - err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); - ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); - - Region::const_iterator head(reg.begin()); - Region::const_iterator tail(reg.end()); - if (head != tail && src_bits && dst_bits) { - const size_t bpp = bytesPerPixel(src->format); - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; - - while (head != tail) { - const Rect& r(*head++); - ssize_t h = r.height(); - if (h <= 0) continue; - size_t size = r.width() * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - - if (src_bits) - src->unlock(); - - if (dst_bits) - dst->unlock(); - - return err; -} - -// ---------------------------------------------------------------------------- - -status_t SurfaceTextureClient::lock( - ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) -{ - if (mLockedBuffer != 0) { - ALOGE("Surface::lock failed, already locked"); - return INVALID_OPERATION; - } - - if (!mConnectedToCpu) { - int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU); - if (err) { - return err; - } - // we're intending to do software rendering from this point - setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - } - - ANativeWindowBuffer* out; - status_t err = dequeueBuffer(&out); - 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); - } - - // 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(mOldDirtyRegion.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); - } - - // keep track of the are of the buffer that is "clean" - // (ie: that will be redrawn) - mOldDirtyRegion = 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; -} - -status_t SurfaceTextureClient::unlockAndPost() -{ - if (mLockedBuffer == 0) { - ALOGE("Surface::unlockAndPost failed, no locked buffer"); - return INVALID_OPERATION; - } - - status_t err = mLockedBuffer->unlock(); - ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); - - err = queueBuffer(mLockedBuffer.get()); - ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", - mLockedBuffer->handle, strerror(-err)); - - mPostedBuffer = mLockedBuffer; - mLockedBuffer = 0; - return err; -} - -}; // namespace android diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk deleted file mode 100644 index 55ac133..0000000 --- a/libs/gui/tests/Android.mk +++ /dev/null @@ -1,42 +0,0 @@ -# Build the unit tests, -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := SurfaceTexture_test - -LOCAL_MODULE_TAGS := tests - -LOCAL_SRC_FILES := \ - Surface_test.cpp \ - SurfaceTextureClient_test.cpp \ - SurfaceTexture_test.cpp \ - -LOCAL_SHARED_LIBRARIES := \ - libEGL \ - libGLESv2 \ - libandroid \ - libbinder \ - libcutils \ - libgui \ - libstlport \ - libui \ - libutils \ - -LOCAL_C_INCLUDES := \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport \ - -# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) -# to integrate with auto-test framework. -include $(BUILD_NATIVE_TEST) - -# Include subdirectory makefiles -# ============================================================ - -# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework -# team really wants is to build the stuff defined by this makefile. -ifeq (,$(ONE_SHOT_MAKEFILE)) -include $(call first-makefiles-under,$(LOCAL_PATH)) -endif diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp deleted file mode 100644 index c1a3c98..0000000 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#include <EGL/egl.h> -#include <gtest/gtest.h> -#include <gui/SurfaceTextureClient.h> -#include <utils/threads.h> - -namespace android { - -class SurfaceTextureClientTest : public ::testing::Test { -protected: - SurfaceTextureClientTest(): - mEglDisplay(EGL_NO_DISPLAY), - mEglSurface(EGL_NO_SURFACE), - mEglContext(EGL_NO_CONTEXT) { - } - - virtual void SetUp() { - mST = new SurfaceTexture(123); - mSTC = new SurfaceTextureClient(mST); - mANW = mSTC; - - // We need a valid GL context so we can test updateTexImage() - // This initializes EGL and create a dummy GL context with a - // pbuffer render target. - mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); - - EGLint majorVersion, minorVersion; - EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLConfig myConfig; - EGLint numConfigs = 0; - EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), - &myConfig, 1, &numConfigs)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLint pbufferAttribs[] = { - EGL_WIDTH, 16, - EGL_HEIGHT, 16, - EGL_NONE }; - mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, pbufferAttribs); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_SURFACE, mEglSurface); - - mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_CONTEXT, mEglContext); - - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - } - - virtual void TearDown() { - mST.clear(); - mSTC.clear(); - mANW.clear(); - - eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(mEglDisplay, mEglContext); - eglDestroySurface(mEglDisplay, mEglSurface); - eglTerminate(mEglDisplay); - } - - virtual EGLint const* getConfigAttribs() { - static EGLint sDefaultConfigAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_NONE - }; - - return sDefaultConfigAttribs; - } - - sp<SurfaceTexture> mST; - sp<SurfaceTextureClient> mSTC; - sp<ANativeWindow> mANW; - - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLContext mEglContext; -}; - -TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) { - sp<ISurfaceTexture> ist(mSTC->getISurfaceTexture()); - ASSERT_TRUE(ist != NULL); -} - -TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) { - int result = -123; - int err = mANW->query(mANW.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, - &result); - EXPECT_EQ(NO_ERROR, err); - EXPECT_EQ(0, result); -} - -TEST_F(SurfaceTextureClientTest, ConcreteTypeIsSurfaceTextureClient) { - int result = -123; - int err = mANW->query(mANW.get(), NATIVE_WINDOW_CONCRETE_TYPE, &result); - EXPECT_EQ(NO_ERROR, err); - EXPECT_EQ(NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, result); -} - -TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { - EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_DISPLAY, dpy); - - EGLint majorVersion; - EGLint minorVersion; - EXPECT_TRUE(eglInitialize(dpy, &majorVersion, &minorVersion)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLConfig myConfig = {0}; - EGLint numConfigs = 0; - EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_STENCIL_SIZE, 8, - EGL_NONE }; - EXPECT_TRUE(eglChooseConfig(dpy, configAttribs, &myConfig, 1, - &numConfigs)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, mANW.get(), - NULL); - EXPECT_NE(EGL_NO_SURFACE, eglSurface); - EXPECT_EQ(EGL_SUCCESS, eglGetError()); - - eglTerminate(dpy); -} - -TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) { - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, 0, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, -1, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, -1)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, -1, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 8, 0)); - EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 8, 0, 0)); -} - -TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) { - ANativeWindowBuffer* buf; - ASSERT_EQ(OK, mANW->dequeueBuffer(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)); -} - -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)); - 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)); -} - -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)); - 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)); -} - -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)); - 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)); -} - -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)); - 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)); - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(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)); -} - -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)); - 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)); - EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0)); - ASSERT_EQ(OK, mANW->dequeueBuffer(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)); -} - -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)); - 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)); -} - -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])); - EXPECT_NE(buf[0], buf[1]); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[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])); - 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])); -} - -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])); - 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])); - 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])); - 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])); -} - -TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { - android_native_buffer_t* buf[3]; - 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])); - 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])); - - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(OK, mST->updateTexImage()); -} - -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])); - 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])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]); -} - -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])); - 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])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]); -} - -TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { - android_native_buffer_t* buf[3]; - 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])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]); - - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1])); - EXPECT_NE(buf[0], buf[1]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - - ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2])); - EXPECT_NE(buf[1], buf[2]); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2])); - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]); -} - -// XXX: We currently have no hardware that properly handles dequeuing the -// buffer that is currently bound to the texture. -TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) { - android_native_buffer_t* buf[3]; - 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)); - 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])); - EXPECT_NE(buf[0], buf[1]); - EXPECT_NE(buf[1], buf[2]); - EXPECT_NE(buf[2], buf[0]); - EXPECT_EQ(firstBuf, buf[2]); -} - -TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { - android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - 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])); - - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2])); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1])); - - EXPECT_EQ(OK, mST->updateTexImage()); - EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]); - - EXPECT_EQ(OK, mANW->dequeueBuffer(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])); - - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2])); -} - -// XXX: This is not expected to pass until the synchronization hacks are removed -// from the SurfaceTexture class. -TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) { - class MyThread : public Thread { - sp<SurfaceTexture> mST; - EGLContext ctx; - EGLSurface sur; - EGLDisplay dpy; - bool mBufferRetired; - Mutex mLock; - virtual bool threadLoop() { - eglMakeCurrent(dpy, sur, sur, ctx); - usleep(20000); - Mutex::Autolock _l(mLock); - mST->updateTexImage(); - mBufferRetired = true; - eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - return false; - } - public: - MyThread(const sp<SurfaceTexture>& mST) - : mST(mST), mBufferRetired(false) { - ctx = eglGetCurrentContext(); - sur = eglGetCurrentSurface(EGL_DRAW); - dpy = eglGetCurrentDisplay(); - eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - ~MyThread() { - eglMakeCurrent(dpy, sur, sur, ctx); - } - void bufferDequeued() { - Mutex::Autolock _l(mLock); - EXPECT_EQ(true, mBufferRetired); - } - }; - - android_native_buffer_t* buf[3]; - 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])); - 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])); - 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])); - thread->bufferDequeued(); - thread->requestExitAndWait(); -} - -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, mST->updateTexImage()); - mST->getTransformMatrix(mtx); - - EXPECT_EQ(1.f, mtx[0]); - EXPECT_EQ(0.f, mtx[1]); - EXPECT_EQ(0.f, mtx[2]); - EXPECT_EQ(0.f, mtx[3]); - - EXPECT_EQ(0.f, mtx[4]); - EXPECT_EQ(-1.f, mtx[5]); - EXPECT_EQ(0.f, mtx[6]); - EXPECT_EQ(0.f, mtx[7]); - - EXPECT_EQ(0.f, mtx[8]); - EXPECT_EQ(0.f, mtx[9]); - EXPECT_EQ(1.f, mtx[10]); - EXPECT_EQ(0.f, mtx[11]); - - EXPECT_EQ(0.f, mtx[12]); - EXPECT_EQ(1.f, mtx[13]); - EXPECT_EQ(0.f, mtx[14]); - EXPECT_EQ(1.f, mtx[15]); -} - -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, mST->updateTexImage()); - ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers - mST->getTransformMatrix(mtx); - - EXPECT_EQ(1.f, mtx[0]); - EXPECT_EQ(0.f, mtx[1]); - EXPECT_EQ(0.f, mtx[2]); - EXPECT_EQ(0.f, mtx[3]); - - EXPECT_EQ(0.f, mtx[4]); - EXPECT_EQ(-1.f, mtx[5]); - EXPECT_EQ(0.f, mtx[6]); - EXPECT_EQ(0.f, mtx[7]); - - EXPECT_EQ(0.f, mtx[8]); - EXPECT_EQ(0.f, mtx[9]); - EXPECT_EQ(1.f, mtx[10]); - EXPECT_EQ(0.f, mtx[11]); - - EXPECT_EQ(0.f, mtx[12]); - EXPECT_EQ(1.f, mtx[13]); - EXPECT_EQ(0.f, mtx[14]); - EXPECT_EQ(1.f, mtx[15]); -} - -TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) { - android_native_buffer_t* buf[3]; - float mtx[16] = {}; - android_native_rect_t crop; - crop.left = 0; - crop.top = 0; - crop.right = 5; - crop.bottom = 5; - - 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_set_crop(mANW.get(), &crop)); - ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0])); - ASSERT_EQ(OK, mST->updateTexImage()); - ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers - mST->getTransformMatrix(mtx); - - // This accounts for the 1 texel shrink for each edge that's included in the - // transform matrix to avoid texturing outside the crop region. - EXPECT_EQ(.5f, mtx[0]); - EXPECT_EQ(0.f, mtx[1]); - EXPECT_EQ(0.f, mtx[2]); - EXPECT_EQ(0.f, mtx[3]); - - EXPECT_EQ(0.f, mtx[4]); - EXPECT_EQ(-.5f, mtx[5]); - EXPECT_EQ(0.f, mtx[6]); - EXPECT_EQ(0.f, mtx[7]); - - EXPECT_EQ(0.f, mtx[8]); - EXPECT_EQ(0.f, mtx[9]); - EXPECT_EQ(1.f, mtx[10]); - EXPECT_EQ(0.f, mtx[11]); - - EXPECT_EQ(0.f, mtx[12]); - EXPECT_EQ(.5f, mtx[13]); - EXPECT_EQ(0.f, mtx[14]); - EXPECT_EQ(1.f, mtx[15]); -} - -// This test verifies that the buffer format can be queried immediately after -// it is set. -TEST_F(SurfaceTextureClientTest, QueryFormatAfterSettingWorks) { - sp<ANativeWindow> anw(mSTC); - int fmts[] = { - // RGBA_8888 should not come first, as it's the default - HAL_PIXEL_FORMAT_RGBX_8888, - HAL_PIXEL_FORMAT_RGBA_8888, - HAL_PIXEL_FORMAT_RGB_888, - HAL_PIXEL_FORMAT_RGB_565, - HAL_PIXEL_FORMAT_BGRA_8888, - HAL_PIXEL_FORMAT_RGBA_5551, - HAL_PIXEL_FORMAT_RGBA_4444, - HAL_PIXEL_FORMAT_YV12, - }; - - const int numFmts = (sizeof(fmts) / sizeof(fmts[0])); - for (int i = 0; i < numFmts; i++) { - int fmt = -1; - ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, fmts[i])); - ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt)); - EXPECT_EQ(fmts[i], fmt); - } -} - -class MultiSurfaceTextureClientTest : public ::testing::Test { - -public: - MultiSurfaceTextureClientTest() : - mEglDisplay(EGL_NO_DISPLAY), - mEglContext(EGL_NO_CONTEXT) { - for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { - mEglSurfaces[i] = EGL_NO_CONTEXT; - } - } - -protected: - - enum { NUM_SURFACE_TEXTURES = 32 }; - - virtual void SetUp() { - mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); - - EGLint majorVersion, minorVersion; - EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLConfig myConfig; - EGLint numConfigs = 0; - EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - EXPECT_TRUE(eglChooseConfig(mEglDisplay, configAttribs, &myConfig, 1, - &numConfigs)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, - 0); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_CONTEXT, mEglContext); - - for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { - sp<SurfaceTexture> st(new SurfaceTexture(i)); - sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st)); - mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig, - static_cast<ANativeWindow*>(stc.get()), NULL); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]); - } - } - - virtual void TearDown() { - eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - - for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { - if (mEglSurfaces[i] != EGL_NO_SURFACE) { - eglDestroySurface(mEglDisplay, mEglSurfaces[i]); - } - } - - if (mEglContext != EGL_NO_CONTEXT) { - eglDestroyContext(mEglDisplay, mEglContext); - } - - if (mEglDisplay != EGL_NO_DISPLAY) { - eglTerminate(mEglDisplay); - } - } - - EGLDisplay mEglDisplay; - EGLSurface mEglSurfaces[NUM_SURFACE_TEXTURES]; - EGLContext mEglContext; -}; - -// XXX: This test is disabled because it causes a hang on some devices. See bug -// 5015672. -TEST_F(MultiSurfaceTextureClientTest, DISABLED_MakeCurrentBetweenSurfacesWorks) { - for (int iter = 0; iter < 8; iter++) { - for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { - eglMakeCurrent(mEglDisplay, mEglSurfaces[i], mEglSurfaces[i], - mEglContext); - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(mEglDisplay, mEglSurfaces[i]); - } - } -} - -} // namespace android diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp deleted file mode 100644 index 8c6defe..0000000 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ /dev/null @@ -1,1730 +0,0 @@ -/* - * Copyright (C) 2011 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 "SurfaceTexture_test" -//#define LOG_NDEBUG 0 - -#include <gtest/gtest.h> -#include <gui/SurfaceTexture.h> -#include <gui/SurfaceTextureClient.h> -#include <ui/GraphicBuffer.h> -#include <utils/String8.h> -#include <utils/threads.h> - -#include <gui/ISurfaceComposer.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <ui/FramebufferNativeWindow.h> - -namespace android { - -class GLTest : public ::testing::Test { -protected: - - GLTest(): - mEglDisplay(EGL_NO_DISPLAY), - mEglSurface(EGL_NO_SURFACE), - mEglContext(EGL_NO_CONTEXT) { - } - - virtual void SetUp() { - mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); - - EGLint majorVersion; - EGLint minorVersion; - EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - RecordProperty("EglVersionMajor", majorVersion); - RecordProperty("EglVersionMajor", minorVersion); - - EGLint numConfigs = 0; - EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig, - 1, &numConfigs)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS"); - if (displaySecsEnv != NULL) { - mDisplaySecs = atoi(displaySecsEnv); - if (mDisplaySecs < 0) { - mDisplaySecs = 0; - } - } else { - mDisplaySecs = 0; - } - - if (mDisplaySecs > 0) { - mComposerClient = new SurfaceComposerClient; - ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); - - mSurfaceControl = mComposerClient->createSurface( - String8("Test Surface"), 0, - getSurfaceWidth(), getSurfaceHeight(), - PIXEL_FORMAT_RGB_888, 0); - - ASSERT_TRUE(mSurfaceControl != NULL); - ASSERT_TRUE(mSurfaceControl->isValid()); - - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); - ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(); - - sp<ANativeWindow> window = mSurfaceControl->getSurface(); - mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, - window.get(), NULL); - } else { - EGLint pbufferAttribs[] = { - EGL_WIDTH, getSurfaceWidth(), - EGL_HEIGHT, getSurfaceHeight(), - EGL_NONE }; - - mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig, - pbufferAttribs); - } - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_SURFACE, mEglSurface); - - mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT, - getContextAttribs()); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_CONTEXT, mEglContext); - - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EGLint w, h; - EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - RecordProperty("EglSurfaceWidth", w); - RecordProperty("EglSurfaceHeight", h); - - glViewport(0, 0, w, h); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - } - - virtual void TearDown() { - // Display the result - if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) { - eglSwapBuffers(mEglDisplay, mEglSurface); - sleep(mDisplaySecs); - } - - if (mComposerClient != NULL) { - mComposerClient->dispose(); - } - if (mEglContext != EGL_NO_CONTEXT) { - eglDestroyContext(mEglDisplay, mEglContext); - } - if (mEglSurface != EGL_NO_SURFACE) { - eglDestroySurface(mEglDisplay, mEglSurface); - } - if (mEglDisplay != EGL_NO_DISPLAY) { - eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - eglTerminate(mEglDisplay); - } - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - } - - virtual EGLint const* getConfigAttribs() { - static EGLint sDefaultConfigAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_STENCIL_SIZE, 8, - EGL_NONE }; - - return sDefaultConfigAttribs; - } - - virtual EGLint const* getContextAttribs() { - static EGLint sDefaultContextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE }; - - return sDefaultContextAttribs; - } - - virtual EGLint getSurfaceWidth() { - return 512; - } - - virtual EGLint getSurfaceHeight() { - return 512; - } - - void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) { - GLuint shader = glCreateShader(shaderType); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - if (shader) { - glShaderSource(shader, 1, &pSource, NULL); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glCompileShader(shader); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - if (!compiled) { - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - if (infoLen) { - char* buf = (char*) malloc(infoLen); - if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); - printf("Shader compile log:\n%s\n", buf); - free(buf); - FAIL(); - } - } else { - char* buf = (char*) malloc(0x1000); - if (buf) { - glGetShaderInfoLog(shader, 0x1000, NULL, buf); - printf("Shader compile log:\n%s\n", buf); - free(buf); - FAIL(); - } - } - glDeleteShader(shader); - shader = 0; - } - } - ASSERT_TRUE(shader != 0); - *outShader = shader; - } - - void createProgram(const char* pVertexSource, const char* pFragmentSource, - GLuint* outPgm) { - GLuint vertexShader, fragmentShader; - { - SCOPED_TRACE("compiling vertex shader"); - loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader); - if (HasFatalFailure()) { - return; - } - } - { - SCOPED_TRACE("compiling fragment shader"); - loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader); - if (HasFatalFailure()) { - return; - } - } - - GLuint program = glCreateProgram(); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - if (program) { - glAttachShader(program, vertexShader); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glAttachShader(program, fragmentShader); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = (char*) malloc(bufLength); - if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); - printf("Program link log:\n%s\n", buf); - free(buf); - FAIL(); - } - } - glDeleteProgram(program); - program = 0; - } - } - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - ASSERT_TRUE(program != 0); - *outPgm = program; - } - - static int abs(int value) { - return value > 0 ? value : -value; - } - - ::testing::AssertionResult checkPixel(int x, int y, int r, - int g, int b, int a, int tolerance=2) { - GLubyte pixel[4]; - String8 msg; - glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); - GLenum err = glGetError(); - if (err != GL_NO_ERROR) { - msg += String8::format("error reading pixel: %#x", err); - while ((err = glGetError()) != GL_NO_ERROR) { - msg += String8::format(", %#x", err); - } - fprintf(stderr, "pixel check failure: %s\n", msg.string()); - return ::testing::AssertionFailure( - ::testing::Message(msg.string())); - } - if (r >= 0 && abs(r - int(pixel[0])) > tolerance) { - msg += String8::format("r(%d isn't %d)", pixel[0], r); - } - if (g >= 0 && abs(g - int(pixel[1])) > tolerance) { - if (!msg.isEmpty()) { - msg += " "; - } - msg += String8::format("g(%d isn't %d)", pixel[1], g); - } - if (b >= 0 && abs(b - int(pixel[2])) > tolerance) { - if (!msg.isEmpty()) { - msg += " "; - } - msg += String8::format("b(%d isn't %d)", pixel[2], b); - } - if (a >= 0 && abs(a - int(pixel[3])) > tolerance) { - if (!msg.isEmpty()) { - msg += " "; - } - msg += String8::format("a(%d isn't %d)", pixel[3], a); - } - if (!msg.isEmpty()) { - fprintf(stderr, "pixel check failure: %s\n", msg.string()); - return ::testing::AssertionFailure( - ::testing::Message(msg.string())); - } else { - return ::testing::AssertionSuccess(); - } - } - - int mDisplaySecs; - sp<SurfaceComposerClient> mComposerClient; - sp<SurfaceControl> mSurfaceControl; - - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLContext mEglContext; - EGLConfig mGlConfig; -}; - -// XXX: Code above this point should live elsewhere - -class SurfaceTextureGLTest : public GLTest { -protected: - enum { TEX_ID = 123 }; - - virtual void SetUp() { - GLTest::SetUp(); - mST = new SurfaceTexture(TEX_ID); - mSTC = new SurfaceTextureClient(mST); - mANW = mSTC; - - const char vsrc[] = - "attribute vec4 vPosition;\n" - "varying vec2 texCoords;\n" - "uniform mat4 texMatrix;\n" - "void main() {\n" - " vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n" - " texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n" - " gl_Position = vPosition;\n" - "}\n"; - - const char fsrc[] = - "#extension GL_OES_EGL_image_external : require\n" - "precision mediump float;\n" - "uniform samplerExternalOES texSampler;\n" - "varying vec2 texCoords;\n" - "void main() {\n" - " gl_FragColor = texture2D(texSampler, texCoords);\n" - "}\n"; - - { - SCOPED_TRACE("creating shader program"); - createProgram(vsrc, fsrc, &mPgm); - if (HasFatalFailure()) { - return; - } - } - - mPositionHandle = glGetAttribLocation(mPgm, "vPosition"); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - ASSERT_NE(-1, mPositionHandle); - mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler"); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - ASSERT_NE(-1, mTexSamplerHandle); - mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix"); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - ASSERT_NE(-1, mTexMatrixHandle); - } - - virtual void TearDown() { - mANW.clear(); - mSTC.clear(); - mST.clear(); - GLTest::TearDown(); - } - - // drawTexture draws the SurfaceTexture over the entire GL viewport. - void drawTexture() { - const GLfloat triangleVertices[] = { - -1.0f, 1.0f, - -1.0f, -1.0f, - 1.0f, -1.0f, - 1.0f, 1.0f, - }; - - glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, - triangleVertices); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glEnableVertexAttribArray(mPositionHandle); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - - glUseProgram(mPgm); - glUniform1i(mTexSamplerHandle, 0); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - - // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as - // they're setting the defautls for that target, but when hacking things - // to use GL_TEXTURE_2D they are needed to achieve the same behavior. - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, - GL_LINEAR); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - - GLfloat texMatrix[16]; - mST->getTransformMatrix(texMatrix); - glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - } - - class FrameWaiter : public SurfaceTexture::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; - }; - - sp<SurfaceTexture> mST; - sp<SurfaceTextureClient> mSTC; - sp<ANativeWindow> mANW; - - GLuint mPgm; - GLint mPositionHandle; - GLint mTexSamplerHandle; - GLint mTexMatrixHandle; -}; - -// Fill a YV12 buffer with a multi-colored checkerboard pattern -void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) { - const int blockWidth = w > 16 ? w / 16 : 1; - const int blockHeight = h > 16 ? h / 16 : 1; - const int yuvTexOffsetY = 0; - int yuvTexStrideY = stride; - int yuvTexOffsetV = yuvTexStrideY * h; - int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; - int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; - int yuvTexStrideU = yuvTexStrideV; - for (int x = 0; x < w; x++) { - for (int y = 0; y < h; y++) { - int parityX = (x / blockWidth) & 1; - int parityY = (y / blockHeight) & 1; - unsigned char intensity = (parityX ^ parityY) ? 63 : 191; - buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; - if (x < w / 2 && y < h / 2) { - buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; - if (x * 2 < w / 2 && y * 2 < h / 2) { - buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] = - buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] = - buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] = - buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = - intensity; - } - } - } - } -} - -// Fill a YV12 buffer with red outside a given rectangle and green inside it. -void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, - const android_native_rect_t& rect) { - const int yuvTexOffsetY = 0; - int yuvTexStrideY = stride; - int yuvTexOffsetV = yuvTexStrideY * h; - int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; - int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; - int yuvTexStrideU = yuvTexStrideV; - for (int x = 0; x < w; x++) { - for (int y = 0; y < h; y++) { - bool inside = rect.left <= x && x < rect.right && - rect.top <= y && y < rect.bottom; - buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64; - if (x < w / 2 && y < h / 2) { - bool inside = rect.left <= 2*x && 2*x < rect.right && - rect.top <= 2*y && 2*y < rect.bottom; - buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16; - buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = - inside ? 16 : 255; - } - } - } -} - -void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) { - const size_t PIXEL_SIZE = 4; - for (int x = 0; x < w; x++) { - for (int y = 0; y < h; y++) { - off_t offset = (y * stride + x) * PIXEL_SIZE; - for (int c = 0; c < 4; c++) { - int parityX = (x / (1 << (c+2))) & 1; - int parityY = (y / (1 << (c+2))) & 1; - buf[offset + c] = (parityX ^ parityY) ? 231 : 35; - } - } - } -} - -void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r, - uint8_t g, uint8_t b, uint8_t a) { - const size_t PIXEL_SIZE = 4; - for (int y = 0; y < h; y++) { - for (int x = 0; x < h; x++) { - off_t offset = (y * stride + x) * PIXEL_SIZE; - buf[offset + 0] = r; - buf[offset + 1] = g; - buf[offset + 2] = b; - buf[offset + 3] = a; - } - } -} - -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { - const int texWidth = 64; - const int texHeight = 66; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); - - ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(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())); - - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, texWidth, texHeight); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255)); - EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255)); - EXPECT_TRUE(checkPixel(63, 65, 0, 133, 0, 255)); - EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255)); - - EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255)); - EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255)); - EXPECT_TRUE(checkPixel(52, 51, 98, 255, 73, 255)); - EXPECT_TRUE(checkPixel( 7, 31, 155, 0, 118, 255)); - EXPECT_TRUE(checkPixel(31, 9, 107, 24, 87, 255)); - EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255)); - EXPECT_TRUE(checkPixel(36, 22, 155, 29, 0, 255)); -} - -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { - const int texWidth = 64; - const int texHeight = 64; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); - - ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(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())); - - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, texWidth, texHeight); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 0, 133, 0, 255)); - EXPECT_TRUE(checkPixel(63, 0, 255, 127, 255, 255)); - EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255)); - EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255)); - - EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255)); - EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255)); - EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255)); - EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255)); - EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255)); - EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255)); - EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255)); -} - -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { - const int texWidth = 64; - const int texHeight = 66; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); - - android_native_rect_t crops[] = { - {4, 6, 22, 36}, - {0, 6, 22, 36}, - {4, 0, 22, 36}, - {4, 6, texWidth, 36}, - {4, 6, 22, texHeight}, - }; - - for (int i = 0; i < 5; i++) { - const android_native_rect_t& crop(crops[i]); - SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", - crop.left, crop.top, crop.right, crop.bottom).string()); - - ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop)); - - ANativeWindowBuffer* anb; - ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(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())); - - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, 64, 64); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(63, 0, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(63, 63, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel( 0, 63, 82, 255, 35, 255)); - - EXPECT_TRUE(checkPixel(25, 14, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(35, 31, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(57, 6, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel( 5, 42, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(32, 33, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(16, 26, 82, 255, 35, 255)); - EXPECT_TRUE(checkPixel(46, 51, 82, 255, 35, 255)); - } -} - -// This test is intended to catch synchronization bugs between the CPU-written -// and GPU-read buffers. -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { - enum { texWidth = 16 }; - enum { texHeight = 16 }; - enum { numFrames = 1024 }; - - ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); - ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2)); - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - GRALLOC_USAGE_SW_WRITE_OFTEN)); - - struct TestPixel { - int x; - int y; - }; - const TestPixel testPixels[] = { - { 4, 11 }, - { 12, 14 }, - { 7, 2 }, - }; - enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])}; - - class ProducerThread : public Thread { - public: - ProducerThread(const sp<ANativeWindow>& anw, - const TestPixel* testPixels): - mANW(anw), - mTestPixels(testPixels) { - } - - virtual ~ProducerThread() { - } - - virtual bool threadLoop() { - for (int i = 0; i < numFrames; i++) { - ANativeWindowBuffer* anb; - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { - return false; - } - if (anb == NULL) { - return false; - } - - 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(); - int yuvTexStrideY = stride; - int yuvTexOffsetV = yuvTexStrideY * texHeight; - int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; - int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; - int yuvTexStrideU = yuvTexStrideV; - - uint8_t* img = NULL; - buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); - - // Gray out all the test pixels first, so we're more likely to - // see a failure if GL is still texturing from the buffer we - // just dequeued. - for (int j = 0; j < numTestPixels; j++) { - int x = mTestPixels[j].x; - int y = mTestPixels[j].y; - uint8_t value = 128; - img[y*stride + x] = value; - } - - // Fill the buffer with gray. - for (int y = 0; y < texHeight; y++) { - for (int x = 0; x < texWidth; x++) { - img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128; - img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128; - img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128; - } - } - - // Set the test pixels to either white or black. - for (int j = 0; j < numTestPixels; j++) { - int x = mTestPixels[j].x; - int y = mTestPixels[j].y; - uint8_t value = 0; - if (j == (i % numTestPixels)) { - value = 255; - } - img[y*stride + x] = value; - } - - buf->unlock(); - if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()) - != NO_ERROR) { - return false; - } - } - return false; - } - - sp<ANativeWindow> mANW; - const TestPixel* mTestPixels; - }; - - sp<FrameWaiter> fw(new FrameWaiter); - mST->setFrameAvailableListener(fw); - - sp<Thread> pt(new ProducerThread(mANW, testPixels)); - pt->run(); - - glViewport(0, 0, texWidth, texHeight); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - // We wait for the first two frames up front so that the producer will be - // likely to dequeue the buffer that's currently being textured from. - fw->waitForFrame(); - fw->waitForFrame(); - - for (int i = 0; i < numFrames; i++) { - SCOPED_TRACE(String8::format("frame %d", i).string()); - - // We must wait for each frame to come in because if we ever do an - // updateTexImage call that doesn't consume a newly available buffer - // then the producer and consumer will get out of sync, which will cause - // a deadlock. - if (i > 1) { - fw->waitForFrame(); - } - mST->updateTexImage(); - drawTexture(); - - for (int j = 0; j < numTestPixels; j++) { - int x = testPixels[j].x; - int y = testPixels[j].y; - uint8_t value = 0; - if (j == (i % numTestPixels)) { - // We must y-invert the texture coords - EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255)); - } else { - // We must y-invert the texture coords - EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255)); - } - } - } - - pt->requestExitAndWait(); -} - -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) { - const int texWidth = 64; - const int texHeight = 66; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - 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_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)); - fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride()); - buf->unlock(); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); - - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, texWidth, texHeight); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); - EXPECT_TRUE(checkPixel(63, 0, 231, 231, 231, 231)); - EXPECT_TRUE(checkPixel(63, 65, 231, 231, 231, 231)); - EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35)); - - EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(23, 65, 231, 35, 231, 35)); - EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35)); - EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35)); - EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231)); - EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231)); - EXPECT_TRUE(checkPixel(37, 47, 231, 35, 231, 231)); - EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35)); - EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35)); - EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231)); - EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231)); - EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231)); - EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35)); - EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231)); -} - -TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) { - const int texWidth = 64; - const int texHeight = 64; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - 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_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)); - fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride()); - buf->unlock(); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); - - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, texWidth, texHeight); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 231, 231, 231, 231)); - EXPECT_TRUE(checkPixel(63, 0, 35, 35, 35, 35)); - EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231)); - EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35)); - - EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231, 35)); - EXPECT_TRUE(checkPixel(16, 1, 231, 231, 35, 231)); - EXPECT_TRUE(checkPixel(21, 12, 231, 35, 35, 231)); - EXPECT_TRUE(checkPixel(26, 51, 231, 35, 231, 35)); - EXPECT_TRUE(checkPixel( 5, 32, 35, 231, 231, 35)); - EXPECT_TRUE(checkPixel(13, 8, 35, 231, 231, 231)); - EXPECT_TRUE(checkPixel(46, 3, 35, 35, 231, 35)); - EXPECT_TRUE(checkPixel(30, 33, 35, 35, 35, 35)); - EXPECT_TRUE(checkPixel( 6, 52, 231, 231, 35, 35)); - EXPECT_TRUE(checkPixel(55, 33, 35, 231, 35, 231)); - EXPECT_TRUE(checkPixel(16, 29, 35, 35, 231, 231)); - EXPECT_TRUE(checkPixel( 1, 30, 35, 35, 35, 231)); - EXPECT_TRUE(checkPixel(41, 37, 35, 35, 231, 231)); - EXPECT_TRUE(checkPixel(46, 29, 231, 231, 35, 35)); - EXPECT_TRUE(checkPixel(15, 25, 35, 231, 35, 231)); - EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35)); -} - -TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { - class ProducerThread : public Thread { - public: - ProducerThread(const sp<ANativeWindow>& anw): - mANW(anw), - mDequeueError(NO_ERROR) { - } - - virtual ~ProducerThread() { - } - - virtual bool threadLoop() { - Mutex::Autolock lock(mMutex); - ANativeWindowBuffer* anb; - - // Frame 1 - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { - return false; - } - if (anb == NULL) { - return false; - } - if (mANW->queueBuffer(mANW.get(), anb) - != NO_ERROR) { - return false; - } - - // Frame 2 - if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { - return false; - } - if (anb == NULL) { - return false; - } - if (mANW->queueBuffer(mANW.get(), anb) - != NO_ERROR) { - return false; - } - - // Frame 3 - error expected - mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb); - return false; - } - - status_t getDequeueError() { - Mutex::Autolock lock(mMutex); - return mDequeueError; - } - - private: - sp<ANativeWindow> mANW; - status_t mDequeueError; - Mutex mMutex; - }; - - sp<FrameWaiter> fw(new FrameWaiter); - mST->setFrameAvailableListener(fw); - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - ASSERT_EQ(OK, mST->setBufferCountServer(2)); - - sp<Thread> pt(new ProducerThread(mANW)); - pt->run(); - - fw->waitForFrame(); - fw->waitForFrame(); - - // Sleep for 100ms to allow the producer thread's dequeueBuffer call to - // block waiting for a buffer to become available. - usleep(100000); - - mST->abandon(); - - pt->requestExitAndWait(); - ASSERT_EQ(NO_INIT, - reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError()); -} - -TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) { - int texHeight = 16; - ANativeWindowBuffer* anb; - - GLint maxTextureSize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - - // make sure it works with small textures - mST->setDefaultBufferSize(16, texHeight); - EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(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, 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(maxTextureSize, anb->width); - EXPECT_EQ(texHeight, anb->height); - EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); - 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(maxTextureSize+1, anb->width); - EXPECT_EQ(texHeight, anb->height); - EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); - ASSERT_NE(NO_ERROR, mST->updateTexImage()); -} - -/* - * This test fixture is for testing GL -> GL texture streaming. It creates an - * EGLSurface and an EGLContext for the image producer to use. - */ -class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest { -protected: - SurfaceTextureGLToGLTest(): - mProducerEglSurface(EGL_NO_SURFACE), - mProducerEglContext(EGL_NO_CONTEXT) { - } - - virtual void SetUp() { - SurfaceTextureGLTest::SetUp(); - - EGLConfig myConfig = {0}; - EGLint numConfigs = 0; - EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig, - 1, &numConfigs)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig, - mANW.get(), NULL); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface); - - mProducerEglContext = eglCreateContext(mEglDisplay, myConfig, - EGL_NO_CONTEXT, getContextAttribs()); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext); - } - - virtual void TearDown() { - if (mProducerEglContext != EGL_NO_CONTEXT) { - eglDestroyContext(mEglDisplay, mProducerEglContext); - } - if (mProducerEglSurface != EGL_NO_SURFACE) { - eglDestroySurface(mEglDisplay, mProducerEglSurface); - } - SurfaceTextureGLTest::TearDown(); - } - - EGLSurface mProducerEglSurface; - EGLContext mProducerEglContext; -}; - -TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) { - const int texWidth = 64; - const int texHeight = 64; - - mST->setDefaultBufferSize(texWidth, texHeight); - - // Do the producer side of things - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - // This is needed to ensure we pick up a buffer of the correct size. - eglSwapBuffers(mEglDisplay, mProducerEglSurface); - - glClearColor(0.6, 0.6, 0.6, 0.6); - glClear(GL_COLOR_BUFFER_BIT); - - glEnable(GL_SCISSOR_TEST); - glScissor(4, 4, 4, 4); - glClearColor(1.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - glScissor(24, 48, 4, 4); - glClearColor(0.0, 1.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - glScissor(37, 17, 4, 4); - glClearColor(0.0, 0.0, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - eglSwapBuffers(mEglDisplay, mProducerEglSurface); - - // Do the consumer side of things - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - glDisable(GL_SCISSOR_TEST); - - mST->updateTexImage(); // Skip the first frame, which was empty - mST->updateTexImage(); - - glClearColor(0.2, 0.2, 0.2, 0.2); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, texWidth, texHeight); - drawTexture(); - - EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153)); - - EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255)); - EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255)); - EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255)); - EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153)); - EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153)); -} - -TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) { - sp<GraphicBuffer> buffers[3]; - - // This test requires async mode to run on a single thread. - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - for (int i = 0; i < 3; i++) { - // Produce a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(mEglDisplay, mProducerEglSurface); - - // Consume a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - mST->updateTexImage(); - buffers[i] = mST->getCurrentBuffer(); - } - - // Destroy the GL texture object to release its ref on buffers[2]. - GLuint texID = TEX_ID; - glDeleteTextures(1, &texID); - - // Destroy the EGLSurface - EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - // Release the ref that the SurfaceTexture has on buffers[2]. - mST->abandon(); - - EXPECT_EQ(1, buffers[0]->getStrongCount()); - EXPECT_EQ(1, buffers[1]->getStrongCount()); - - // Depending on how lazily the GL driver dequeues buffers, we may end up - // with either two or three total buffers. If there are three, make sure - // the last one was properly down-ref'd. - if (buffers[2] != buffers[0]) { - EXPECT_EQ(1, buffers[2]->getStrongCount()); - } -} - -TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) { - sp<GraphicBuffer> buffers[3]; - - // This test requires async mode to run on a single thread. - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - for (int i = 0; i < 3; i++) { - // Produce a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - // Consume a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_EQ(NO_ERROR, mST->updateTexImage()); - buffers[i] = mST->getCurrentBuffer(); - } - - // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has - // on buffers[2]. - mST->abandon(); - - // Destroy the GL texture object to release its ref on buffers[2]. - GLuint texID = TEX_ID; - glDeleteTextures(1, &texID); - - // Destroy the EGLSurface. - EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - EXPECT_EQ(1, buffers[0]->getStrongCount()); - EXPECT_EQ(1, buffers[1]->getStrongCount()); - - // Depending on how lazily the GL driver dequeues buffers, we may end up - // with either two or three total buffers. If there are three, make sure - // the last one was properly down-ref'd. - if (buffers[2] != buffers[0]) { - EXPECT_EQ(1, buffers[2]->getStrongCount()); - } -} - -TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) { - // This test requires 3 buffers to run on a single thread. - mST->setBufferCountServer(3); - - ASSERT_TRUE(mST->isSynchronousMode()); - - for (int i = 0; i < 10; i++) { - // Produce a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - // Consume a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_EQ(NO_ERROR, mST->updateTexImage()); - } - - ASSERT_TRUE(mST->isSynchronousMode()); -} - -/* - * This test fixture is for testing GL -> GL texture streaming from one thread - * to another. It contains functionality to create a producer thread that will - * perform GL rendering to an ANativeWindow that feeds frames to a - * SurfaceTexture. Additionally it supports interlocking the producer and - * consumer threads so that a specific sequence of calls can be - * deterministically created by the test. - * - * The intended usage is as follows: - * - * TEST_F(...) { - * class PT : public ProducerThread { - * virtual void render() { - * ... - * swapBuffers(); - * } - * }; - * - * runProducerThread(new PT()); - * - * // The order of these calls will vary from test to test and may include - * // multiple frames and additional operations (e.g. GL rendering from the - * // texture). - * fc->waitForFrame(); - * mST->updateTexImage(); - * fc->finishFrame(); - * } - * - */ -class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest { -protected: - - // ProducerThread is an abstract base class to simplify the creation of - // OpenGL ES frame producer threads. - class ProducerThread : public Thread { - public: - virtual ~ProducerThread() { - } - - void setEglObjects(EGLDisplay producerEglDisplay, - EGLSurface producerEglSurface, - EGLContext producerEglContext) { - mProducerEglDisplay = producerEglDisplay; - mProducerEglSurface = producerEglSurface; - mProducerEglContext = producerEglContext; - } - - virtual bool threadLoop() { - eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext); - render(); - eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - return false; - } - - protected: - virtual void render() = 0; - - void swapBuffers() { - eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface); - } - - EGLDisplay mProducerEglDisplay; - EGLSurface mProducerEglSurface; - EGLContext mProducerEglContext; - }; - - // FrameCondition is a utility class for interlocking between the producer - // and consumer threads. The FrameCondition object should be created and - // destroyed in the consumer thread only. The consumer thread should set - // the FrameCondition as the FrameAvailableListener of the SurfaceTexture, - // and should call both waitForFrame and finishFrame once for each expected - // frame. - // - // This interlocking relies on the fact that onFrameAvailable gets called - // synchronously from SurfaceTexture::queueBuffer. - class FrameCondition : public SurfaceTexture::FrameAvailableListener { - public: - FrameCondition(): - mFrameAvailable(false), - mFrameFinished(false) { - } - - // waitForFrame waits for the next frame to arrive. This should be - // called from the consumer thread once for every frame expected by the - // test. - void waitForFrame() { - Mutex::Autolock lock(mMutex); - ALOGV("+waitForFrame"); - while (!mFrameAvailable) { - mFrameAvailableCondition.wait(mMutex); - } - mFrameAvailable = false; - ALOGV("-waitForFrame"); - } - - // Allow the producer to return from its swapBuffers call and continue - // on to produce the next frame. This should be called by the consumer - // thread once for every frame expected by the test. - void finishFrame() { - Mutex::Autolock lock(mMutex); - ALOGV("+finishFrame"); - mFrameFinished = true; - mFrameFinishCondition.signal(); - ALOGV("-finishFrame"); - } - - // This should be called by SurfaceTexture on the producer thread. - virtual void onFrameAvailable() { - Mutex::Autolock lock(mMutex); - ALOGV("+onFrameAvailable"); - mFrameAvailable = true; - mFrameAvailableCondition.signal(); - while (!mFrameFinished) { - mFrameFinishCondition.wait(mMutex); - } - mFrameFinished = false; - ALOGV("-onFrameAvailable"); - } - - protected: - bool mFrameAvailable; - bool mFrameFinished; - - Mutex mMutex; - Condition mFrameAvailableCondition; - Condition mFrameFinishCondition; - }; - - virtual void SetUp() { - SurfaceTextureGLToGLTest::SetUp(); - mFC = new FrameCondition(); - mST->setFrameAvailableListener(mFC); - } - - virtual void TearDown() { - if (mProducerThread != NULL) { - mProducerThread->requestExitAndWait(); - } - mProducerThread.clear(); - mFC.clear(); - SurfaceTextureGLToGLTest::TearDown(); - } - - void runProducerThread(const sp<ProducerThread> producerThread) { - ASSERT_TRUE(mProducerThread == NULL); - mProducerThread = producerThread; - producerThread->setEglObjects(mEglDisplay, mProducerEglSurface, - mProducerEglContext); - producerThread->run(); - } - - sp<ProducerThread> mProducerThread; - sp<FrameCondition> mFC; -}; - -TEST_F(SurfaceTextureGLThreadToGLTest, - UpdateTexImageBeforeFrameFinishedCompletes) { - class PT : public ProducerThread { - virtual void render() { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - swapBuffers(); - } - }; - - runProducerThread(new PT()); - - mFC->waitForFrame(); - mST->updateTexImage(); - mFC->finishFrame(); - - // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! -} - -TEST_F(SurfaceTextureGLThreadToGLTest, - UpdateTexImageAfterFrameFinishedCompletes) { - class PT : public ProducerThread { - virtual void render() { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - swapBuffers(); - } - }; - - runProducerThread(new PT()); - - mFC->waitForFrame(); - mFC->finishFrame(); - mST->updateTexImage(); - - // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! -} - -TEST_F(SurfaceTextureGLThreadToGLTest, - RepeatedUpdateTexImageBeforeFrameFinishedCompletes) { - enum { NUM_ITERATIONS = 1024 }; - - class PT : public ProducerThread { - virtual void render() { - for (int i = 0; i < NUM_ITERATIONS; i++) { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ALOGV("+swapBuffers"); - swapBuffers(); - ALOGV("-swapBuffers"); - } - } - }; - - runProducerThread(new PT()); - - for (int i = 0; i < NUM_ITERATIONS; i++) { - mFC->waitForFrame(); - ALOGV("+updateTexImage"); - mST->updateTexImage(); - ALOGV("-updateTexImage"); - mFC->finishFrame(); - - // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! - } -} - -TEST_F(SurfaceTextureGLThreadToGLTest, - RepeatedUpdateTexImageAfterFrameFinishedCompletes) { - enum { NUM_ITERATIONS = 1024 }; - - class PT : public ProducerThread { - virtual void render() { - for (int i = 0; i < NUM_ITERATIONS; i++) { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ALOGV("+swapBuffers"); - swapBuffers(); - ALOGV("-swapBuffers"); - } - } - }; - - runProducerThread(new PT()); - - for (int i = 0; i < NUM_ITERATIONS; i++) { - mFC->waitForFrame(); - mFC->finishFrame(); - ALOGV("+updateTexImage"); - mST->updateTexImage(); - ALOGV("-updateTexImage"); - - // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! - } -} - -// XXX: This test is disabled because it is currently hanging on some devices. -TEST_F(SurfaceTextureGLThreadToGLTest, - DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) { - enum { NUM_ITERATIONS = 64 }; - - class PT : public ProducerThread { - virtual void render() { - for (int i = 0; i < NUM_ITERATIONS; i++) { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - ALOGV("+swapBuffers"); - swapBuffers(); - ALOGV("-swapBuffers"); - } - } - }; - - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - ASSERT_EQ(OK, mST->setBufferCountServer(2)); - - runProducerThread(new PT()); - - // Allow three frames to be rendered and queued before starting the - // rendering in this thread. For the latter two frames we don't call - // updateTexImage so the next dequeue from the producer thread will block - // waiting for a frame to become available. - mFC->waitForFrame(); - mFC->finishFrame(); - - // We must call updateTexImage to consume the first frame so that the - // SurfaceTexture is able to reduce the buffer count to 2. This is because - // the GL driver may dequeue a buffer when the EGLSurface is created, and - // that happens before we call setBufferCountServer. It's possible that the - // driver does not dequeue a buffer at EGLSurface creation time, so we - // cannot rely on this to cause the second dequeueBuffer call to block. - mST->updateTexImage(); - - mFC->waitForFrame(); - mFC->finishFrame(); - mFC->waitForFrame(); - mFC->finishFrame(); - - // Sleep for 100ms to allow the producer thread's dequeueBuffer call to - // block waiting for a buffer to become available. - usleep(100000); - - // Render and present a number of images. This thread should not be blocked - // by the fact that the producer thread is blocking in dequeue. - for (int i = 0; i < NUM_ITERATIONS; i++) { - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(mEglDisplay, mEglSurface); - } - - // Consume the two pending buffers to unblock the producer thread. - mST->updateTexImage(); - mST->updateTexImage(); - - // Consume the remaining buffers from the producer thread. - for (int i = 0; i < NUM_ITERATIONS-3; i++) { - mFC->waitForFrame(); - mFC->finishFrame(); - ALOGV("+updateTexImage"); - mST->updateTexImage(); - ALOGV("-updateTexImage"); - } -} - -class SurfaceTextureFBOTest : public SurfaceTextureGLTest { -protected: - - virtual void SetUp() { - SurfaceTextureGLTest::SetUp(); - - glGenFramebuffers(1, &mFbo); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - - glGenTextures(1, &mFboTex); - glBindTexture(GL_TEXTURE_2D, mFboTex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(), - getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_2D, 0); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - - glBindFramebuffer(GL_FRAMEBUFFER, mFbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, mFboTex, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); - } - - virtual void TearDown() { - SurfaceTextureGLTest::TearDown(); - - glDeleteTextures(1, &mFboTex); - glDeleteFramebuffers(1, &mFbo); - } - - GLuint mFbo; - GLuint mFboTex; -}; - -// This test is intended to verify that proper synchronization is done when -// rendering into an FBO. -TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { - const int texWidth = 64; - const int texHeight = 64; - - ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), - texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); - ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), - 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_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; - buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); - 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, mST->updateTexImage()); - - glBindFramebuffer(GL_FRAMEBUFFER, mFbo); - drawTexture(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - 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_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, - (void**)(&img))); - fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0, - 0, 255); - ASSERT_EQ(NO_ERROR, buf->unlock()); - ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), - buf->getNativeBuffer())); - - ASSERT_EQ(NO_ERROR, mST->updateTexImage()); - - drawTexture(); - - EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255)); - } - - glBindFramebuffer(GL_FRAMEBUFFER, mFbo); - - EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255)); -} - -} // namespace android diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp deleted file mode 100644 index b585d68..0000000 --- a/libs/gui/tests/Surface_test.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#include <gtest/gtest.h> - -#include <binder/IMemory.h> -#include <gui/ISurfaceComposer.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> -#include <utils/String8.h> - -#include <private/gui/ComposerService.h> - -namespace android { - -class SurfaceTest : public ::testing::Test { -protected: - virtual void SetUp() { - mComposerClient = new SurfaceComposerClient; - ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); - - mSurfaceControl = mComposerClient->createSurface( - String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGBA_8888, 0); - - ASSERT_TRUE(mSurfaceControl != NULL); - ASSERT_TRUE(mSurfaceControl->isValid()); - - SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff)); - ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - SurfaceComposerClient::closeGlobalTransaction(); - - mSurface = mSurfaceControl->getSurface(); - ASSERT_TRUE(mSurface != NULL); - } - - virtual void TearDown() { - mComposerClient->dispose(); - } - - sp<Surface> mSurface; - sp<SurfaceComposerClient> mComposerClient; - sp<SurfaceControl> mSurfaceControl; -}; - -TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) { - sp<ANativeWindow> anw(mSurface); - int result = -123; - int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, - &result); - EXPECT_EQ(NO_ERROR, err); - EXPECT_EQ(1, result); -} - -TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenPurgatorized) { - mSurfaceControl.clear(); - - sp<ANativeWindow> anw(mSurface); - int result = -123; - int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, - &result); - EXPECT_EQ(NO_ERROR, err); - EXPECT_EQ(1, result); -} - -// This test probably doesn't belong here. -TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { - sp<ANativeWindow> anw(mSurface); - - // Verify the screenshot works with no protected buffers. - sp<IMemoryHeap> heap; - uint32_t w=0, h=0; - PixelFormat fmt=0; - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, - 0x7fffffff)); - ASSERT_TRUE(heap != NULL); - - // Set the PROTECTED usage bit and verify that the screenshot fails. Note - // that we need to dequeue a buffer in order for it to actually get - // allocated in SurfaceFlinger. - ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), - GRALLOC_USAGE_PROTECTED)); - ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); - ANativeWindowBuffer* buf = 0; - - status_t err = anw->dequeueBuffer(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)); - return; - } - ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf)); - - 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)); - } - heap = 0; - w = h = fmt = 0; - ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, - 64, 64, 0, 0x7fffffff)); - ASSERT_TRUE(heap != NULL); -} - -TEST_F(SurfaceTest, ConcreteTypeIsSurface) { - sp<ANativeWindow> anw(mSurface); - int result = -123; - int err = anw->query(anw.get(), NATIVE_WINDOW_CONCRETE_TYPE, &result); - EXPECT_EQ(NO_ERROR, err); - EXPECT_EQ(NATIVE_WINDOW_SURFACE, result); -} - -} |