diff options
| -rw-r--r-- | include/gui/SurfaceTexture.h | 19 | ||||
| -rw-r--r-- | include/surfaceflinger/IGraphicBufferAlloc.h | 64 | ||||
| -rw-r--r-- | include/surfaceflinger/ISurfaceComposer.h | 14 | ||||
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 43 | ||||
| -rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 15 | ||||
| -rw-r--r-- | libs/surfaceflinger_client/Android.mk | 1 | ||||
| -rw-r--r-- | libs/surfaceflinger_client/IGraphicBufferAlloc.cpp | 108 | ||||
| -rw-r--r-- | libs/surfaceflinger_client/ISurfaceComposer.cpp | 46 | ||||
| -rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 10 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 68 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 20 |
11 files changed, 329 insertions, 79 deletions
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 09cf2a27f3..002e48b6d9 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -26,12 +26,15 @@ #include <ui/GraphicBuffer.h> #include <utils/threads.h> +#include <utils/Vector.h> #define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture" namespace android { // ---------------------------------------------------------------------------- +class IGraphicBufferAlloc; + class SurfaceTexture : public BnSurfaceTexture { public: enum { MIN_BUFFER_SLOTS = 3 }; @@ -140,6 +143,12 @@ private: // reset mCurrentTexture to INVALID_BUFFER_SLOT. int mCurrentTexture; + // mCurrentTextureBuf is the graphic buffer of the current texture. It's + // possible that this buffer is not associated with any buffer slot, so we + // must track it separately in order to properly use + // IGraphicBufferAlloc::freeAllGraphicBuffersExcept. + sp<GraphicBuffer> mCurrentTextureBuf; + // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set to mLastQueuedCrop each time updateTexImage is called. Rect mCurrentCrop; @@ -176,6 +185,16 @@ private: // changed with a call to setTexName. const GLuint mTexName; + // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to + // allocate new GraphicBuffer objects. + sp<IGraphicBufferAlloc> mGraphicBufferAlloc; + + // mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is + // referencing. This is kept so that gralloc implementations do not need to + // properly handle the case where SurfaceFlinger no longer holds a reference + // to a buffer, but other processes do. + Vector<sp<GraphicBuffer> > mAllocdBuffers; + // 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. diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h new file mode 100644 index 0000000000..d996af75a4 --- /dev/null +++ b/include/surfaceflinger/IGraphicBufferAlloc.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H +#define ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/RefBase.h> + +#include <binder/IInterface.h> + +namespace android { +// ---------------------------------------------------------------------------- + +class IGraphicBufferAlloc : public IInterface +{ +public: + DECLARE_META_INTERFACE(GraphicBufferAlloc); + + /* Create a new GraphicBuffer for the client to use. The server will + * maintain a reference to the newly created GraphicBuffer until + * freeAllGraphicBuffers is called. + */ + virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) = 0; + + /* Free all but one of the GraphicBuffer objects that the server is + * currently referencing. If bufIndex is not a valid index of the buffers + * the server is referencing, then all buffers are freed. + */ + virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 1bab7d71bc..56ed3a4cf8 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -28,6 +28,7 @@ #include <ui/PixelFormat.h> #include <surfaceflinger/ISurfaceComposerClient.h> +#include <surfaceflinger/IGraphicBufferAlloc.h> namespace android { // ---------------------------------------------------------------------------- @@ -96,6 +97,10 @@ public: */ virtual sp<ISurfaceComposerClient> createClientConnection() = 0; + /* create a graphic buffer allocator + */ + virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0; + /* retrieve the control block */ virtual sp<IMemoryHeap> getCblk() const = 0; @@ -131,13 +136,6 @@ public: * This is an ASYNCHRONOUS call. */ virtual void signal() const = 0; - - /* Create a new GraphicBuffer for the client to use. SurfaceFlinger will - * not maintain a reference to the GraphicBuffer, so the underlying native - * handle will be freed once the client references are released. - */ - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) const = 0; }; // ---------------------------------------------------------------------------- @@ -151,7 +149,7 @@ public: BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, CREATE_CLIENT_CONNECTION, - CREATE_GRAPHIC_BUFFER, + CREATE_GRAPHIC_BUFFER_ALLOC, GET_CBLK, OPEN_GLOBAL_TRANSACTION, CLOSE_GLOBAL_TRANSACTION, diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 1389ed6a5c..447de76508 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -29,6 +29,7 @@ #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/SurfaceComposerClient.h> +#include <surfaceflinger/IGraphicBufferAlloc.h> #include <utils/Log.h> @@ -83,6 +84,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex) : mSlots[i].mEglDisplay = EGL_NO_DISPLAY; mSlots[i].mOwnedByClient = false; } + sp<ISurfaceComposer> composer(ComposerService::getComposerService()); + mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); } SurfaceTexture::~SurfaceTexture() { @@ -110,9 +113,8 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf, return 0; } usage |= GraphicBuffer::USAGE_HW_TEXTURE; - sp<ISurfaceComposer> composer(ComposerService::getComposerService()); - sp<GraphicBuffer> graphicBuffer(composer->createGraphicBuffer(w, h, - format, usage)); + sp<GraphicBuffer> graphicBuffer( + mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage)); if (graphicBuffer == 0) { LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed"); } else { @@ -122,6 +124,7 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf, mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; } + mAllocdBuffers.add(graphicBuffer); } return graphicBuffer; } @@ -204,27 +207,28 @@ status_t SurfaceTexture::updateTexImage() { // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT, // so this check will fail until a buffer gets queued. if (mCurrentTexture != mLastQueued) { - // Update the SurfaceTexture state. - mCurrentTexture = mLastQueued; - mCurrentCrop = mLastQueuedCrop; - mCurrentTransform = mLastQueuedTransform; - // Update the GL texture object. - EGLImageKHR image = mSlots[mCurrentTexture].mEglImage; + EGLImageKHR image = mSlots[mLastQueued].mEglImage; if (image == EGL_NO_IMAGE_KHR) { EGLDisplay dpy = eglGetCurrentDisplay(); - sp<GraphicBuffer> graphicBuffer = mSlots[mCurrentTexture].mGraphicBuffer; + sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer; image = createImage(dpy, graphicBuffer); - mSlots[mCurrentTexture].mEglImage = image; - mSlots[mCurrentTexture].mEglDisplay = dpy; + mSlots[mLastQueued].mEglImage = image; + mSlots[mLastQueued].mEglDisplay = dpy; } glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); GLint error = glGetError(); if (error != GL_NO_ERROR) { LOGE("error binding external texture image %p (slot %d): %#04x", - image, mCurrentTexture, error); + image, mLastQueued, error); return -EINVAL; } + + // Update the SurfaceTexture state. + mCurrentTexture = mLastQueued; + mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer; + mCurrentCrop = mLastQueuedCrop; + mCurrentTransform = mLastQueuedTransform; } return OK; } @@ -282,6 +286,19 @@ void SurfaceTexture::freeAllBuffers() { mSlots[i].mEglDisplay = EGL_NO_DISPLAY; } } + + int exceptBuf = -1; + for (size_t i = 0; i < mAllocdBuffers.size(); i++) { + if (mAllocdBuffers[i] == mCurrentTextureBuf) { + exceptBuf = i; + break; + } + } + mAllocdBuffers.clear(); + if (exceptBuf >= 0) { + mAllocdBuffers.add(mCurrentTextureBuf); + } + mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf); } EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 8a5914460b..24cee24d4d 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "SurfaceTextureClient" +//#define LOG_NDEBUG 0 #include <gui/SurfaceTextureClient.h> @@ -82,10 +83,12 @@ int SurfaceTextureClient::setSwapInterval(int interval) { } int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { + LOGV("SurfaceTextureClient::dequeueBuffer"); Mutex::Autolock lock(mMutex); int buf = -1; status_t err = mSurfaceTexture->dequeueBuffer(&buf); if (err < 0) { + LOGE("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err); return err; } sp<GraphicBuffer>& gbuf(mSlots[buf]); @@ -96,6 +99,7 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight, mReqFormat, mReqUsage); if (gbuf == 0) { + LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed"); return NO_MEMORY; } } @@ -104,6 +108,7 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { } int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { + LOGV("SurfaceTextureClient::cancelBuffer"); Mutex::Autolock lock(mMutex); for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (mSlots[i].get() == buffer) { @@ -115,11 +120,13 @@ int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { } int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { + LOGV("SurfaceTextureClient::lockBuffer"); Mutex::Autolock lock(mMutex); return OK; } int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { + LOGV("SurfaceTextureClient::queueBuffer"); Mutex::Autolock lock(mMutex); for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (mSlots[i].get() == GraphicBuffer::getSelf(buffer)) { @@ -131,6 +138,7 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { } int SurfaceTextureClient::query(int what, int* value) { + LOGV("SurfaceTextureClient::query"); Mutex::Autolock lock(mMutex); // XXX: Implement this! return INVALID_OPERATION; @@ -206,17 +214,20 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { } int SurfaceTextureClient::connect(int api) { + LOGV("SurfaceTextureClient::connect"); // XXX: Implement this! return INVALID_OPERATION; } int SurfaceTextureClient::disconnect(int api) { + LOGV("SurfaceTextureClient::disconnect"); // XXX: Implement this! return INVALID_OPERATION; } int SurfaceTextureClient::setUsage(uint32_t reqUsage) { + LOGV("SurfaceTextureClient::setUsage"); Mutex::Autolock lock(mMutex); mReqUsage = reqUsage; return OK; @@ -224,6 +235,7 @@ int SurfaceTextureClient::setUsage(uint32_t reqUsage) int SurfaceTextureClient::setCrop(Rect const* rect) { + LOGV("SurfaceTextureClient::setCrop"); Mutex::Autolock lock(mMutex); // empty/invalid rects are not allowed @@ -239,6 +251,7 @@ int SurfaceTextureClient::setCrop(Rect const* rect) int SurfaceTextureClient::setBufferCount(int bufferCount) { + LOGV("SurfaceTextureClient::setBufferCount"); Mutex::Autolock lock(mMutex); status_t err = mSurfaceTexture->setBufferCount(bufferCount); @@ -254,6 +267,7 @@ int SurfaceTextureClient::setBufferCount(int bufferCount) int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) { + LOGV("SurfaceTextureClient::setBuffersGeometry"); Mutex::Autolock lock(mMutex); if (w<0 || h<0 || format<0) @@ -271,6 +285,7 @@ int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) int SurfaceTextureClient::setBuffersTransform(int transform) { + LOGV("SurfaceTextureClient::setBuffersTransform"); Mutex::Autolock lock(mMutex); status_t err = mSurfaceTexture->setTransform(transform); return err; diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk index ce3c71a7d9..4a0faf06a1 100644 --- a/libs/surfaceflinger_client/Android.mk +++ b/libs/surfaceflinger_client/Android.mk @@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \ ISurfaceComposer.cpp \ ISurface.cpp \ ISurfaceComposerClient.cpp \ + IGraphicBufferAlloc.cpp \ LayerState.cpp \ SharedBufferStack.cpp \ Surface.cpp \ diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp new file mode 100644 index 0000000000..e05da725c4 --- /dev/null +++ b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// tag as surfaceflinger +#define LOG_TAG "SurfaceFlinger" + +#include <stdint.h> +#include <sys/types.h> + +#include <binder/Parcel.h> + +#include <ui/GraphicBuffer.h> + +#include <surfaceflinger/IGraphicBufferAlloc.h> + +// --------------------------------------------------------------------------- + +namespace android { + +enum { + CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION, + FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, +}; + +class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc> +{ +public: + BpGraphicBufferAlloc(const sp<IBinder>& impl) + : BpInterface<IGraphicBufferAlloc>(impl) + { + } + + virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) { + Parcel data, reply; + data.writeInterfaceToken( + IGraphicBufferAlloc::getInterfaceDescriptor()); + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(format); + data.writeInt32(usage); + remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply); + sp<GraphicBuffer> graphicBuffer; + bool nonNull = (bool)reply.readInt32(); + if (nonNull) { + graphicBuffer = new GraphicBuffer(); + reply.read(*graphicBuffer); + } + return graphicBuffer; + } + + virtual void freeAllGraphicBuffersExcept(int bufIdx) { + Parcel data, reply; + data.writeInterfaceToken( + IGraphicBufferAlloc::getInterfaceDescriptor()); + data.writeInt32(bufIdx); + remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc"); + +// ---------------------------------------------------------------------- + +status_t BnGraphicBufferAlloc::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + // codes that don't require permission check + + switch(code) { + case CREATE_GRAPHIC_BUFFER: { + CHECK_INTERFACE(IGraphicBufferAlloc, data, reply); + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + PixelFormat format = data.readInt32(); + uint32_t usage = data.readInt32(); + sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage)); + reply->writeInt32(result != 0); + if (result != 0) { + reply->write(*result); + } + return NO_ERROR; + } break; + case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: { + CHECK_INTERFACE(IGraphicBufferAlloc, data, reply); + int bufIdx = data.readInt32(); + freeAllGraphicBuffersExcept(bufIdx); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index a42b49d9d9..22168244c8 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -26,7 +26,6 @@ #include <binder/IServiceManager.h> #include <ui/DisplayInfo.h> -#include <ui/GraphicBuffer.h> #include <surfaceflinger/ISurfaceComposer.h> @@ -65,6 +64,15 @@ public: return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder()); } + virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() + { + uint32_t n; + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply); + return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder()); + } + virtual sp<IMemoryHeap> getCblk() const { Parcel data, reply; @@ -170,25 +178,6 @@ public: data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY); } - - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) const { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(format); - data.writeInt32(usage); - remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER, data, - &reply); - sp<GraphicBuffer> graphicBuffer; - bool nonNull = (bool)reply.readInt32(); - if (nonNull) { - graphicBuffer = new GraphicBuffer(); - reply.read(*graphicBuffer); - } - return graphicBuffer; - } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -209,6 +198,11 @@ status_t BnSurfaceComposer::onTransact( sp<IBinder> b = createClientConnection()->asBinder(); reply->writeStrongBinder(b); } break; + case CREATE_GRAPHIC_BUFFER_ALLOC: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> b = createGraphicBufferAlloc()->asBinder(); + reply->writeStrongBinder(b); + } break; case OPEN_GLOBAL_TRANSACTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); openGlobalTransaction(); @@ -267,18 +261,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(f); reply->writeInt32(res); } break; - case CREATE_GRAPHIC_BUFFER: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - uint32_t w = data.readInt32(); - uint32_t h = data.readInt32(); - PixelFormat format = data.readInt32(); - uint32_t usage = data.readInt32(); - sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage)); - reply->writeInt32(result != 0); - if (result != 0) { - reply->write(*result); - } - } break; case TURN_ELECTRON_BEAM_OFF: { CHECK_INTERFACE(ISurfaceComposer, data, reply); int32_t mode = data.readInt32(); diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 8a021cbfc9..0c1fcf9124 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -503,12 +503,18 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const void LayerBase::setBufferCrop(const Rect& crop) { if (!crop.isEmpty()) { - mBufferCrop = crop; + if (mBufferCrop != crop) { + mBufferCrop = crop; + mFlinger->invalidateHwcGeometry(); + } } } void LayerBase::setBufferTransform(uint32_t transform) { - mBufferTransform = transform; + if (mBufferTransform != transform) { + mBufferTransform = transform; + mFlinger->invalidateHwcGeometry(); + } } void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c982ea5896..77695d73e8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -144,6 +144,11 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection() return bclient; } +sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() +{ + sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); + return gba; +} const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const { @@ -460,7 +465,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) handleTransactionLocked(transactionFlags, ditchedLayers); mLastTransactionTime = systemTime() - now; mDebugInTransaction = 0; - mHwWorkListDirty = true; + invalidateHwcGeometry(); // here the transaction has been committed } @@ -726,13 +731,18 @@ void SurfaceFlinger::handlePageFlip() mWormholeRegion = screenRegion.subtract(opaqueRegion); mVisibleRegionsDirty = false; - mHwWorkListDirty = true; + invalidateHwcGeometry(); } unlockPageFlip(currentLayers); mDirtyRegion.andSelf(screenRegion); } +void SurfaceFlinger::invalidateHwcGeometry() +{ + mHwWorkListDirty = true; +} + bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) { bool recomputeVisibleRegions = false; @@ -1586,7 +1596,7 @@ status_t SurfaceFlinger::onTransact( case 1008: // toggle use of hw composer n = data.readInt32(); mDebugDisableHWC = n ? 1 : 0; - mHwWorkListDirty = true; + invalidateHwcGeometry(); // fall-through... case 1004:{ // repaint everything Mutex::Autolock _l(mStateLock); @@ -2267,25 +2277,6 @@ sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const // --------------------------------------------------------------------------- -sp<GraphicBuffer> SurfaceFlinger::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) const { - // XXX: HACK HACK HACK!!! This should NOT be static, but it is to fix a - // race between SurfaceFlinger unref'ing the buffer and the client ref'ing - // it. - static sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); - status_t err = graphicBuffer->initCheck(); - if (err != 0) { - LOGE("createGraphicBuffer: init check failed: %d", err); - return 0; - } else if (graphicBuffer->handle == 0) { - LOGE("createGraphicBuffer: unable to create GraphicBuffer"); - return 0; - } - return graphicBuffer; -} - -// --------------------------------------------------------------------------- - Client::Client(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mNameGenerator(1) { @@ -2465,6 +2456,39 @@ status_t UserClient::setState(int32_t count, const layer_state_t* states) { // --------------------------------------------------------------------------- +GraphicBufferAlloc::GraphicBufferAlloc() {} + +GraphicBufferAlloc::~GraphicBufferAlloc() {} + +sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) { + sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); + status_t err = graphicBuffer->initCheck(); + if (err != 0) { + LOGE("createGraphicBuffer: init check failed: %d", err); + return 0; + } else if (graphicBuffer->handle == 0) { + LOGE("createGraphicBuffer: unable to create GraphicBuffer"); + return 0; + } + Mutex::Autolock _l(mLock); + mBuffers.add(graphicBuffer); + return graphicBuffer; +} + +void GraphicBufferAlloc::freeAllGraphicBuffersExcept(int bufIdx) { + Mutex::Autolock _l(mLock); + if (0 <= bufIdx && bufIdx < mBuffers.size()) { + sp<GraphicBuffer> b(mBuffers[bufIdx]); + mBuffers.clear(); + mBuffers.add(b); + } else { + mBuffers.clear(); + } +} + +// --------------------------------------------------------------------------- + GraphicPlane::GraphicPlane() : mHw(0) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 48642d4ed4..2591123da3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -34,6 +34,7 @@ #include <ui/PixelFormat.h> #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/ISurfaceComposerClient.h> +#include <surfaceflinger/IGraphicBufferAlloc.h> #include "Barrier.h" #include "Layer.h" @@ -119,6 +120,21 @@ private: sp<SurfaceFlinger> mFlinger; }; +class GraphicBufferAlloc : public BnGraphicBufferAlloc +{ +public: + GraphicBufferAlloc(); + virtual ~GraphicBufferAlloc(); + + virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage); + virtual void freeAllGraphicBuffersExcept(int bufIdx); + +private: + Vector<sp<GraphicBuffer> > mBuffers; + Mutex mLock; +}; + // --------------------------------------------------------------------------- class GraphicPlane @@ -184,6 +200,7 @@ public: // ISurfaceComposer interface virtual sp<ISurfaceComposerClient> createConnection(); virtual sp<ISurfaceComposerClient> createClientConnection(); + virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc(); virtual sp<IMemoryHeap> getCblk() const; virtual void bootFinished(); virtual void openGlobalTransaction(); @@ -208,6 +225,7 @@ public: status_t removeLayer(const sp<LayerBase>& layer); status_t addLayer(const sp<LayerBase>& layer); status_t invalidateLayerVisibility(const sp<LayerBase>& layer); + void invalidateHwcGeometry(); sp<Layer> getLayer(const sp<ISurface>& sur) const; @@ -322,8 +340,6 @@ private: status_t electronBeamOnAnimationImplLocked(); status_t renderScreenToTextureLocked(DisplayID dpy, GLuint* textureName, GLfloat* uOut, GLfloat* vOut); - sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) const; friend class FreezeLock; sp<FreezeLock> getFreezeLock() const; |