add the ability to reject buffers in SurfaceTexture::updateTexImage
SurfaceFlinger is using this new feature to reject buffers that
don't have the right size.
Bug: 6498869
Change-Id: I8a7250a47db6c082a357b703feb3b9d0fc8d3443
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5e527cd..d07a4b6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -527,86 +527,113 @@
mFlinger->signalLayerUpdate();
}
- if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
+ struct Reject : public SurfaceTexture::BufferRejecter {
+ Layer::State& front;
+ Layer::State& current;
+ bool& recomputeVisibleRegions;
+ Reject(Layer::State& front, Layer::State& current,
+ bool& recomputeVisibleRegions)
+ : front(front), current(current),
+ recomputeVisibleRegions(recomputeVisibleRegions) {
+ }
+
+ virtual bool reject(const sp<GraphicBuffer>& buf,
+ const BufferQueue::BufferItem& item) {
+ if (buf == NULL) {
+ return false;
+ }
+
+ uint32_t bufWidth = buf->getWidth();
+ uint32_t bufHeight = buf->getHeight();
+
+ // check that we received a buffer of the right size
+ // (Take the buffer's orientation into account)
+ if (item.mTransform & Transform::ROT_90) {
+ swap(bufWidth, bufHeight);
+ }
+
+
+ bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ if (front.active != front.requested) {
+
+ if (isFixedSize ||
+ (bufWidth == front.requested.w &&
+ bufHeight == front.requested.h))
+ {
+ // Here we pretend the transaction happened by updating the
+ // current and drawing states. Drawing state is only accessed
+ // in this thread, no need to have it locked
+ front.active = front.requested;
+
+ // We also need to update the current state so that
+ // we don't end-up overwriting the drawing state with
+ // this stale current state during the next transaction
+ //
+ // NOTE: We don't need to hold the transaction lock here
+ // because State::active is only accessed from this thread.
+ current.active = front.active;
+
+ // recompute visible region
+ recomputeVisibleRegions = true;
+ }
+
+ ALOGD_IF(DEBUG_RESIZE,
+ "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+ " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+ " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+ this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
+ front.active.w, front.active.h,
+ front.active.crop.left,
+ front.active.crop.top,
+ front.active.crop.right,
+ front.active.crop.bottom,
+ front.active.crop.getWidth(),
+ front.active.crop.getHeight(),
+ front.requested.w, front.requested.h,
+ front.requested.crop.left,
+ front.requested.crop.top,
+ front.requested.crop.right,
+ front.requested.crop.bottom,
+ front.requested.crop.getWidth(),
+ front.requested.crop.getHeight());
+ }
+
+ if (!isFixedSize) {
+ if (front.active.w != bufWidth ||
+ front.active.h != bufHeight) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+
+ Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
+
+ if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
return;
}
+
// update the active buffer
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
+ mFrameLatencyNeeded = true;
+ if (oldActiveBuffer == NULL && mActiveBuffer != NULL) {
+ // the first time we receive a buffer, we need to trigger a
+ // geometry invalidation.
+ mFlinger->invalidateHwcGeometry();
+ }
+
uint32_t bufWidth = mActiveBuffer->getWidth();
uint32_t bufHeight = mActiveBuffer->getHeight();
- const uint32_t transform(mSurfaceTexture->getCurrentTransform());
- const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
-
- // check that we received a buffer of the right size
- // (Take the buffer's orientation into account)
- if (mCurrentTransform & Transform::ROT_90) {
- swap(bufWidth, bufHeight);
- }
-
- // update the layer size if needed
- const Layer::State& front(drawingState());
-
- if (front.active != front.requested) {
- bool isFixedSize = scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-
- if (isFixedSize ||
- (bufWidth == front.requested.w &&
- bufHeight == front.requested.h))
- {
- // Here we pretend the transaction happened by updating the
- // current and drawing states. Drawing state is only accessed
- // in this thread, no need to have it locked
- Layer::State& editFront(mDrawingState);
- editFront.active = front.requested;
-
- // We also need to update the current state so that
- // we don't end-up overwriting the drawing state with
- // this stale current state during the next transaction
- //
- // NOTE: We don't need to hold the transaction lock here
- // because State::active is only accessed from this thread.
- Layer::State& editCurrent(currentState());
- editCurrent.active = front.active;
-
- // recompute visible region
- recomputeVisibleRegions = true;
- }
-
- ALOGD_IF(DEBUG_RESIZE,
- "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
- " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
- this, bufWidth, bufHeight, transform, scalingMode,
- front.active.w, front.active.h,
- front.active.crop.left,
- front.active.crop.top,
- front.active.crop.right,
- front.active.crop.bottom,
- front.active.crop.getWidth(),
- front.active.crop.getHeight(),
- front.requested.w, front.requested.h,
- front.requested.crop.left,
- front.requested.crop.top,
- front.requested.crop.right,
- front.requested.crop.bottom,
- front.requested.crop.getWidth(),
- front.requested.crop.getHeight());
- }
-
- mFrameLatencyNeeded = true;
-
- if (oldActiveBuffer == NULL && mActiveBuffer != NULL) {
- // the first time we receive a buffer, we need to trigger a
- // geometry invalidation.
- mFlinger->invalidateHwcGeometry();
- }
-
Rect crop(mSurfaceTexture->getCurrentCrop());
+ const uint32_t transform(mSurfaceTexture->getCurrentTransform());
+ const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
if ((crop != mCurrentCrop) ||
(transform != mCurrentTransform) ||
(scalingMode != mCurrentScalingMode))
@@ -630,6 +657,7 @@
}
// FIXME: mPostedDirtyRegion = dirty & bounds
+ const Layer::State& front(drawingState());
mPostedDirtyRegion.set(front.active.w, front.active.h);
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);