diff options
42 files changed, 815 insertions, 78 deletions
diff --git a/build/phone-xhdpi-1024-dalvik-heap.mk b/build/phone-xhdpi-1024-dalvik-heap.mk index 221227d..20f365f 100644 --- a/build/phone-xhdpi-1024-dalvik-heap.mk +++ b/build/phone-xhdpi-1024-dalvik-heap.mk @@ -21,5 +21,5 @@ PRODUCT_PROPERTY_OVERRIDES += \ dalvik.vm.heapgrowthlimit=96m \ dalvik.vm.heapsize=256m \ dalvik.vm.heaptargetutilization=0.75 \ - dalvik.vm.heapminfree=512k \ + dalvik.vm.heapminfree=2m \ dalvik.vm.heapmaxfree=8m diff --git a/build/phone-xhdpi-2048-dalvik-heap.mk b/build/phone-xhdpi-2048-dalvik-heap.mk index 042a6e6..324e883 100644 --- a/build/phone-xhdpi-2048-dalvik-heap.mk +++ b/build/phone-xhdpi-2048-dalvik-heap.mk @@ -22,5 +22,5 @@ PRODUCT_PROPERTY_OVERRIDES += \ dalvik.vm.heapgrowthlimit=192m \ dalvik.vm.heapsize=512m \ dalvik.vm.heaptargetutilization=0.75 \ - dalvik.vm.heapminfree=512k \ + dalvik.vm.heapminfree=2m \ dalvik.vm.heapmaxfree=8m diff --git a/build/tablet-10in-xhdpi-2048-dalvik-heap.mk b/build/tablet-10in-xhdpi-2048-dalvik-heap.mk index 1721fcc..f154450 100644 --- a/build/tablet-10in-xhdpi-2048-dalvik-heap.mk +++ b/build/tablet-10in-xhdpi-2048-dalvik-heap.mk @@ -21,5 +21,5 @@ PRODUCT_PROPERTY_OVERRIDES += \ dalvik.vm.heapgrowthlimit=192m \ dalvik.vm.heapsize=512m \ dalvik.vm.heaptargetutilization=0.75 \ - dalvik.vm.heapminfree=512k \ + dalvik.vm.heapminfree=2m \ dalvik.vm.heapmaxfree=8m diff --git a/build/tablet-7in-hdpi-1024-dalvik-heap.mk b/build/tablet-7in-hdpi-1024-dalvik-heap.mk index 5bbd2b0..5c8ce3e 100644 --- a/build/tablet-7in-hdpi-1024-dalvik-heap.mk +++ b/build/tablet-7in-hdpi-1024-dalvik-heap.mk @@ -21,5 +21,5 @@ PRODUCT_PROPERTY_OVERRIDES += \ dalvik.vm.heapgrowthlimit=64m \ dalvik.vm.heapsize=384m \ dalvik.vm.heaptargetutilization=0.75 \ - dalvik.vm.heapminfree=512k \ + dalvik.vm.heapminfree=2m \ dalvik.vm.heapmaxfree=8m diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index f3fcca0..8718bb6 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -188,6 +188,12 @@ static void dumpstate() { run_command("WIFI NETWORKS", 20, SU_PATH, "root", "wpa_cli", "list_networks", NULL); +#ifdef FWDUMP_bcmdhd + run_command("DUMP WIFI INTERNAL COUNTERS", 20, + SU_PATH, "root", "wlutil", "counters", NULL); +#endif + dump_file("INTERRUPTS (1)", "/proc/interrupts"); + property_get("dhcp.wlan0.gateway", network, ""); if (network[0]) run_command("PING GATEWAY", 10, SU_PATH, "root", "ping", "-c", "3", "-i", ".5", network, NULL); @@ -197,12 +203,13 @@ static void dumpstate() { property_get("dhcp.wlan0.dns2", network, ""); if (network[0]) run_command("PING DNS2", 10, SU_PATH, "root", "ping", "-c", "3", "-i", ".5", network, NULL); -#ifdef FWDUMP_bcm4329 +#ifdef FWDUMP_bcmdhd run_command("DUMP WIFI STATUS", 20, SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL); run_command("DUMP WIFI INTERNAL COUNTERS", 20, SU_PATH, "root", "wlutil", "counters", NULL); #endif + dump_file("INTERRUPTS (2)", "/proc/interrupts"); print_properties(); diff --git a/data/etc/com.stericsson.hardware.fm.receiver.xml b/data/etc/com.stericsson.hardware.fm.receiver.xml new file mode 100644 index 0000000..13092fa --- /dev/null +++ b/data/etc/com.stericsson.hardware.fm.receiver.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- This is the standard feature indicating that the device includes FM receiver. --> +<permissions> + <feature name="com.stericsson.hardware.fm.receiver" /> +</permissions> diff --git a/data/etc/com.stericsson.hardware.fm.transmitter.xml b/data/etc/com.stericsson.hardware.fm.transmitter.xml new file mode 100644 index 0000000..9b51c03 --- /dev/null +++ b/data/etc/com.stericsson.hardware.fm.transmitter.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- This is the standard feature indicating that the device includes FM transmitter. --> +<permissions> + <feature name="com.stericsson.hardware.fm.transmitter" /> +</permissions> diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 9e265ba..cd38cfe 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -33,6 +33,23 @@ namespace android { // ---------------------------------------------------------------------------- +#ifdef QCOM_BSP +/* + * Structure to hold the buffer geometry + */ +struct QBufGeometry { + int mWidth; + int mHeight; + int mFormat; + QBufGeometry(): mWidth(0), mHeight(0), mFormat(0) {} + void set(int w, int h, int f) { + mWidth = w; + mHeight = h; + mFormat = f; + } +}; +#endif + class BufferQueue : public BnSurfaceTexture { public: enum { MIN_UNDEQUEUED_BUFFERS = 2 }; @@ -148,6 +165,21 @@ public: // The default mode is asynchronous. virtual status_t setSynchronousMode(bool enabled); +#ifdef QCOM_BSP + // setBufferSize enables us to specify user defined sizes for the buffers + // that need to be allocated by surfaceflinger for its client. This is + // useful for cases where the client doesn't want the gralloc to calculate + // buffer size. client should reset this value to 0, if it wants gralloc + // to calculate the size for the buffer. this will take effect from next + // dequeue buffer. + virtual status_t setBuffersSize(int size); + + // update buffer width, height and format for a native buffer + // dynamically from the client which will take effect in the next + // queue buffer. + virtual status_t updateBuffersGeometry(int w, int h, int f); +#endif + // connect attempts to connect a producer client API to the BufferQueue. // This must be called before any other ISurfaceTexture methods are called // except for getAllocator. @@ -537,6 +569,11 @@ private: // mTransformHint is used to optimize for screen rotations uint32_t mTransformHint; + +#ifdef QCOM_BSP + // holds the updated buffer geometry info of the new video resolution. + QBufGeometry mNextBufferInfo; +#endif }; // ---------------------------------------------------------------------------- diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h index cee41d9..adc0b7f 100644 --- a/include/gui/IGraphicBufferAlloc.h +++ b/include/gui/IGraphicBufferAlloc.h @@ -38,6 +38,9 @@ public: */ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, status_t* error) = 0; +#ifdef QCOM_BSP + virtual void setGraphicBufferSize(int size) = 0; +#endif }; // ---------------------------------------------------------------------------- diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h index ae7c5c2..f2a6510 100644 --- a/include/gui/ISurfaceTexture.h +++ b/include/gui/ISurfaceTexture.h @@ -164,6 +164,20 @@ public: // The default mode is asynchronous. virtual status_t setSynchronousMode(bool enabled) = 0; +#ifdef QCOM_BSP + // setBufferSize enables to specify the user defined size of the buffer + // that needs to be allocated by surfaceflinger for its client. This is + // useful for cases where the client doesn't want the gralloc to calculate + // buffer size. client should reset this value to 0, if it wants gralloc to + // calculate the size for the buffer. this will take effect from next + // dequeue buffer. + virtual status_t setBuffersSize(int size) = 0; + + // update buffer width, height and format information from the client + // which will take effect in the next queue buffer. + virtual status_t updateBuffersGeometry(int w, int h, int f) = 0; +#endif + // connect attempts to connect a client API to the SurfaceTexture. This // must be called before any other ISurfaceTexture methods are called except // for getAllocator. diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 1bbad60..7eb6b64 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -77,6 +77,12 @@ public: // this legacy function (when they shouldn't). static status_t getDisplayInfo(int32_t displayId, DisplayInfo* info); +#if defined(ICS_CAMERA_BLOB) || defined(MR0_CAMERA_BLOB) + static ssize_t getDisplayWidth(int32_t displayId); + static ssize_t getDisplayHeight(int32_t displayId); + static ssize_t getDisplayOrientation(int32_t displayId); +#endif + // ------------------------------------------------------------------------ // surface creation / destruction diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index 50fd1ba..f2b523d 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -93,6 +93,10 @@ private: int dispatchSetCrop(va_list args); int dispatchSetPostTransformCrop(va_list args); int dispatchSetUsage(va_list args); +#ifdef QCOM_BSP + int dispatchUpdateBuffersGeometry(va_list args); + int dispatchSetBuffersSize(va_list args); +#endif int dispatchLock(va_list args); int dispatchUnlockAndPost(va_list args); @@ -103,7 +107,10 @@ protected: virtual int perform(int operation, va_list args); virtual int query(int what, int* value) const; virtual int setSwapInterval(int interval); - +#ifdef QCOM_BSP + virtual int updateBuffersGeometry(int w, int h, int f); + virtual int setBuffersSize(int size); +#endif virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer); virtual int connect(int api); @@ -161,6 +168,12 @@ private: // at the next deuque operation. It is initialized to 0. uint32_t mReqUsage; +#ifdef QCOM_BSP + // mReqSize is the size of the buffer that will be requested + // at the next dequeue operation. It is initialized to 0. + uint32_t mReqSize; +#endif + // mTimestamp is the timestamp that will be used for the next buffer queue // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that // a timestamp is auto-generated when queueBuffer is called. diff --git a/include/media/openmax/OMX_IVCommon.h b/include/media/openmax/OMX_IVCommon.h index effbaae..24f91ce 100644 --- a/include/media/openmax/OMX_IVCommon.h +++ b/include/media/openmax/OMX_IVCommon.h @@ -160,6 +160,7 @@ typedef enum OMX_COLOR_FORMATTYPE { OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100, OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00, OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03, + OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04, OMX_COLOR_FormatMax = 0x7FFFFFFF } OMX_COLOR_FORMATTYPE; diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index 1c84d0e..af85063 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -72,6 +72,12 @@ public: GraphicBuffer(); +#ifdef QCOM_BSP + // creates buffer of bufferSize + GraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage, uint32_t bufferSize); +#endif + // creates w * h buffer GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); @@ -97,6 +103,10 @@ public: status_t lock(uint32_t usage, void** vaddr); status_t lock(uint32_t usage, const Rect& rect, void** vaddr); status_t unlock(); +#ifdef QCOM_BSP + status_t perform(buffer_handle_t hnd, int operation, + uint32_t w, uint32_t h, PixelFormat format); +#endif ANativeWindowBuffer* getNativeBuffer() const; @@ -133,9 +143,12 @@ private: GraphicBuffer& operator = (const GraphicBuffer& rhs); const GraphicBuffer& operator = (const GraphicBuffer& rhs) const; - status_t initSize(uint32_t w, uint32_t h, PixelFormat format, + status_t initSize(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); - +#ifdef QCOM_BSP + status_t initSize(uint32_t w, uint32_t h, PixelFormat format, + uint32_t usage, uint32_t bufferSize); +#endif void free_handle(); // Flattenable interface diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h index 0f2a492..a4d5b8c 100644 --- a/include/ui/GraphicBufferAllocator.h +++ b/include/ui/GraphicBufferAllocator.h @@ -68,6 +68,11 @@ public: status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride); +#ifdef QCOM_BSP + status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, + buffer_handle_t* handle, int32_t* stride, uint32_t bufferSize); +#endif + status_t free(buffer_handle_t handle); void dump(String8& res) const; @@ -87,6 +92,7 @@ private: static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList; friend class Singleton<GraphicBufferAllocator>; + friend class BufferLiberatorThread; GraphicBufferAllocator(); ~GraphicBufferAllocator(); diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h index 1fdecab..858fb1b 100644 --- a/include/ui/GraphicBufferMapper.h +++ b/include/ui/GraphicBufferMapper.h @@ -51,6 +51,11 @@ public: status_t getphys(buffer_handle_t handle, void** paddr); #endif +#ifdef QCOM_BSP + status_t perform(buffer_handle_t handle, int operation, + uint32_t w, uint32_t h, uint32_t format); +#endif + // dumps information about the mapping of this handle void dump(buffer_handle_t handle); diff --git a/include/utils/Trace.h b/include/utils/Trace.h index 93e2285..41bce00 100644 --- a/include/utils/Trace.h +++ b/include/utils/Trace.h @@ -54,6 +54,8 @@ #define ATRACE_TAG_CAMERA (1<<10) #define ATRACE_TAG_LAST ATRACE_TAG_CAMERA +#define ATRACE_TAG_NOT_READY (1LL<<63) // Reserved for use during init + #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST) #ifndef ATRACE_TAG diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index d970a33..084ea0d 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -54,9 +54,11 @@ ifneq ($(filter generic%,$(TARGET_DEVICE)),) LOCAL_CFLAGS += -DUSE_FENCE_SYNC endif -ifeq ($(TARGET_BOARD_PLATFORM), msm8960) +ifeq ($(call is-vendor-board-platform,QCOM),true) +ifneq ($(TARGET_QCOM_DISPLAY_VARIANT),legacy) LOCAL_CFLAGS += -DUSE_NATIVE_FENCE_SYNC endif +endif include $(BUILD_SHARED_LIBRARY) diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 590946a..acf6cec 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -64,6 +64,70 @@ static const char* scalingModeName(int scalingMode) { } } +#ifdef QCOM_BSP +/* + * Checks if memory needs to be reallocated for this buffer. + * + * @param: Geometry of the current buffer. + * @param: Required Geometry. + * @param: Geometry of the updated buffer. + * + * @return True if a memory reallocation is required. + */ +static bool needNewBuffer(const QBufGeometry currentGeometry, + const QBufGeometry requiredGeometry, + const QBufGeometry updatedGeometry) +{ + // no allocation required if there is change in resoultion or format. + if (updatedGeometry.mWidth && updatedGeometry.mHeight && + updatedGeometry.mFormat) { + return false; + } + // If the current buffer info matches the updated info, + // we do not require any memory allocation. + if (currentGeometry.mWidth != requiredGeometry.mWidth || + currentGeometry.mHeight != requiredGeometry.mHeight || + currentGeometry.mFormat != requiredGeometry.mFormat) { + // Current and required geometry do not match. Allocation + // required. + return true; + } + return false; +} + +/* + * Geometry update for the currently queued buffer is required or not. + * + * @param: buffer currently queued buffer. + * @param: Updated width + * @param: Updated height + * @param: Updated format + * + * @return True if a buffer needs to be updated with new attributes. + */ +static bool isBufferGeometryUpdateRequired(sp<GraphicBuffer> buffer, + const QBufGeometry updatedGeometry) +{ + if (buffer == 0) { + ALOGW("isBufferGeometryUpdateRequired: graphic buffer is NULL"); + return false; + } + + if (!updatedGeometry.mWidth || !updatedGeometry.mHeight || + !updatedGeometry.mFormat) { + // No update required. Return. + return false; + } + if (buffer->width == updatedGeometry.mWidth && + buffer->height == updatedGeometry.mHeight && + buffer->format == updatedGeometry.mFormat) { + // The buffer has already been updated. Return. + return false; + } + return true; +} +#endif + BufferQueue::BufferQueue(bool allowSynchronousMode, const sp<IGraphicBufferAlloc>& allocator) : mDefaultWidth(1), @@ -94,6 +158,9 @@ BufferQueue::BufferQueue(bool allowSynchronousMode, } else { mGraphicBufferAlloc = allocator; } +#ifdef QCOM_BSP + mNextBufferInfo.set(0, 0, 0); +#endif } BufferQueue::~BufferQueue() { @@ -195,6 +262,15 @@ status_t BufferQueue::setBufferCount(int bufferCount) { return OK; } +#ifdef QCOM_BSP +status_t BufferQueue::setBuffersSize(int size) { + ST_LOGV("setBuffersSize: size=%d", size); + Mutex::Autolock lock(mMutex); + mGraphicBufferAlloc->setGraphicBufferSize(size); + return NO_ERROR; +} +#endif + int BufferQueue::query(int what, int* outValue) { ATRACE_CALL(); @@ -314,9 +390,8 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, * the consumer may still have pending reads of the * buffers in flight. */ - bool isOlder = mSlots[i].mFrameNumber < - mSlots[found].mFrameNumber; - if (found < 0 || isOlder) { + if ((found < 0) || + mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { found = i; } } @@ -379,10 +454,29 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, mSlots[buf].mBufferState = BufferSlot::DEQUEUED; const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); +#ifdef QCOM_BSP + QBufGeometry currentGeometry; + if (buffer != NULL) + currentGeometry.set(buffer->width, buffer->height, buffer->format); + else + currentGeometry.set(0, 0, 0); + + QBufGeometry requiredGeometry; + requiredGeometry.set(w, h, format); + + QBufGeometry updatedGeometry; + updatedGeometry.set(mNextBufferInfo.mWidth, mNextBufferInfo.mHeight, + mNextBufferInfo.mFormat); +#endif + if ((buffer == NULL) || +#ifdef QCOM_BSP + needNewBuffer(currentGeometry, requiredGeometry, updatedGeometry) || +#else (uint32_t(buffer->width) != w) || (uint32_t(buffer->height) != h) || (uint32_t(buffer->format) != format) || +#endif ((uint32_t(buffer->usage) & usage) != usage)) { mSlots[buf].mAcquireCalled = false; @@ -445,6 +539,15 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, return returnFlags; } +#ifdef QCOM_BSP +status_t BufferQueue::updateBuffersGeometry(int w, int h, int f) { + ST_LOGV("updateBuffersGeometry: w=%d h=%d f=%d", w, h, f); + Mutex::Autolock lock(mMutex); + mNextBufferInfo.set(w, h, f); + return NO_ERROR; +} +#endif + status_t BufferQueue::setSynchronousMode(bool enabled) { ATRACE_CALL(); ST_LOGV("setSynchronousMode: enabled=%d", enabled); @@ -518,7 +621,31 @@ status_t BufferQueue::queueBuffer(int buf, return -EINVAL; } +#ifdef QCOM_BSP + // Update the buffer Geometry if required + QBufGeometry updatedGeometry; + updatedGeometry.set(mNextBufferInfo.mWidth, + mNextBufferInfo.mHeight, mNextBufferInfo.mFormat); +#endif const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); +#ifdef QCOM_BSP + // Update the geometry of this buffer without reallocation. + if(isBufferGeometryUpdateRequired(graphicBuffer, updatedGeometry)) { + status_t res = graphicBuffer->perform(graphicBuffer->handle, + GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY, + updatedGeometry.mWidth, + updatedGeometry.mHeight, + updatedGeometry.mFormat); + if(res == NO_ERROR) { + graphicBuffer->width = updatedGeometry.mWidth; + graphicBuffer->height = updatedGeometry.mHeight; + graphicBuffer->format = updatedGeometry.mFormat; + // set flags to destroy old eglImage and create new eglImage. + mSlots[buf].mAcquireCalled = false; + mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; + } + } +#endif Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); Rect croppedCrop; crop.intersect(bufferRect, &croppedCrop); @@ -548,6 +675,8 @@ status_t BufferQueue::queueBuffer(int buf, Fifo::iterator front(mQueue.begin()); // buffer currently queued is freed mSlots[*front].mBufferState = BufferSlot::FREE; + // reset the frame number of the freed buffer + mSlots[*front].mFrameNumber = 0; // and we record the new buffer index in the queued list *front = buf; } @@ -681,6 +810,9 @@ status_t BufferQueue::disconnect(int api) { if (mConnectedApi == api) { drainQueueAndFreeBuffersLocked(); mConnectedApi = NO_CONNECTED_API; +#ifdef QCOM_BSP + mNextBufferInfo.set(0, 0, 0); +#endif mDequeueCondition.broadcast(); listener = mConsumerListener; } else { diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index 139f219..8afb509 100644 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp @@ -32,6 +32,9 @@ namespace android { enum { CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION, +#ifdef QCOM_BSP + SET_GRAPHIC_BUFFER_SIZE, +#endif }; class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc> @@ -63,6 +66,16 @@ public: *error = result; return graphicBuffer; } + +#ifdef QCOM_BSP + virtual void setGraphicBufferSize(int size) { + Parcel data, reply; + data.writeInterfaceToken( + IGraphicBufferAlloc::getInterfaceDescriptor()); + data.writeInt32(size); + remote()->transact(SET_GRAPHIC_BUFFER_SIZE, data, &reply); + } +#endif }; IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc"); @@ -108,6 +121,14 @@ status_t BnGraphicBufferAlloc::onTransact( } return NO_ERROR; } break; +#ifdef QCOM_BSP + case SET_GRAPHIC_BUFFER_SIZE: { + CHECK_INTERFACE(IGraphicBufferAlloc, data, reply); + int size = data.readInt32(); + setGraphicBufferSize(size); + return NO_ERROR; + } break; +#endif default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index a0b1e74..ce31a5b 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -38,6 +38,10 @@ enum { CANCEL_BUFFER, QUERY, SET_SYNCHRONOUS_MODE, +#ifdef QCOM_BSP + UPDATE_BUFFERS_GEOMETRY, + SET_BUFFERS_SIZE, +#endif CONNECT, DISCONNECT, }; @@ -156,6 +160,35 @@ public: return result; } +#ifdef QCOM_BSP + virtual status_t updateBuffersGeometry(int w, int h, int f) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(f); + status_t result = remote()->transact(UPDATE_BUFFERS_GEOMETRY, + data, &reply); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt32(); + return result; + } + + virtual status_t setBuffersSize(int size) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); + data.writeInt32(size); + status_t result = remote()->transact(SET_BUFFERS_SIZE, data, &reply); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt32(); + return result; + } +#endif + virtual status_t connect(int api, QueueBufferOutput* output) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); @@ -266,6 +299,24 @@ status_t BnSurfaceTexture::onTransact( reply->writeInt32(res); return NO_ERROR; } break; +#ifdef QCOM_BSP + case UPDATE_BUFFERS_GEOMETRY: { + CHECK_INTERFACE(ISurfaceTexture, data, reply); + int w = data.readInt32(); + int h = data.readInt32(); + int f = data.readInt32(); + status_t res = updateBuffersGeometry(w, h, f); + reply->writeInt32(res); + return NO_ERROR; + } break; + case SET_BUFFERS_SIZE: { + CHECK_INTERFACE(ISurfaceTexture, data, reply); + int size = data.readInt32(); + status_t res = setBuffersSize(size); + reply->writeInt32(res); + return NO_ERROR; + } break; +#endif case CONNECT: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int api = data.readInt32(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0301f72..e6b4b21 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -630,6 +630,26 @@ status_t SurfaceComposerClient::getDisplayInfo( return getDisplayInfo(getBuiltInDisplay(displayId), info); } +#if defined(ICS_CAMERA_BLOB) || defined(MR0_CAMERA_BLOB) +ssize_t SurfaceComposerClient::getDisplayWidth(int32_t displayId) { + DisplayInfo info; + getDisplayInfo(getBuiltInDisplay(displayId), &info); + return info.w; +} + +ssize_t SurfaceComposerClient::getDisplayHeight(int32_t displayId) { + DisplayInfo info; + getDisplayInfo(getBuiltInDisplay(displayId), &info); + return info.h; +} + +ssize_t SurfaceComposerClient::getDisplayOrientation(int32_t displayId) { + DisplayInfo info; + getDisplayInfo(getBuiltInDisplay(displayId), &info); + return info.orientation; +} +#endif + // ---------------------------------------------------------------------------- ScreenshotClient::ScreenshotClient() diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index afdbf04..5de963c 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -80,6 +80,9 @@ void SurfaceTextureClient::init() { mReqHeight = 0; mReqFormat = 0; mReqUsage = 0; +#ifdef QCOM_BSP + mReqSize = 0; +#endif mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; mCrop.clear(); mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; @@ -400,6 +403,14 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_FORMAT: res = dispatchSetBuffersFormat(args); break; +#ifdef QCOM_BSP + case NATIVE_WINDOW_SET_BUFFERS_SIZE: + res = dispatchSetBuffersSize(args); + break; + case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY: + res = dispatchUpdateBuffersGeometry(args); + break; +#endif case NATIVE_WINDOW_LOCK: res = dispatchLock(args); break; @@ -451,6 +462,7 @@ 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; @@ -461,6 +473,7 @@ int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) { int w = va_arg(args, int); int h = va_arg(args, int); + return setBuffersDimensions(w, h); } @@ -475,6 +488,20 @@ int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) { return setBuffersFormat(f); } +#ifdef QCOM_BSP +int SurfaceTextureClient::dispatchSetBuffersSize(va_list args) { + int size = va_arg(args, int); + return setBuffersSize(size); +} + +int SurfaceTextureClient::dispatchUpdateBuffersGeometry(va_list args) { + int w = va_arg(args, int); + int h = va_arg(args, int); + int f = va_arg(args, int); + return updateBuffersGeometry(w, h, f); +} +#endif + int SurfaceTextureClient::dispatchSetScalingMode(va_list args) { int m = va_arg(args, int); return setScalingMode(m); @@ -530,6 +557,9 @@ int SurfaceTextureClient::disconnect(int api) { mReqWidth = 0; mReqHeight = 0; mReqUsage = 0; +#ifdef QCOM_BSP + mReqSize = 0; +#endif mCrop.clear(); mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mTransform = 0; @@ -630,6 +660,40 @@ int SurfaceTextureClient::setBuffersFormat(int format) return NO_ERROR; } +#ifdef QCOM_BSP +int SurfaceTextureClient::setBuffersSize(int size) +{ + ATRACE_CALL(); + ALOGV("SurfaceTextureClient::setBuffersSize"); + + if (size<0) + return BAD_VALUE; + + Mutex::Autolock lock(mMutex); + if(mReqSize != (uint32_t)size) { + mReqSize = size; + return mSurfaceTexture->setBuffersSize(size); + } + return NO_ERROR; +} + +int SurfaceTextureClient::updateBuffersGeometry(int w, int h, int f) +{ + ATRACE_CALL(); + ALOGV("SurfaceTextureClient::updateBuffersGeometry"); + + if (w<0 || h<0 || f<0) + return BAD_VALUE; + + if ((w && !h) || (!w && h)) + return BAD_VALUE; + + Mutex::Autolock lock(mMutex); + status_t err = mSurfaceTexture->updateBuffersGeometry(w, h, f); + return err; +} +#endif + int SurfaceTextureClient::setScalingMode(int mode) { ATRACE_CALL(); diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index b9cab85..219375e 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -60,6 +60,22 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, mInitCheck = initSize(w, h, reqFormat, reqUsage); } +#ifdef QCOM_BSP +GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, + PixelFormat reqFormat, uint32_t reqUsage, uint32_t bufferSize) + : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mIndex(-1) +{ + width = + height = + stride = + format = + usage = 0; + handle = NULL; + mInitCheck = initSize(w, h, reqFormat, reqUsage, bufferSize); +} +#endif + GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, PixelFormat inFormat, uint32_t inUsage, uint32_t inStride, native_handle_t* inHandle, bool keepOwnership) @@ -154,6 +170,23 @@ status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, return err; } +#ifdef QCOM_BSP +status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, + uint32_t reqUsage, uint32_t bufferSize) +{ + GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); + status_t err = allocator.alloc(w, h, format, + reqUsage, &handle, &stride, bufferSize); + if (err == NO_ERROR) { + this->width = w; + this->height = h; + this->format = format; + this->usage = reqUsage; + } + return err; +} +#endif + status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) { const Rect lockBounds(width, height); @@ -180,6 +213,16 @@ status_t GraphicBuffer::unlock() return res; } +#ifdef QCOM_BSP +status_t GraphicBuffer::perform(buffer_handle_t hnd, int operation, + uint32_t w, uint32_t h, PixelFormat format) +{ + status_t res = getBufferMapper().perform(hnd, + GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY, w, h, format); + return res; +} +#endif + size_t GraphicBuffer::getFlattenedSize() const { return (8 + (handle ? handle->numInts : 0))*sizeof(int); } diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index c1b246f..470f58a 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -90,9 +90,119 @@ void GraphicBufferAllocator::dumpToSystemLog() ALOGD("%s", s.string()); } +class BufferLiberatorThread : public Thread { +public: + + static void queueCaptiveBuffer(buffer_handle_t handle) { + size_t queueSize; + { + Mutex::Autolock lock(sMutex); + if (sThread == NULL) { + sThread = new BufferLiberatorThread; + sThread->run("BufferLiberator"); + } + + sThread->mQueue.push_back(handle); + sThread->mQueuedCondition.signal(); + queueSize = sThread->mQueue.size(); + } + } + + static void waitForLiberation() { + Mutex::Autolock lock(sMutex); + + waitForLiberationLocked(); + } + + static void maybeWaitForLiberation() { + Mutex::Autolock lock(sMutex); + if (sThread != NULL) { + if (sThread->mQueue.size() > 8) { + waitForLiberationLocked(); + } + } + } + +private: + + BufferLiberatorThread() {} + + virtual bool threadLoop() { + buffer_handle_t handle; + { // Scope for mutex + Mutex::Autolock lock(sMutex); + while (mQueue.isEmpty()) { + mQueuedCondition.wait(sMutex); + } + handle = mQueue[0]; + } + + status_t err; + GraphicBufferAllocator& gba(GraphicBufferAllocator::get()); + { // Scope for tracing + ATRACE_NAME("gralloc::free"); + err = gba.mAllocDev->free(gba.mAllocDev, handle); + } + ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(GraphicBufferAllocator::sLock); + KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t>& + list(GraphicBufferAllocator::sAllocList); + list.removeItem(handle); + } + + { // Scope for mutex + Mutex::Autolock lock(sMutex); + mQueue.removeAt(0); + mFreedCondition.broadcast(); + } + + return true; + } + + static void waitForLiberationLocked() { + if (sThread == NULL) { + return; + } + + const nsecs_t timeout = 500 * 1000 * 1000; + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t timeToStop = now + timeout; + while (!sThread->mQueue.isEmpty() && now < timeToStop) { + sThread->mFreedCondition.waitRelative(sMutex, timeToStop - now); + now = systemTime(SYSTEM_TIME_MONOTONIC); + } + + if (!sThread->mQueue.isEmpty()) { + ALOGW("waitForLiberationLocked timed out"); + } + } + + static Mutex sMutex; + static sp<BufferLiberatorThread> sThread; + Vector<buffer_handle_t> mQueue; + Condition mQueuedCondition; + Condition mFreedCondition; +}; + +Mutex BufferLiberatorThread::sMutex; +sp<BufferLiberatorThread> BufferLiberatorThread::sThread; + status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { +#ifdef QCOM_BSP + status_t err = alloc(w, h, format, usage, handle, stride, 0); + return err; +} + +status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, + PixelFormat format, int usage, + buffer_handle_t* handle, + int32_t* stride, uint32_t bufferSize) +{ +#endif ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. @@ -100,7 +210,6 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma w = h = 1; // we have a h/w allocator and h/w buffer is requested - status_t err; #ifdef EXYNOS4_ENHANCEMENTS if ((format == 0x101) || (format == 0x105) || (format == 0x107)) { @@ -111,11 +220,39 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma } #endif + status_t err; + + // If too many async frees are queued up then wait for some of them to + // complete before attempting to allocate more memory. This is exercised + // by the android.opengl.cts.GLSurfaceViewTest CTS test. + BufferLiberatorThread::maybeWaitForLiberation(); + +#ifdef QCOM_BSP + err = mAllocDev->allocSize(mAllocDev, w, h, + format, usage, handle, stride, bufferSize); +#else err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); +#endif + + if (err != NO_ERROR) { + ALOGW("WOW! gralloc alloc failed, waiting for pending frees!"); + BufferLiberatorThread::waitForLiberation(); +#ifdef QCOM_BSP + err = mAllocDev->allocSize(mAllocDev, w, h, + format, usage, handle, stride, bufferSize); +#else + err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); +#endif + } +#ifdef QCOM_BSP + ALOGW_IF(err, "alloc(%u, %u, %d, %08x, %d ...) failed %d (%s)", + w, h, format, usage, bufferSize, err, strerror(-err)); +#else ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); - +#endif + if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); @@ -138,21 +275,11 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma return err; } + status_t GraphicBufferAllocator::free(buffer_handle_t handle) { - ATRACE_CALL(); - status_t err; - - err = mAllocDev->free(mAllocDev, handle); - - ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); - if (err == NO_ERROR) { - Mutex::Autolock _l(sLock); - KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); - list.removeItem(handle); - } - - return err; + BufferLiberatorThread::queueCaptiveBuffer(handle); + return NO_ERROR; } // --------------------------------------------------------------------------- diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 19c549d..d16a1bb 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -108,5 +108,18 @@ status_t GraphicBufferMapper::getphys(buffer_handle_t handle, void** paddr) } #endif +#ifdef QCOM_BSP +status_t GraphicBufferMapper::perform(buffer_handle_t handle, int operation, + uint32_t w, uint32_t h, uint32_t format) +{ + ATRACE_CALL(); + status_t err; + + err = mAllocMod->perform(mAllocMod, operation, w, h, format, handle); + + ALOGW_IF(err, "perform(...) failed %d (%s)", err, strerror(-err)); + return err; +} +#endif // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/utils/Trace.cpp b/libs/utils/Trace.cpp index 5cd5731..f5aaea3 100644 --- a/libs/utils/Trace.cpp +++ b/libs/utils/Trace.cpp @@ -25,7 +25,7 @@ namespace android { volatile int32_t Tracer::sIsReady = 0; int Tracer::sTraceFD = -1; -uint64_t Tracer::sEnabledTags = 0; +uint64_t Tracer::sEnabledTags = ATRACE_TAG_NOT_READY; Mutex Tracer::sMutex; void Tracer::changeCallback() { @@ -46,7 +46,7 @@ void Tracer::init() { sTraceFD = open(traceFileName, O_WRONLY); if (sTraceFD == -1) { ALOGE("error opening trace file: %s (%d)", strerror(errno), errno); - // sEnabledTags remains zero indicating that no tracing can occur + sEnabledTags = 0; // no tracing can occur } else { loadSystemProperty(); } diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 96e1cba..0d4bed5 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -124,6 +124,12 @@ void initEglTraceLevel() { void initEglDebugLevel() { int propertyLevel = 0; char value[PROPERTY_VALUE_MAX]; + + // check system property only on userdebug or eng builds + property_get("ro.debuggable", value, "0"); + if (value[0] == '0') + return; + property_get("debug.egl.debug_proc", value, ""); if (strlen(value) > 0) { long pid = getpid(); diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 23e89da..ed1b472 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -760,8 +760,8 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso && cnx->egl.eglGetProcAddress) { - found = true; // Extensions are independent of the bound context + addr = cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = #if EGL_TRACE @@ -769,10 +769,13 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) gHooksTrace.ext.extensions[slot] = #endif cnx->egl.eglGetProcAddress(procname); + if (addr) found = true; } if (found) { +#if USE_FAST_TLS_KEY addr = gExtensionForwarders[slot]; +#endif sGLExtentionMap.add(name, addr); sGLExtentionSlot++; } diff --git a/opengl/specs/EGL_ANDROID_native_fence_sync.txt b/opengl/specs/EGL_ANDROID_native_fence_sync.txt index 8273be4..ee05b40 100644 --- a/opengl/specs/EGL_ANDROID_native_fence_sync.txt +++ b/opengl/specs/EGL_ANDROID_native_fence_sync.txt @@ -100,10 +100,10 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) EGL_SYNC_TYPE_KHR EGL_SYNC_NATIVE_FENCE_ANDROID EGL_SYNC_STATUS_KHR EGL_UNSIGNALED_KHR EGL_SYNC_CONDITION_KHR EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR - EGL_SYNC_NATIVE_FENCE_FD_ANDROID EGL_NO_NATIVE_FENCE_ANDROID + EGL_SYNC_NATIVE_FENCE_FD_ANDROID EGL_NO_NATIVE_FENCE_FD_ANDROID If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not - EGL_NO_NATIVE_FENCE_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is + EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is set to EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR attribute is set to reflect the signal status of the native fence object. Additionally, the EGL implementation assumes ownership of the file @@ -114,7 +114,7 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) "When a fence sync object is created or when an EGL native fence sync object is created with the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute set - to EGL_NO_NATIVE_FENCE_ANDROID, eglCreateSyncKHR also inserts a fence + to EGL_NO_NATIVE_FENCE_FD_ANDROID, eglCreateSyncKHR also inserts a fence command into the command stream of the bound client API's current context (i.e., the context returned by eglGetCurrentContext), and associates it with the newly created sync object. @@ -157,8 +157,9 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) empty (containing only EGL_NONE), EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is generated. * If <type> is EGL_SYNC_NATIVE_FENCE_ANDROID and <attrib_list> contains - an attribute other than EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is - returned and an EGL_BAD_ATTRIBUTE error is generated. + an attribute other than EGL_SYNC_NATIVE_FENCE_FD_ANDROID, + EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is + generated. * If <type> is not a supported type of sync object, EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is generated. @@ -193,8 +194,8 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) "If no errors are generated, EGL_TRUE is returned, and <sync> will no longer be the handle of a valid sync object. Additionally, if <sync> is an EGL native fence sync object and the EGL_SYNC_NATIVE_FENCE_FD_ANDROID - attribute is not EGL_NO_NATIVE_FENCE_ANDROID then that file descriptor is - closed." + attribute is not EGL_NO_NATIVE_FENCE_FD_ANDROID then that file descriptor + is closed." Add the following after the last paragraph of Section 3.8.1 (Sync Objects), added by KHR_fence_sync @@ -213,11 +214,11 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) ------ * If <sync> is not a valid sync object for <dpy>, - EGL_NO_NATIVE_FENCE_ANDROID is returned and an EGL_BAD_PARAMETER + EGL_NO_NATIVE_FENCE_FD_ANDROID is returned and an EGL_BAD_PARAMETER error is generated. * If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute of <sync> is - EGL_NO_NATIVE_FENCE_ANDROID, EGL_NO_NATIVE_FENCE_ANDROID is returned - and an EGL_BAD_PARAMETER error is generated. + EGL_NO_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID is + returned and an EGL_BAD_PARAMETER error is generated. * If <dpy> does not match the display passed to eglCreateSyncKHR when <sync> was created, the behaviour is undefined." diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index dac8467..b3fa5fb 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -23,9 +23,6 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -ifeq ($(TARGET_BOARD_PLATFORM),omap3) - LOCAL_CFLAGS += -DNO_RGBX_8888 -endif ifeq ($(TARGET_BOARD_PLATFORM),omap4) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY endif diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 395402d..a6b51a9 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -80,6 +80,7 @@ DisplayDevice::DisplayDevice( EGLConfig config) : mFlinger(flinger), mType(type), mHwcDisplayId(-1), + mDisplayToken(displayToken), mNativeWindow(nativeWindow), mFramebufferSurface(framebufferSurface), mDisplay(EGL_NO_DISPLAY), diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp index 965ff01..0c94c7d 100644 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp +++ b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp @@ -26,6 +26,9 @@ namespace android { // ---------------------------------------------------------------------------- GraphicBufferAlloc::GraphicBufferAlloc() { +#ifdef QCOM_BSP + mBufferSize = 0; +#endif } GraphicBufferAlloc::~GraphicBufferAlloc() { @@ -33,7 +36,13 @@ GraphicBufferAlloc::~GraphicBufferAlloc() { sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, status_t* error) { +#ifdef QCOM_BSP + sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, + usage, mBufferSize)); +#else sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); +#endif + status_t err = graphicBuffer->initCheck(); *error = err; if (err != 0 || graphicBuffer->handle == 0) { @@ -48,6 +57,12 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h return graphicBuffer; } +#ifdef QCOM_BSP +void GraphicBufferAlloc::setGraphicBufferSize(int size) { + mBufferSize = size; +} +#endif + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h index b08750c..521383d 100644 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h +++ b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h @@ -35,6 +35,11 @@ public: virtual ~GraphicBufferAlloc(); virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, status_t* error); +#ifdef QCOM_BSP + virtual void setGraphicBufferSize(int size); +private: + int mBufferSize; +#endif }; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 379fb16..9b4f2ab 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -776,11 +776,6 @@ status_t HWComposer::prepare() { if (l.compositionType == HWC_FRAMEBUFFER) { disp.hasFbComp = true; } - // If the composition type is BLIT, we set this to - // trigger a FLIP - if(l.compositionType == HWC_BLIT) { - disp.hasFbComp = true; - } if (l.compositionType == HWC_OVERLAY) { disp.hasOvComp = true; } @@ -1000,6 +995,9 @@ public: getLayer()->visibleRegionScreen.numRects = 0; getLayer()->visibleRegionScreen.rects = NULL; } + virtual void setPerFrameDefaultState() { + //getLayer()->compositionType = HWC_FRAMEBUFFER; + } virtual void setSkip(bool skip) { if (skip) { getLayer()->flags |= HWC_SKIP_LAYER; @@ -1073,7 +1071,9 @@ public: virtual void setAcquireFenceFd(int fenceFd) { getLayer()->acquireFenceFd = fenceFd; } - + virtual void setPerFrameDefaultState() { + //getLayer()->compositionType = HWC_FRAMEBUFFER; + } virtual void setDefaultState() { getLayer()->compositionType = HWC_FRAMEBUFFER; getLayer()->hints = 0; @@ -1237,7 +1237,6 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { "HWC", "BACKGROUND", "FB TARGET", - "FB_BLIT", "UNKNOWN"}; if (type >= NELEM(compositionTypeName)) type = NELEM(compositionTypeName) - 1; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a78ffac..7c67407 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -141,6 +141,7 @@ public: virtual int32_t getCompositionType() const = 0; virtual uint32_t getHints() const = 0; virtual int getAndResetReleaseFenceFd() = 0; + virtual void setPerFrameDefaultState() = 0; virtual void setDefaultState() = 0; virtual void setSkip(bool skip) = 0; virtual void setBlending(uint32_t blending) = 0; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 064f689..c1561b2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -63,6 +63,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client) mFormat(PIXEL_FORMAT_NONE), mGLExtensions(GLExtensions::getInstance()), mOpaqueLayer(true), + mNeedsDithering(false), mSecure(false), mProtectedByApp(false) { @@ -110,7 +111,8 @@ void Layer::onFirstRef() mSurfaceTexture->setDefaultMaxBufferCount(3); #endif - updateTransformHint(); + const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); + updateTransformHint(hw); } Layer::~Layer() @@ -193,6 +195,23 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mSurfaceTexture->setDefaultBufferFormat(format); mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); + int displayMinColorDepth; + int layerRedsize; + switch (mFlinger->getUseDithering()) { + case 0: + mNeedsDithering = false; + break; + case 1: + displayMinColorDepth = mFlinger->getMinColorDepth(); + // we use the red index + layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); + mNeedsDithering = (layerRedsize > displayMinColorDepth); + break; + case 2: + mNeedsDithering = true; + break; + } + return NO_ERROR; } @@ -767,15 +786,12 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const return usage; } -void Layer::updateTransformHint() const { +void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { - // The transform hint is used to improve performance on the main - // display -- we can only have a single transform hint, it cannot + // The transform hint is used to improve performance, but we can + // only have a single transform hint, it cannot // apply to all displays. - // This is why we use the default display here. This is not an - // oversight. - sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); const Transform& planeTransform(hw->getTransform()); orientation = planeTransform.getOrientation(); if (orientation & Transform::ROT_INVALID) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6f75d8c..a3d6ab9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -77,6 +77,7 @@ public: virtual uint32_t doTransaction(uint32_t transactionFlags); virtual Region latchBuffer(bool& recomputeVisibleRegions); virtual bool isOpaque() const; + virtual bool needsDithering() const { return mNeedsDithering; } virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; virtual void onRemoved(); @@ -91,8 +92,8 @@ public: inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; } // Updates the transform hint in our SurfaceTexture to match - // the current orientation of the default display device. - virtual void updateTransformHint() const; + // the current orientation of the display device. + virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const; protected: virtual void onFirstRef(); @@ -142,6 +143,7 @@ private: PixelFormat mFormat; const GLExtensions& mGLExtensions; bool mOpaqueLayer; + bool mNeedsDithering; // page-flip thread (currently main thread) bool mSecure; // no screenshots diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index db4ef87..612e47b 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -300,6 +300,7 @@ void LayerBase::setGeometry( void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { + layer.setPerFrameDefaultState(); // we have to set the visible region on every frame because // we currently free it during onLayerDisplayed(), which is called // after HWComposer::commit() -- every frame. @@ -353,6 +354,7 @@ void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& glDisable(GL_TEXTURE_EXTERNAL_OES); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); + glDisable(GL_DITHER); LayerMesh mesh; computeGeometry(hw, &mesh); @@ -427,6 +429,12 @@ void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& texCoords[i].v = 1.0f - texCoords[i].v; } + if (needsDithering()) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoords); glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 00c4ffe..4d5a5b0 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -246,7 +246,7 @@ public: * Updates the SurfaceTexture's transform hint, for layers that have * a SurfaceTexture. */ - virtual void updateTransformHint() const { } + virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { } /** always call base class first */ virtual void dump(String8& result, char* scratch, size_t size) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 67b1316..1842949 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -104,7 +104,8 @@ SurfaceFlinger::SurfaceFlinger() mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), - mBootFinished(false) + mBootFinished(false), + mUseDithering(0) { ALOGI("SurfaceFlinger is starting"); @@ -122,8 +123,13 @@ SurfaceFlinger::SurfaceFlinger() mDebugDDMS = 0; } } + + property_get("persist.sys.use_dithering", value, "1"); + mUseDithering = atoi(value); + ALOGI_IF(mDebugRegion, "showupdates enabled"); ALOGI_IF(mDebugDDMS, "DDMS debugging enabled"); + ALOGI_IF(mUseDithering, "use dithering"); #ifdef SAMSUNG_HDMI_SUPPORT ALOGD(">>> Run service"); @@ -429,7 +435,11 @@ void SurfaceFlinger::initializeGL(EGLDisplay display) { glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); glShadeModel(GL_FLAT); - glDisable(GL_DITHER); + if (mUseDithering == 2) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } glDisable(GL_CULL_FACE); struct pack565 { @@ -467,6 +477,9 @@ void SurfaceFlinger::initializeGL(EGLDisplay display) { ALOGI("extensions: %s", extensions.getExtension()); ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize); ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]); + + // XXX Assume bit depth for red is equal to minimum depth of all colors + mMinColorDepth = r; } status_t SurfaceFlinger::readyToRun() @@ -564,6 +577,10 @@ uint32_t SurfaceFlinger::getMaxTextureSize() const { return mMaxTextureSize; } +uint32_t SurfaceFlinger::getMinColorDepth() const { + return mMinColorDepth; +} + uint32_t SurfaceFlinger::getMaxViewportDims() const { return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1]; @@ -1092,7 +1109,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (transactionFlags & eTraversalNeeded) { for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer = currentLayers[i]; + const sp<LayerBase>& layer(currentLayers[i]); uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -1165,18 +1182,6 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) disp->setProjection(state.orientation, state.viewport, state.frame); } - - // Walk through all the layers in currentLayers, - // and update their transform hint. - // - // TODO: we could be much more clever about which - // layers we touch and how often we do these updates - // (e.g. only touch the layers associated with this - // display, and only on a rotation). - for (size_t i = 0; i < count; i++) { - const sp<LayerBase>& layerBase = currentLayers[i]; - layerBase->updateTransformHint(); - } } } } @@ -1231,6 +1236,61 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } + if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { + // The transform hint might have changed for some layers + // (either because a display has changed, or because a layer + // as changed). + // + // Walk through all the layers in currentLayers, + // and update their transform hint. + // + // If a layer is visible only on a single display, then that + // display is used to calculate the hint, otherwise we use the + // default display. + // + // NOTE: we do this here, rather than in rebuildLayerStacks() so that + // the hint is set before we acquire a buffer from the surface texture. + // + // NOTE: layer transactions have taken place already, so we use their + // drawing state. However, SurfaceFlinger's own transaction has not + // happened yet, so we must use the current state layer list + // (soon to become the drawing state list). + // + sp<const DisplayDevice> disp; + uint32_t currentlayerStack = 0; + for (size_t i=0; i<count; i++) { + // NOTE: we rely on the fact that layers are sorted by + // layerStack first (so we don't have to traverse the list + // of displays for every layer). + const sp<LayerBase>& layerBase(currentLayers[i]); + uint32_t layerStack = layerBase->drawingState().layerStack; + if (i==0 || currentlayerStack != layerStack) { + currentlayerStack = layerStack; + // figure out if this layerstack is mirrored + // (more than one display) if so, pick the default display, + // if not, pick the only display it's on. + disp.clear(); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + sp<const DisplayDevice> hw(mDisplays[dpy]); + if (hw->getLayerStack() == currentlayerStack) { + if (disp == NULL) { + disp = hw; + } else { + disp = getDefaultDisplayDevice(); + break; + } + } + } + } + if (disp != NULL) { + // presumably this means this layer is using a layerStack + // that is not visible on any display + layerBase->updateTransformHint(disp); + } + } + } + + /* * Perform our own transaction if needed */ @@ -1576,9 +1636,6 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const layer->draw(hw, clip); break; } - case HWC_BLIT: - //Do nothing - break; case HWC_FRAMEBUFFER_TARGET: { // this should not happen as the iterator shouldn't // let us get there. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e8c4b9c..050d10f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -324,8 +324,12 @@ private: static EGLContext createGLContext(EGLDisplay disp, EGLConfig config); void initializeGL(EGLDisplay display); uint32_t getMaxTextureSize() const; + uint32_t getMinColorDepth() const; uint32_t getMaxViewportDims() const; + // 0: surface doesn't need dithering, 1: use if necessary, 2: use permanently + inline int getUseDithering() const { return mUseDithering; } + /* ------------------------------------------------------------------------ * Display and layer stack management */ @@ -423,6 +427,7 @@ private: sp<EventThread> mEventThread; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; + GLint mMinColorDepth; EGLContext mEGLContext; EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; @@ -448,6 +453,7 @@ private: volatile nsecs_t mDebugInTransaction; nsecs_t mLastTransactionTime; bool mBootFinished; + int mUseDithering; // these are thread safe mutable MessageQueue mEventQueue; |