Loading include/gui/SurfaceTexture.h +13 −0 Original line number Diff line number Diff line Loading @@ -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, Loading libs/gui/SurfaceTexture.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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. Loading services/surfaceflinger/Layer.cpp +95 −67 Original line number Diff line number Diff line Loading @@ -527,31 +527,34 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFlinger->signalLayerUpdate(); } if (mSurfaceTexture->updateTexImage() < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return; 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; } // update the active buffer mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufHeight = mActiveBuffer->getHeight(); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); 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 (mCurrentTransform & Transform::ROT_90) { if (item.mTransform & Transform::ROT_90) { 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) { bool isFixedSize = scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; if (isFixedSize || (bufWidth == front.requested.w && Loading @@ -560,8 +563,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // 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; front.active = front.requested; // We also need to update the current state so that // we don't end-up overwriting the drawing state with Loading @@ -569,8 +571,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // // 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; current.active = front.active; // recompute visible region recomputeVisibleRegions = true; Loading @@ -580,7 +581,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) "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, this, bufWidth, bufHeight, item.mTransform, item.mScalingMode, front.active.w, front.active.h, front.active.crop.left, front.active.crop.top, Loading @@ -597,16 +598,42 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) 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) { // 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(); Rect crop(mSurfaceTexture->getCurrentCrop()); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) Loading @@ -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 Loading
include/gui/SurfaceTexture.h +13 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
libs/gui/SurfaceTexture.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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. Loading
services/surfaceflinger/Layer.cpp +95 −67 Original line number Diff line number Diff line Loading @@ -527,31 +527,34 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFlinger->signalLayerUpdate(); } if (mSurfaceTexture->updateTexImage() < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return; 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; } // update the active buffer mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufHeight = mActiveBuffer->getHeight(); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); 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 (mCurrentTransform & Transform::ROT_90) { if (item.mTransform & Transform::ROT_90) { 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) { bool isFixedSize = scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; if (isFixedSize || (bufWidth == front.requested.w && Loading @@ -560,8 +563,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // 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; front.active = front.requested; // We also need to update the current state so that // we don't end-up overwriting the drawing state with Loading @@ -569,8 +571,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // // 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; current.active = front.active; // recompute visible region recomputeVisibleRegions = true; Loading @@ -580,7 +581,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) "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, this, bufWidth, bufHeight, item.mTransform, item.mScalingMode, front.active.w, front.active.h, front.active.crop.left, front.active.crop.top, Loading @@ -597,16 +598,42 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) 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) { // 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(); Rect crop(mSurfaceTexture->getCurrentCrop()); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) Loading @@ -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