* commit '584fcb3218e07d7b4cc0aeaef41faa4e891b45a4': add the ability to reject buffers in SurfaceTexture::updateTexImage
This commit is contained in:
commit
2466e402a0
@ -236,6 +236,19 @@ protected:
|
||||
static bool isExternalFormat(uint32_t format);
|
||||
|
||||
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.
|
||||
EGLImageKHR createImage(EGLDisplay dpy,
|
||||
|
@ -176,6 +176,10 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
|
||||
}
|
||||
|
||||
status_t SurfaceTexture::updateTexImage() {
|
||||
return SurfaceTexture::updateTexImage(NULL);
|
||||
}
|
||||
|
||||
status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
|
||||
ATRACE_CALL();
|
||||
ST_LOGV("updateTexImage");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
@ -228,6 +232,16 @@ status_t SurfaceTexture::updateTexImage() {
|
||||
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
|
||||
// item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
|
||||
// detaching from a context but the buffer has not been re-allocated.
|
||||
|
@ -527,86 +527,113 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
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 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
Loading…
Reference in New Issue
Block a user