diff options
-rw-r--r-- | libs/gui/Surface.cpp | 6 | ||||
-rw-r--r-- | libs/ui/GraphicBufferMapper.cpp | 15 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Mesh.cpp | 30 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 29 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 4 |
5 files changed, 69 insertions, 15 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 5d81f10..35aa7c7 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -267,6 +267,9 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, Mutex::Autolock lock(mMutex); int i = getSlotFromBufferLocked(buffer); if (i < 0) { + if (fenceFd >= 0) { + close(fenceFd); + } return i; } sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); @@ -308,6 +311,9 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { } int i = getSlotFromBufferLocked(buffer); if (i < 0) { + if (fenceFd >= 0) { + close(fenceFd); + } return i; } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 31bfb2d..90a1c11 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -131,8 +131,10 @@ status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr, fenceFd); } else { - sync_wait(fenceFd, -1); - close(fenceFd); + if (fenceFd >= 0) { + sync_wait(fenceFd, -1); + close(fenceFd); + } err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); @@ -154,12 +156,17 @@ status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), ycbcr, fenceFd); } else if (mAllocMod->lock_ycbcr != NULL) { - sync_wait(fenceFd, -1); - close(fenceFd); + if (fenceFd >= 0) { + sync_wait(fenceFd, -1); + close(fenceFd); + } err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), ycbcr); } else { + if (fenceFd >= 0) { + close(fenceFd); + } return -EINVAL; // do not log failure } diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp index 3f50cb0..ffd9be2 100644 --- a/services/surfaceflinger/RenderEngine/Mesh.cpp +++ b/services/surfaceflinger/RenderEngine/Mesh.cpp @@ -16,14 +16,40 @@ #include "Mesh.h" +#include <utils/Log.h> + namespace android { Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize) : mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize), mPrimitive(primitive) { - mVertices = new float[(vertexSize + texCoordSize) * vertexCount]; - mStride = mVertexSize + mTexCoordsSize; + if (vertexCount == 0) { + mVertices = new float[1]; + mVertices[0] = 0.0f; + mStride = 0; + return; + } + + size_t stride = vertexSize + texCoordSize; + size_t remainder = (stride * vertexCount) / vertexCount; + // Since all of the input parameters are unsigned, if stride is less than + // either vertexSize or texCoordSize, it must have overflowed. remainder + // will be equal to stride as long as stride * vertexCount doesn't overflow. + if ((stride < vertexSize) || (remainder != stride)) { + ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize, + texCoordSize); + mVertices = new float[1]; + mVertices[0] = 0.0f; + mVertexCount = 0; + mVertexSize = 0; + mTexCoordsSize = 0; + mStride = 0; + return; + } + + mVertices = new float[stride * vertexCount]; + mStride = stride; } Mesh::~Mesh() { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1419557..0d57ae5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2018,18 +2018,25 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Regio engine.fillRegionWithColor(region, height, 0, 0, 0, 0); } -void SurfaceFlinger::addClientLayer(const sp<Client>& client, +status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc) { + // add this layer to the current state list + { + Mutex::Autolock _l(mStateLock); + if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) { + return NO_MEMORY; + } + mCurrentState.layersSortedByZ.add(lbc); + mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); + } + // attach this layer to the client client->attachLayer(handle, lbc); - // add this layer to the current state list - Mutex::Autolock _l(mStateLock); - mCurrentState.layersSortedByZ.add(lbc); - mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); + return NO_ERROR; } status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { @@ -2286,10 +2293,16 @@ status_t SurfaceFlinger::createLayer( break; } - if (result == NO_ERROR) { - addClientLayer(client, *handle, *gbp, layer); - setTransactionFlags(eTransactionNeeded); + if (result != NO_ERROR) { + return result; } + + result = addClientLayer(client, *handle, *gbp, layer); + if (result != NO_ERROR) { + return result; + } + + setTransactionFlags(eTransactionNeeded); return result; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d2654d4..3759a92 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -144,6 +144,8 @@ private: // every half hour. enum { LOG_FRAME_STATS_PERIOD = 30*60*60 }; + static const size_t MAX_LAYERS = 4096; + // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); @@ -305,7 +307,7 @@ private: status_t removeLayer(const sp<Layer>& layer); // add a layer to SurfaceFlinger - void addClientLayer(const sp<Client>& client, + status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc); |