Merge "SurfaceFlinger: Fix PTS on stale buffers"
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 @@
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 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 @@
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 @@
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/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 0de5cca..ba11259 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -199,10 +199,8 @@
// un-premultiply if needed before linearization
fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
}
- fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));";
fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
- fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
if (!needs.isOpaque() && needs.isPremultiplied()) {
// and re-premultiply if needed after gamma correction
fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index df4ac2e..715b92f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1994,18 +1994,25 @@
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) {
@@ -2262,10 +2269,16 @@
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 a06d1be..74f9031 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -144,6 +144,8 @@
// 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 @@
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);