Merge "better fix for [2420565] Surface.lockCanvas() updates the dirty region too often" into kraken

This commit is contained in:
Mathias Agopian
2010-04-21 22:27:22 -07:00
committed by Android (Google) Code Review
6 changed files with 45 additions and 39 deletions

View File

@@ -324,7 +324,7 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
SkRegion clipReg; SkRegion clipReg;
if (dirtyRegion.isRect()) { // very common case if (dirtyRegion.isRect()) { // very common case
const Rect& b(dirtyRegion.getBounds()); const Rect b(dirtyRegion.getBounds());
clipReg.setRect(b.left, b.top, b.right, b.bottom); clipReg.setRect(b.left, b.top, b.right, b.bottom);
} else { } else {
size_t count; size_t count;

View File

@@ -250,7 +250,7 @@ private:
sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mLockedBuffer;
sp<GraphicBuffer> mPostedBuffer; sp<GraphicBuffer> mPostedBuffer;
mutable Region mOldDirtyRegion; mutable Region mOldDirtyRegion;
bool mNeedFullUpdate; bool mReserved;
// query() must be called from dequeueBuffer() thread // query() must be called from dequeueBuffer() thread
uint32_t mWidth; uint32_t mWidth;

View File

@@ -540,9 +540,15 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
mFlinger->signalEvent(); mFlinger->signalEvent();
} }
if (!mPostedDirtyRegion.isEmpty()) { /* a buffer was posted, so we need to call reloadTexture(), which
reloadTexture( mPostedDirtyRegion ); * will update our internal data structures (eg: EGLImageKHR or
} * texture names). we need to do this even if mPostedDirtyRegion is
* empty -- it's orthogonal to the fact that a new buffer was posted,
* for instance, a degenerate case could be that the user did an empty
* update but repainted the buffer with appropriate content (after a
* resize for instance).
*/
reloadTexture( mPostedDirtyRegion );
} }
void Layer::unlockPageFlip( void Layer::unlockPageFlip(

View File

@@ -54,7 +54,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
mOrientation(0), mOrientation(0),
mLeft(0), mTop(0), mLeft(0), mTop(0),
mTransactionFlags(0), mTransactionFlags(0),
mPremultipliedAlpha(true), mDebug(false), mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
mInvalidate(0) mInvalidate(0)
{ {
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());

View File

@@ -84,10 +84,14 @@ status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
if (uint32_t(buffer) >= NUM_BUFFER_MAX) if (uint32_t(buffer) >= NUM_BUFFER_MAX)
return BAD_INDEX; return BAD_INDEX;
// in the current implementation we only send a single rectangle FlatRegion& reg(buffers[buffer].dirtyRegion);
if (dirty.isEmpty()) {
reg.count = 0;
return NO_ERROR;
}
size_t count; size_t count;
Rect const* r = dirty.getArray(&count); Rect const* r = dirty.getArray(&count);
FlatRegion& reg(buffers[buffer].dirtyRegion);
if (count > FlatRegion::NUM_RECT_MAX) { if (count > FlatRegion::NUM_RECT_MAX) {
const Rect bounds(dirty.getBounds()); const Rect bounds(dirty.getBounds());
reg.count = 1; reg.count = 1;

View File

@@ -17,8 +17,6 @@
#define LOG_TAG "Surface" #define LOG_TAG "Surface"
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -28,8 +26,6 @@
#include <utils/CallStack.h> #include <utils/CallStack.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <pixelflinger/pixelflinger.h>
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <binder/IMemory.h> #include <binder/IMemory.h>
@@ -55,6 +51,8 @@ static status_t copyBlt(
const sp<GraphicBuffer>& src, const sp<GraphicBuffer>& src,
const Region& reg) const Region& reg)
{ {
// src and dst with, height and format must be identical. no verification
// is done here.
status_t err; status_t err;
uint8_t const * src_bits = NULL; uint8_t const * src_bits = NULL;
err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
@@ -67,7 +65,6 @@ static status_t copyBlt(
Region::const_iterator head(reg.begin()); Region::const_iterator head(reg.begin());
Region::const_iterator tail(reg.end()); Region::const_iterator tail(reg.end());
if (head != tail && src_bits && dst_bits) { if (head != tail && src_bits && dst_bits) {
// NOTE: dst and src must be the same format
const size_t bpp = bytesPerPixel(src->format); const size_t bpp = bytesPerPixel(src->format);
const size_t dbpr = dst->stride * bpp; const size_t dbpr = dst->stride * bpp;
const size_t sbpr = src->stride * bpp; const size_t sbpr = src->stride * bpp;
@@ -354,7 +351,6 @@ void Surface::init()
// be default we request a hardware surface // be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER; mUsage = GRALLOC_USAGE_HW_RENDER;
mConnected = 0; mConnected = 0;
mNeedFullUpdate = false;
} }
Surface::~Surface() Surface::~Surface()
@@ -734,37 +730,38 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
backBuffer->getIndex(), strerror(-err)); backBuffer->getIndex(), strerror(-err));
if (err == NO_ERROR) { if (err == NO_ERROR) {
// we handle copy-back here...
const Rect bounds(backBuffer->width, backBuffer->height); const Rect bounds(backBuffer->width, backBuffer->height);
Region scratch(bounds); const Region boundsRegion(bounds);
Region scratch(boundsRegion);
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
newDirtyRegion &= boundsRegion;
const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); // figure out if we can copy the frontbuffer back
if (mNeedFullUpdate) {
mNeedFullUpdate = false;
Region uninitialized(bounds);
uninitialized.subtractSelf(copyback | newDirtyRegion);
// reset newDirtyRegion to bounds when a buffer is reallocated
// and we have nothing to copy back to it
if (!uninitialized.isEmpty())
newDirtyRegion.set(bounds);
}
newDirtyRegion.andSelf(bounds);
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
if (frontBuffer != 0 && const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width && backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height && backBuffer->height == frontBuffer->height &&
!(mFlags & ISurfaceComposer::eDestroyBackbuffer)) backBuffer->format == frontBuffer->format &&
{ !(mFlags & ISurfaceComposer::eDestroyBackbuffer));
if (!copyback.isEmpty()) {
// copy front to back // the dirty region we report to surfaceflinger is the one
// given by the user (as opposed to the one *we* return to the
// user).
mDirtyRegion = newDirtyRegion;
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback); copyBlt(backBuffer, frontBuffer, copyback);
} } else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion = boundsRegion;
} }
mDirtyRegion = newDirtyRegion; // keep track of the are of the buffer that is "clean"
// (ie: that will be redrawn)
mOldDirtyRegion = newDirtyRegion; mOldDirtyRegion = newDirtyRegion;
void* vaddr; void* vaddr;
@@ -843,7 +840,6 @@ status_t Surface::getBufferLocked(int index, int usage)
if (err == NO_ERROR) { if (err == NO_ERROR) {
currentBuffer = buffer; currentBuffer = buffer;
currentBuffer->setIndex(index); currentBuffer->setIndex(index);
mNeedFullUpdate = true;
} }
} else { } else {
err = err<0 ? err : NO_MEMORY; err = err<0 ? err : NO_MEMORY;