diff options
| -rw-r--r-- | include/binder/Parcel.h | 55 | ||||
| -rw-r--r-- | include/gui/SurfaceTexture.h | 23 | ||||
| -rw-r--r-- | include/utils/Errors.h | 1 | ||||
| -rw-r--r-- | libs/binder/Parcel.cpp | 134 | ||||
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 156 | ||||
| -rw-r--r-- | libs/ui/Region.cpp | 1 | ||||
| -rw-r--r-- | libs/utils/Android.mk | 8 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 10 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 16 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/LayerBase.h | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 11 |
13 files changed, 328 insertions, 94 deletions
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index bfe13f01bc..3fa2acbdaa 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -38,6 +38,9 @@ struct flat_binder_object; // defined in support_p/binder_module.h class Parcel { public: + class ReadableBlob; + class WritableBlob; + Parcel(); ~Parcel(); @@ -46,7 +49,7 @@ public: size_t dataAvail() const; size_t dataPosition() const; size_t dataCapacity() const; - + status_t setDataSize(size_t size); void setDataPosition(size_t pos) const; status_t setDataCapacity(size_t size); @@ -56,6 +59,9 @@ public: status_t appendFrom(const Parcel *parcel, size_t start, size_t len); + bool pushAllowFds(bool allowFds); + void restoreAllowFds(bool lastValue); + bool hasFileDescriptors() const; // Writes the RPC header. @@ -109,7 +115,13 @@ public: // Place a file descriptor into the parcel. A dup of the fd is made, which // will be closed once the parcel is destroyed. status_t writeDupFileDescriptor(int fd); - + + // Writes a blob to the parcel. + // If the blob is small, then it is stored in-place, otherwise it is + // transferred by way of an anonymous shared memory region. + // The caller should call release() on the blob after writing its contents. + status_t writeBlob(size_t len, WritableBlob* outBlob); + status_t writeObject(const flat_binder_object& val, bool nullMetaData); // Like Parcel.java's writeNoException(). Just writes a zero int32. @@ -157,7 +169,11 @@ public: // Retrieve a file descriptor from the parcel. This returns the raw fd // in the parcel, which you do not own -- use dup() to get your own copy. int readFileDescriptor() const; - + + // Reads a blob from the parcel. + // The caller should call release() on the blob after reading its contents. + status_t readBlob(size_t len, ReadableBlob* outBlob) const; + const flat_binder_object* readObject(bool nullMetaData) const; // Explicitly close all file descriptors in the parcel. @@ -177,7 +193,7 @@ public: release_func relFunc, void* relCookie); void print(TextOutput& to, uint32_t flags = 0) const; - + private: Parcel(const Parcel& o); Parcel& operator=(const Parcel& o); @@ -212,9 +228,40 @@ private: mutable bool mFdsKnown; mutable bool mHasFds; + bool mAllowFds; release_func mOwner; void* mOwnerCookie; + + class Blob { + public: + Blob(); + ~Blob(); + + void release(); + inline size_t size() const { return mSize; } + + protected: + void init(bool mapped, void* data, size_t size); + void clear(); + + bool mMapped; + void* mData; + size_t mSize; + }; + +public: + class ReadableBlob : public Blob { + friend class Parcel; + public: + inline const void* data() const { return mData; } + }; + + class WritableBlob : public Blob { + friend class Parcel; + public: + inline void* data() { return mData; } + }; }; // --------------------------------------------------------------------------- diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 493993d6d9..e2d6179ef0 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -20,13 +20,15 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #include <gui/ISurfaceTexture.h> #include <ui/GraphicBuffer.h> -#include <utils/threads.h> +#include <utils/String8.h> #include <utils/Vector.h> +#include <utils/threads.h> #define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture" @@ -60,7 +62,8 @@ public: // tex indicates the name OpenGL texture to which images are to be streamed. // This texture name cannot be changed once the SurfaceTexture is created. - SurfaceTexture(GLuint tex, bool allowSynchronousMode = true); + SurfaceTexture(GLuint tex, bool allowSynchronousMode = true, + GLenum texTarget = GL_TEXTURE_EXTERNAL_OES); virtual ~SurfaceTexture(); @@ -202,6 +205,10 @@ public: // by OpenGL ES as a texture) then those buffer will remain allocated. void abandon(); + // set the name of the SurfaceTexture that will be used to identify it in + // log messages. + void setName(const String8& name); + // dump our state in a String void dump(String8& result) const; void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; @@ -444,11 +451,23 @@ private: // all ISurfaceTexture methods capable of returning an error. bool mAbandoned; + // mName is a string used to identify the SurfaceTexture in log messages. + // It is set by the setName method. + String8 mName; + // mMutex is the mutex used to prevent concurrent access to the member // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; + // mTexTarget is the GL texture target with which the GL texture object is + // associated. It is set in the constructor and never changed. It is + // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android + // Browser. In that case it is set to GL_TEXTURE_2D to allow + // glCopyTexSubImage to read from the texture. This is a hack to work + // around a GL driver limitation on the number of FBO attachments, which the + // browser's tile cache exceeds. + const GLenum mTexTarget; }; // ---------------------------------------------------------------------------- diff --git a/include/utils/Errors.h b/include/utils/Errors.h index 81f818b75d..0b75b1926c 100644 --- a/include/utils/Errors.h +++ b/include/utils/Errors.h @@ -72,6 +72,7 @@ enum { TIMED_OUT = 0x80000005, UNKNOWN_TRANSACTION = 0x80000006, #endif + FDS_NOT_ALLOWED = 0x80000007, }; // Restore define; enumeration is in "android" namespace, so the value defined diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index a0fc4d05bc..608877eb7d 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -30,12 +30,14 @@ #include <utils/TextOutput.h> #include <utils/misc.h> #include <utils/Flattenable.h> +#include <cutils/ashmem.h> #include <private/binder/binder_module.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <sys/mman.h> #ifndef INT32_MAX #define INT32_MAX ((int32_t)(2147483647)) @@ -54,6 +56,9 @@ // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER #define EX_HAS_REPLY_HEADER -128 +// Maximum size of a blob to transfer in-place. +static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024; + // XXX This can be made public if we want to provide // support for typed data. struct small_flat_data @@ -399,6 +404,8 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) mDataPos += len; mDataSize += len; + err = NO_ERROR; + if (numObjects > 0) { // grow objects if (mObjectsCapacity < mObjectsSize + numObjects) { @@ -430,11 +437,28 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) flat->handle = dup(flat->handle); flat->cookie = (void*)1; mHasFds = mFdsKnown = true; + if (!mAllowFds) { + err = FDS_NOT_ALLOWED; + } } } } - return NO_ERROR; + return err; +} + +bool Parcel::pushAllowFds(bool allowFds) +{ + const bool origValue = mAllowFds; + if (!allowFds) { + mAllowFds = false; + } + return origValue; +} + +void Parcel::restoreAllowFds(bool lastValue) +{ + mAllowFds = lastValue; } bool Parcel::hasFileDescriptors() const @@ -706,6 +730,54 @@ status_t Parcel::writeDupFileDescriptor(int fd) return writeObject(obj, true); } +status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) +{ + status_t status; + + if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) { + LOGV("writeBlob: write in place"); + status = writeInt32(0); + if (status) return status; + + void* ptr = writeInplace(len); + if (!ptr) return NO_MEMORY; + + outBlob->init(false /*mapped*/, ptr, len); + return NO_ERROR; + } + + LOGV("writeBlob: write to ashmem"); + int fd = ashmem_create_region("Parcel Blob", len); + if (fd < 0) return NO_MEMORY; + + int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); + if (result < 0) { + status = -result; + } else { + void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + status = -errno; + } else { + result = ashmem_set_prot_region(fd, PROT_READ); + if (result < 0) { + status = -result; + } else { + status = writeInt32(1); + if (!status) { + status = writeFileDescriptor(fd); + if (!status) { + outBlob->init(true /*mapped*/, ptr, len); + return NO_ERROR; + } + } + } + } + ::munmap(ptr, len); + } + ::close(fd); + return status; +} + status_t Parcel::write(const Flattenable& val) { status_t err; @@ -759,6 +831,9 @@ restart_write: // remember if it's a file descriptor if (val.type == BINDER_TYPE_FD) { + if (!mAllowFds) { + return FDS_NOT_ALLOWED; + } mHasFds = mFdsKnown = true; } @@ -1025,6 +1100,32 @@ int Parcel::readFileDescriptor() const return BAD_TYPE; } +status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const +{ + int32_t useAshmem; + status_t status = readInt32(&useAshmem); + if (status) return status; + + if (!useAshmem) { + LOGV("readBlob: read in place"); + const void* ptr = readInplace(len); + if (!ptr) return BAD_VALUE; + + outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len); + return NO_ERROR; + } + + LOGV("readBlob: read from ashmem"); + int fd = readFileDescriptor(); + if (fd == int(BAD_TYPE)) return BAD_VALUE; + + void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (!ptr) return NO_MEMORY; + + outBlob->init(true /*mapped*/, ptr, len); + return NO_ERROR; +} + status_t Parcel::read(Flattenable& val) const { // size @@ -1283,6 +1384,7 @@ status_t Parcel::restartWrite(size_t desired) mNextObjectHint = 0; mHasFds = false; mFdsKnown = true; + mAllowFds = true; return NO_ERROR; } @@ -1434,6 +1536,7 @@ void Parcel::initState() mNextObjectHint = 0; mHasFds = false; mFdsKnown = true; + mAllowFds = true; mOwner = NULL; } @@ -1452,4 +1555,33 @@ void Parcel::scanForFds() const mFdsKnown = true; } +// --- Parcel::Blob --- + +Parcel::Blob::Blob() : + mMapped(false), mData(NULL), mSize(0) { +} + +Parcel::Blob::~Blob() { + release(); +} + +void Parcel::Blob::release() { + if (mMapped && mData) { + ::munmap(mData, mSize); + } + clear(); +} + +void Parcel::Blob::init(bool mapped, void* data, size_t size) { + mMapped = mapped; + mData = data; + mSize = size; +} + +void Parcel::Blob::clear() { + mMapped = false; + mData = NULL; + mSize = 0; +} + }; // namespace android diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index f2bc81e9a7..c72a45b895 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -39,6 +39,12 @@ #define ALLOW_DEQUEUE_CURRENT_BUFFER false +// Macros for including the SurfaceTexture name in log messages +#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__) namespace android { @@ -82,7 +88,14 @@ static float mtxRot270[16] = { static void mtxMul(float out[16], const float a[16], const float b[16]); -SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : +// 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) : mDefaultWidth(1), mDefaultHeight(1), mPixelFormat(PIXEL_FORMAT_RGBA_8888), @@ -98,16 +111,21 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mSynchronousMode(false), mAllowSynchronousMode(allowSynchronousMode), mConnectedApi(NO_CONNECTED_API), - mAbandoned(false) { - LOGV("SurfaceTexture::SurfaceTexture"); + mAbandoned(false), + mTexTarget(texTarget) { + // Choose a name using the PID and a process-unique ID. + mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); + + ST_LOGV("SurfaceTexture::SurfaceTexture"); sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); mNextCrop.makeInvalid(); - memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); + memcpy(mCurrentTransformMatrix, mtxIdentity, + sizeof(mCurrentTransformMatrix)); } SurfaceTexture::~SurfaceTexture() { - LOGV("SurfaceTexture::~SurfaceTexture"); + ST_LOGV("SurfaceTexture::~SurfaceTexture"); freeAllBuffersLocked(); } @@ -151,22 +169,22 @@ status_t SurfaceTexture::setBufferCountServer(int bufferCount) { } status_t SurfaceTexture::setBufferCount(int bufferCount) { - LOGV("SurfaceTexture::setBufferCount"); + ST_LOGV("SurfaceTexture::setBufferCount"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setBufferCount: SurfaceTexture has been abandoned!"); + ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!"); return NO_INIT; } if (bufferCount > NUM_BUFFER_SLOTS) { - LOGE("setBufferCount: bufferCount larger than slots available"); + 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) { - LOGE("setBufferCount: client owns some buffers"); + ST_LOGE("setBufferCount: client owns some buffers"); return -EINVAL; } } @@ -181,7 +199,7 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { } if (bufferCount < minBufferSlots) { - LOGE("setBufferCount: requested buffer count (%d) is less than " + ST_LOGE("setBufferCount: requested buffer count (%d) is less than " "minimum (%d)", bufferCount, minBufferSlots); return BAD_VALUE; } @@ -200,7 +218,8 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) { if (!w || !h) { - LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", w, h); + ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", + w, h); return BAD_VALUE; } @@ -211,14 +230,14 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) } status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - LOGV("SurfaceTexture::requestBuffer"); + ST_LOGV("SurfaceTexture::requestBuffer"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("requestBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } if (slot < 0 || mBufferCount <= slot) { - LOGE("requestBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", mBufferCount, slot); return BAD_VALUE; } @@ -229,10 +248,10 @@ status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { - LOGV("SurfaceTexture::dequeueBuffer"); + ST_LOGV("SurfaceTexture::dequeueBuffer"); if ((w && !h) || (!w && h)) { - LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); + ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); return BAD_VALUE; } @@ -245,7 +264,7 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, bool tryAgain = true; while (tryAgain) { if (mAbandoned) { - LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -334,7 +353,8 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, // than allowed. const int avail = mBufferCount - (dequeuedCount+1); if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { - LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", + ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded " + "(dequeued=%d)", MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), dequeuedCount); return -EBUSY; @@ -391,7 +411,8 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, mGraphicBufferAlloc->createGraphicBuffer( w, h, format, usage, &error)); if (graphicBuffer == 0) { - LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); + ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " + "failed"); return error; } if (updateFormat) { @@ -413,7 +434,7 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); + ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -441,29 +462,29 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - LOGV("SurfaceTexture::queueBuffer"); + ST_LOGV("SurfaceTexture::queueBuffer"); sp<FrameAvailableListener> listener; { // scope for the lock Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("queueBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } if (buf < 0 || buf >= mBufferCount) { - LOGE("queueBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); return -EINVAL; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); + ST_LOGE("queueBuffer: slot %d is not owned by the client " + "(state=%d)", buf, mSlots[buf].mBufferState); return -EINVAL; } else if (buf == mCurrentTexture) { - LOGE("queueBuffer: slot %d is current!", buf); + ST_LOGE("queueBuffer: slot %d is current!", buf); return -EINVAL; } else if (!mSlots[buf].mRequestBufferCalled) { - LOGE("queueBuffer: slot %d was enqueued without requesting a " + ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " "buffer", buf); return -EINVAL; } @@ -513,20 +534,20 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, } void SurfaceTexture::cancelBuffer(int buf) { - LOGV("SurfaceTexture::cancelBuffer"); + ST_LOGV("SurfaceTexture::cancelBuffer"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); + ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); return; } if (buf < 0 || buf >= mBufferCount) { - LOGE("cancelBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); return; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", + ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", buf, mSlots[buf].mBufferState); return; } @@ -535,10 +556,10 @@ void SurfaceTexture::cancelBuffer(int buf) { } status_t SurfaceTexture::setCrop(const Rect& crop) { - LOGV("SurfaceTexture::setCrop"); + ST_LOGV("SurfaceTexture::setCrop"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setCrop: SurfaceTexture has been abandoned!"); + ST_LOGE("setCrop: SurfaceTexture has been abandoned!"); return NO_INIT; } mNextCrop = crop; @@ -546,10 +567,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) { } status_t SurfaceTexture::setTransform(uint32_t transform) { - LOGV("SurfaceTexture::setTransform"); + ST_LOGV("SurfaceTexture::setTransform"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setTransform: SurfaceTexture has been abandoned!"); + ST_LOGE("setTransform: SurfaceTexture has been abandoned!"); return NO_INIT; } mNextTransform = transform; @@ -558,11 +579,11 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::connect(int api, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); + ST_LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("connect: SurfaceTexture has been abandoned!"); + ST_LOGE("connect: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -573,7 +594,7 @@ status_t SurfaceTexture::connect(int api, case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi != NO_CONNECTED_API) { - LOGE("connect: already connected (cur=%d, req=%d)", + ST_LOGE("connect: already connected (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } else { @@ -591,11 +612,11 @@ status_t SurfaceTexture::connect(int api, } status_t SurfaceTexture::disconnect(int api) { - LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); + ST_LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("disconnect: SurfaceTexture has been abandoned!"); + ST_LOGE("disconnect: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -613,7 +634,7 @@ status_t SurfaceTexture::disconnect(int api) { mNextTransform = 0; mDequeueCondition.signal(); } else { - LOGE("disconnect: connected to another api (cur=%d, req=%d)", + ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } @@ -626,7 +647,7 @@ status_t SurfaceTexture::disconnect(int api) { } status_t SurfaceTexture::setScalingMode(int mode) { - LOGV("SurfaceTexture::setScalingMode(%d)", mode); + ST_LOGV("SurfaceTexture::setScalingMode(%d)", mode); switch (mode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: @@ -642,11 +663,11 @@ status_t SurfaceTexture::setScalingMode(int mode) { } status_t SurfaceTexture::updateTexImage() { - LOGV("SurfaceTexture::updateTexImage"); + ST_LOGV("SurfaceTexture::updateTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); + ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); return NO_INIT; } @@ -661,7 +682,7 @@ status_t SurfaceTexture::updateTexImage() { if (image == EGL_NO_IMAGE_KHR) { EGLDisplay dpy = eglGetCurrentDisplay(); if (mSlots[buf].mGraphicBuffer == 0) { - LOGE("buffer at slot %d is null", buf); + ST_LOGE("buffer at slot %d is null", buf); return BAD_VALUE; } image = createImage(dpy, mSlots[buf].mGraphicBuffer); @@ -676,15 +697,15 @@ status_t SurfaceTexture::updateTexImage() { GLint error; while ((error = glGetError()) != GL_NO_ERROR) { - LOGW("updateTexImage: clearing GL error: %#04x", error); + ST_LOGW("updateTexImage: clearing GL error: %#04x", error); } - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); + glBindTexture(mTexTarget, mTexName); + glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); bool failed = false; while ((error = glGetError()) != GL_NO_ERROR) { - LOGE("error binding external texture image %p (slot %d): %#04x", + ST_LOGE("error binding external texture image %p (slot %d): %#04x", image, buf, error); failed = true; } @@ -715,7 +736,7 @@ status_t SurfaceTexture::updateTexImage() { mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); + glBindTexture(mTexTarget, mTexName); } return OK; @@ -741,7 +762,7 @@ bool SurfaceTexture::isExternalFormat(uint32_t format) } GLenum SurfaceTexture::getCurrentTextureTarget() const { - return GL_TEXTURE_EXTERNAL_OES; + return mTexTarget; } void SurfaceTexture::getTransformMatrix(float mtx[16]) { @@ -750,7 +771,7 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) { } void SurfaceTexture::computeCurrentTransformMatrix() { - LOGV("SurfaceTexture::computeCurrentTransformMatrix"); + ST_LOGV("SurfaceTexture::computeCurrentTransformMatrix"); float xform[16]; for (int i = 0; i < 16; i++) { @@ -841,14 +862,14 @@ void SurfaceTexture::computeCurrentTransformMatrix() { } nsecs_t SurfaceTexture::getTimestamp() { - LOGV("SurfaceTexture::getTimestamp"); + ST_LOGV("SurfaceTexture::getTimestamp"); Mutex::Autolock lock(mMutex); return mCurrentTimestamp; } void SurfaceTexture::setFrameAvailableListener( const sp<FrameAvailableListener>& listener) { - LOGV("SurfaceTexture::setFrameAvailableListener"); + ST_LOGV("SurfaceTexture::setFrameAvailableListener"); Mutex::Autolock lock(mMutex); mFrameAvailableListener = listener; } @@ -892,11 +913,11 @@ status_t SurfaceTexture::drainQueueLocked() { while (mSynchronousMode && !mQueue.isEmpty()) { mDequeueCondition.wait(mMutex); if (mAbandoned) { - LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); + ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); return NO_INIT; } if (mConnectedApi == NO_CONNECTED_API) { - LOGE("drainQueueLocked: SurfaceTexture is not connected!"); + ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!"); return NO_INIT; } } @@ -926,7 +947,7 @@ EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); if (image == EGL_NO_IMAGE_KHR) { EGLint error = eglGetError(); - LOGE("error creating EGLImage: %#x", error); + ST_LOGE("error creating EGLImage: %#x", error); } return image; } @@ -956,7 +977,7 @@ int SurfaceTexture::query(int what, int* outValue) Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("query: SurfaceTexture has been abandoned!"); + ST_LOGE("query: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -991,6 +1012,10 @@ void SurfaceTexture::abandon() { mDequeueCondition.signal(); } +void SurfaceTexture::setName(const String8& name) { + mName = name; +} + void SurfaceTexture::dump(String8& result) const { char buffer[1024]; @@ -1004,8 +1029,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, snprintf(buffer, SIZE, "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " "mPixelFormat=%d, mTexName=%d\n", - prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, - mPixelFormat, mTexName); + prefix, mBufferCount, mSynchronousMode, mDefaultWidth, + mDefaultHeight, mPixelFormat, mTexName); result.append(buffer); String8 fifo; @@ -1024,8 +1049,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, prefix, mCurrentCrop.left, mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, mCurrentTransform, mCurrentTexture, - prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom, - mNextTransform, fifoSize, fifo.string() + prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, + mNextCrop.bottom, mNextTransform, fifoSize, fifo.string() ); result.append(buffer); @@ -1048,8 +1073,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, "transform=0x%02x, timestamp=%lld", prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState), - slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom, - slot.mTransform, slot.mTimestamp + slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, + slot.mCrop.bottom, slot.mTransform, slot.mTimestamp ); result.append(buffer); @@ -1057,7 +1082,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, if (buf != NULL) { snprintf(buffer, SIZE, ", %p [%4ux%4u:%4u,%3X]", - buf->handle, buf->width, buf->height, buf->stride, buf->format); + buf->handle, buf->width, buf->height, buf->stride, + buf->format); result.append(buffer); } result.append("\n"); diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 8dab291b3c..565608889d 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -482,6 +482,7 @@ void Region::boolean_operation(int op, Region& dst, if (!rhs.isValid()) { LOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}", op, rhs.left, rhs.top, rhs.right, rhs.bottom); + return; } #if VALIDATE_WITH_CORECG || VALIDATE_REGIONS diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index e4eadbd004..638f72f0b6 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -100,12 +100,8 @@ LOCAL_LDLIBS += -lpthread LOCAL_SHARED_LIBRARIES := \ libz \ liblog \ - libcutils - -ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86) -# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp -LOCAL_SHARED_LIBRARIES += libdl -endif # linux-x86 + libcutils \ + libdl LOCAL_MODULE:= libutils include $(BUILD_SHARED_LIBRARY) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index e707bdce7d..879e858027 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -176,9 +176,9 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, mList->numHwLayers, mList->flags); result.append(buffer); result.append( - " type | hints | flags | tr | blend | format | source rectangle | crop rectangle name \n" - "-----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); - // " ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] + " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" + "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); + // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] for (size_t i=0 ; i<mList->numHwLayers ; i++) { const hwc_layer_t& l(mList->hwLayers[i]); const sp<LayerBase> layer(visibleLayersSortedByZ[i]); @@ -190,9 +190,9 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, } } snprintf(buffer, SIZE, - " %8s | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", + " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", l.compositionType ? "OVERLAY" : "FB", - l.hints, l.flags, l.transform, l.blending, format, + intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format, l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, layer->getName().string()); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f85ce7fd09..41d7a90978 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -112,6 +112,11 @@ void Layer::onRemoved() mSurfaceTexture->abandon(); } +void Layer::setName(const String8& name) { + LayerBase::setName(name); + mSurfaceTexture->setName(name); +} + sp<ISurface> Layer::createSurface() { class BSurface : public BnSurface, public LayerCleaner { @@ -371,11 +376,12 @@ uint32_t Layer::doTransaction(uint32_t flags) Layer::State& editDraw(mDrawingState); editDraw.requested_w = temp.requested_w; editDraw.requested_h = temp.requested_h; - - // record the new size, form this point on, when the client request - // a buffer, it'll get the new size. - mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h); } + + // record the new size, form this point on, when the client request + // a buffer, it'll get the new size. + mSurfaceTexture->setDefaultBufferSize(temp.requested_w, + temp.requested_h); } if (temp.sequence != front.sequence) { @@ -578,7 +584,7 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const uint32_t Layer::getTransformHint() const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { - orientation = getOrientation(); + orientation = getPlaneOrientation(); if (orientation & Transform::ROT_INVALID) { orientation = 0; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ff389aecef..82e35218d2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -74,6 +74,7 @@ public: virtual bool isProtected() const; virtual void onRemoved(); virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); } + virtual void setName(const String8& name); // LayerBaseClient interface virtual wp<IBinder> getSurfaceTextureBinder() const; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index e5ce814bda..7a47f620f3 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -45,6 +45,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mFiltering(false), mNeedsFiltering(false), mInOverlay(false), mOrientation(0), + mPlaneOrientation(0), mTransactionFlags(0), mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), mInvalidate(0) @@ -256,6 +257,7 @@ void LayerBase::validateVisibility(const Transform& planeTransform) // cache a few things... mOrientation = tr.getOrientation(); + mPlaneOrientation = planeTransform.getOrientation(); mTransform = tr; mTransformedBounds = tr.makeBounds(w, h); } diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index a14b397a8d..7f6214510d 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -81,7 +81,7 @@ public: Region transparentRegion; }; - void setName(const String8& name); + virtual void setName(const String8& name); String8 getName() const; // modify current state @@ -221,6 +221,7 @@ public: inline State& currentState() { return mCurrentState; } int32_t getOrientation() const { return mOrientation; } + int32_t getPlaneOrientation() const { return mPlaneOrientation; } protected: const GraphicPlane& graphicPlane(int dpy) const; @@ -254,6 +255,7 @@ private: protected: // cached during validateVisibility() int32_t mOrientation; + int32_t mPlaneOrientation; Transform mTransform; GLfloat mVertices[4][2]; Rect mTransformedBounds; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 09097eea8e..3f154ce329 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -986,19 +986,20 @@ void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut) void SurfaceFlinger::composeSurfaces(const Region& dirty) { - if (UNLIKELY(!mWormholeRegion.isEmpty())) { + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + HWComposer& hwc(hw.getHwComposer()); + + const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER); + if (UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) { // should never happen unless the window manager has a bug // draw something... drawWormhole(); } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - HWComposer& hwc(hw.getHwComposer()); - hwc_layer_t* const cur(hwc.getLayers()); - /* * and then, render the layers targeted at the framebuffer */ + hwc_layer_t* const cur(hwc.getLayers()); const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { |