am 2c8207e9: add the ability to reject buffers in SurfaceTexture::updateTexImage

* commit '2c8207e9627fe6c7a90e31fae8d71ae49df56845':
  add the ability to reject buffers in SurfaceTexture::updateTexImage
This commit is contained in:
Mathias Agopian 2012-05-29 19:50:58 -07:00 committed by Android Git Automerger
commit 584fcb3218
3 changed files with 123 additions and 68 deletions

View File

@ -236,6 +236,19 @@ protected:
static bool isExternalFormat(uint32_t format); static bool isExternalFormat(uint32_t format);
private: private:
// this version of updateTexImage() takes a functor used to reject or not
// the newly acquired buffer.
// this API is TEMPORARY and intended to be used by SurfaceFlinger only,
// which is why class Layer is made a friend of SurfaceTexture below.
class BufferRejecter {
friend class SurfaceTexture;
virtual bool reject(const sp<GraphicBuffer>& buf,
const BufferQueue::BufferItem& item) = 0;
protected:
virtual ~BufferRejecter() { }
};
friend class Layer;
status_t updateTexImage(BufferRejecter* rejecter);
// createImage creates a new EGLImage from a GraphicBuffer. // createImage creates a new EGLImage from a GraphicBuffer.
EGLImageKHR createImage(EGLDisplay dpy, EGLImageKHR createImage(EGLDisplay dpy,

View File

@ -176,6 +176,10 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
} }
status_t SurfaceTexture::updateTexImage() { status_t SurfaceTexture::updateTexImage() {
return SurfaceTexture::updateTexImage(NULL);
}
status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
ATRACE_CALL(); ATRACE_CALL();
ST_LOGV("updateTexImage"); ST_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
@ -228,6 +232,16 @@ status_t SurfaceTexture::updateTexImage() {
mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer; mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
} }
// we call the rejecter here, in case the caller has a reason to
// not accept this buffer. this is used by SurfaceFlinger to
// reject buffers which have the wrong size
if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) {
mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
glBindTexture(mTexTarget, mTexName);
return NO_ERROR;
}
// Update the GL texture object. We may have to do this even when // Update the GL texture object. We may have to do this even when
// item.mGraphicBuffer == NULL, if we destroyed the EGLImage when // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
// detaching from a context but the buffer has not been re-allocated. // detaching from a context but the buffer has not been re-allocated.

View File

@ -527,31 +527,34 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
mFlinger->signalLayerUpdate(); mFlinger->signalLayerUpdate();
} }
if (mSurfaceTexture->updateTexImage() < NO_ERROR) { struct Reject : public SurfaceTexture::BufferRejecter {
// something happened! Layer::State& front;
recomputeVisibleRegions = true; Layer::State& current;
return; bool& recomputeVisibleRegions;
Reject(Layer::State& front, Layer::State& current,
bool& recomputeVisibleRegions)
: front(front), current(current),
recomputeVisibleRegions(recomputeVisibleRegions) {
} }
// update the active buffer virtual bool reject(const sp<GraphicBuffer>& buf,
mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); const BufferQueue::BufferItem& item) {
if (buf == NULL) {
return false;
}
uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufWidth = buf->getWidth();
uint32_t bufHeight = mActiveBuffer->getHeight(); uint32_t bufHeight = buf->getHeight();
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
// check that we received a buffer of the right size // check that we received a buffer of the right size
// (Take the buffer's orientation into account) // (Take the buffer's orientation into account)
if (mCurrentTransform & Transform::ROT_90) { if (item.mTransform & Transform::ROT_90) {
swap(bufWidth, bufHeight); swap(bufWidth, bufHeight);
} }
// update the layer size if needed
const Layer::State& front(drawingState());
bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (front.active != front.requested) { if (front.active != front.requested) {
bool isFixedSize = scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (isFixedSize || if (isFixedSize ||
(bufWidth == front.requested.w && (bufWidth == front.requested.w &&
@ -560,8 +563,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// Here we pretend the transaction happened by updating the // Here we pretend the transaction happened by updating the
// current and drawing states. Drawing state is only accessed // current and drawing states. Drawing state is only accessed
// in this thread, no need to have it locked // in this thread, no need to have it locked
Layer::State& editFront(mDrawingState); front.active = front.requested;
editFront.active = front.requested;
// We also need to update the current state so that // We also need to update the current state so that
// we don't end-up overwriting the drawing state with // we don't end-up overwriting the drawing state with
@ -569,8 +571,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// //
// NOTE: We don't need to hold the transaction lock here // NOTE: We don't need to hold the transaction lock here
// because State::active is only accessed from this thread. // because State::active is only accessed from this thread.
Layer::State& editCurrent(currentState()); current.active = front.active;
editCurrent.active = front.active;
// recompute visible region // recompute visible region
recomputeVisibleRegions = true; recomputeVisibleRegions = true;
@ -580,7 +581,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
"lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n" "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\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", " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
this, bufWidth, bufHeight, transform, scalingMode, this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
front.active.w, front.active.h, front.active.w, front.active.h,
front.active.crop.left, front.active.crop.left,
front.active.crop.top, front.active.crop.top,
@ -597,16 +598,42 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
front.requested.crop.getHeight()); front.requested.crop.getHeight());
} }
mFrameLatencyNeeded = true; 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) { if (oldActiveBuffer == NULL && mActiveBuffer != NULL) {
// the first time we receive a buffer, we need to trigger a // the first time we receive a buffer, we need to trigger a
// geometry invalidation. // geometry invalidation.
mFlinger->invalidateHwcGeometry(); mFlinger->invalidateHwcGeometry();
} }
uint32_t bufWidth = mActiveBuffer->getWidth();
uint32_t bufHeight = mActiveBuffer->getHeight();
Rect crop(mSurfaceTexture->getCurrentCrop()); Rect crop(mSurfaceTexture->getCurrentCrop());
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
if ((crop != mCurrentCrop) || if ((crop != mCurrentCrop) ||
(transform != mCurrentTransform) || (transform != mCurrentTransform) ||
(scalingMode != mCurrentScalingMode)) (scalingMode != mCurrentScalingMode))
@ -630,6 +657,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
} }
// FIXME: mPostedDirtyRegion = dirty & bounds // FIXME: mPostedDirtyRegion = dirty & bounds
const Layer::State& front(drawingState());
mPostedDirtyRegion.set(front.active.w, front.active.h); mPostedDirtyRegion.set(front.active.w, front.active.h);
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);