am 057a561a: am 57a9f5a0: am fd5f41be: Merge "libgui: Pass surface damage through BufferQueue"
* commit '057a561afbf30ede99b5ec627deec7ee11701f6d': libgui: Pass surface damage through BufferQueue
This commit is contained in:
commit
2992fcd0b2
|
@ -21,6 +21,7 @@
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
|
#include <ui/Region.h>
|
||||||
|
|
||||||
#include <system/graphics.h>
|
#include <system/graphics.h>
|
||||||
|
|
||||||
|
@ -106,6 +107,10 @@ class BufferItem : public Flattenable<BufferItem> {
|
||||||
// Indicates this buffer must be transformed by the inverse transform of the screen
|
// Indicates this buffer must be transformed by the inverse transform of the screen
|
||||||
// it is displayed onto. This is applied after mTransform.
|
// it is displayed onto. This is applied after mTransform.
|
||||||
bool mTransformToDisplayInverse;
|
bool mTransformToDisplayInverse;
|
||||||
|
|
||||||
|
// Describes the portion of the surface that has been modified since the
|
||||||
|
// previous frame
|
||||||
|
Region mSurfaceDamage;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <ui/Fence.h>
|
#include <ui/Fence.h>
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
|
#include <ui/Region.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -281,7 +282,7 @@ public:
|
||||||
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp),
|
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp),
|
||||||
dataSpace(dataSpace), crop(crop), scalingMode(scalingMode),
|
dataSpace(dataSpace), crop(crop), scalingMode(scalingMode),
|
||||||
transform(transform), stickyTransform(sticky),
|
transform(transform), stickyTransform(sticky),
|
||||||
async(async), fence(fence) { }
|
async(async), fence(fence), surfaceDamage() { }
|
||||||
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
|
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
|
||||||
android_dataspace* outDataSpace,
|
android_dataspace* outDataSpace,
|
||||||
Rect* outCrop, int* outScalingMode,
|
Rect* outCrop, int* outScalingMode,
|
||||||
|
@ -306,6 +307,9 @@ public:
|
||||||
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
|
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
|
||||||
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
|
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
|
||||||
|
|
||||||
|
const Region& getSurfaceDamage() const { return surfaceDamage; }
|
||||||
|
void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
int isAutoTimestamp;
|
int isAutoTimestamp;
|
||||||
|
@ -316,6 +320,7 @@ public:
|
||||||
uint32_t stickyTransform;
|
uint32_t stickyTransform;
|
||||||
int async;
|
int async;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
|
Region surfaceDamage;
|
||||||
};
|
};
|
||||||
|
|
||||||
// QueueBufferOutput must be a POD structure
|
// QueueBufferOutput must be a POD structure
|
||||||
|
|
|
@ -147,6 +147,7 @@ private:
|
||||||
int dispatchUnlockAndPost(va_list args);
|
int dispatchUnlockAndPost(va_list args);
|
||||||
int dispatchSetSidebandStream(va_list args);
|
int dispatchSetSidebandStream(va_list args);
|
||||||
int dispatchSetBuffersDataSpace(va_list args);
|
int dispatchSetBuffersDataSpace(va_list args);
|
||||||
|
int dispatchSetSurfaceDamage(va_list args);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
|
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
|
||||||
|
@ -171,6 +172,7 @@ protected:
|
||||||
virtual int setBuffersDataSpace(android_dataspace dataSpace);
|
virtual int setBuffersDataSpace(android_dataspace dataSpace);
|
||||||
virtual int setCrop(Rect const* rect);
|
virtual int setCrop(Rect const* rect);
|
||||||
virtual int setUsage(uint32_t reqUsage);
|
virtual int setUsage(uint32_t reqUsage);
|
||||||
|
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
|
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
|
||||||
|
@ -296,7 +298,12 @@ private:
|
||||||
sp<GraphicBuffer> mPostedBuffer;
|
sp<GraphicBuffer> mPostedBuffer;
|
||||||
bool mConnectedToCpu;
|
bool mConnectedToCpu;
|
||||||
|
|
||||||
// must be accessed from lock/unlock thread only
|
// In the lock/unlock context, this reflects the region that the producer
|
||||||
|
// wished to update and whether the Surface was able to copy the previous
|
||||||
|
// buffer back to allow a partial update.
|
||||||
|
//
|
||||||
|
// In the dequeue/queue context, this reflects the surface damage (the
|
||||||
|
// damage since the last frame) passed in by the producer.
|
||||||
Region mDirtyRegion;
|
Region mDirtyRegion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ class Rect : public ARect, public LightFlattenablePod<Rect>
|
||||||
public:
|
public:
|
||||||
typedef ARect::value_type value_type;
|
typedef ARect::value_type value_type;
|
||||||
|
|
||||||
|
static const Rect INVALID_RECT;
|
||||||
|
|
||||||
// we don't provide copy-ctor and operator= on purpose
|
// we don't provide copy-ctor and operator= on purpose
|
||||||
// because we want the compiler generated versions
|
// because we want the compiler generated versions
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ class String8;
|
||||||
class Region : public LightFlattenable<Region>
|
class Region : public LightFlattenable<Region>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const Region INVALID_REGION;
|
||||||
|
|
||||||
Region();
|
Region();
|
||||||
Region(const Region& rhs);
|
Region(const Region& rhs);
|
||||||
explicit Region(const Rect& rhs);
|
explicit Region(const Rect& rhs);
|
||||||
|
|
|
@ -64,6 +64,8 @@ size_t BufferItem::getFlattenedSize() const {
|
||||||
c += mFence->getFlattenedSize();
|
c += mFence->getFlattenedSize();
|
||||||
FlattenableUtils::align<4>(c);
|
FlattenableUtils::align<4>(c);
|
||||||
}
|
}
|
||||||
|
c += mSurfaceDamage.getFlattenedSize();
|
||||||
|
FlattenableUtils::align<4>(c);
|
||||||
return sizeof(int32_t) + c + getPodSize();
|
return sizeof(int32_t) + c + getPodSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +107,9 @@ status_t BufferItem::flatten(
|
||||||
size -= FlattenableUtils::align<4>(buffer);
|
size -= FlattenableUtils::align<4>(buffer);
|
||||||
flags |= 2;
|
flags |= 2;
|
||||||
}
|
}
|
||||||
|
status_t err = mSurfaceDamage.flatten(buffer, size);
|
||||||
|
if (err) return err;
|
||||||
|
size -= FlattenableUtils::align<4>(buffer);
|
||||||
|
|
||||||
// check we have enough space (in case flattening the fence/graphicbuffer lied to us)
|
// check we have enough space (in case flattening the fence/graphicbuffer lied to us)
|
||||||
if (size < getPodSize()) {
|
if (size < getPodSize()) {
|
||||||
|
@ -148,6 +153,9 @@ status_t BufferItem::unflatten(
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
size -= FlattenableUtils::align<4>(buffer);
|
size -= FlattenableUtils::align<4>(buffer);
|
||||||
}
|
}
|
||||||
|
status_t err = mSurfaceDamage.unflatten(buffer, size);
|
||||||
|
if (err) return err;
|
||||||
|
size -= FlattenableUtils::align<4>(buffer);
|
||||||
|
|
||||||
// check we have enough space
|
// check we have enough space
|
||||||
if (size < getPodSize()) {
|
if (size < getPodSize()) {
|
||||||
|
|
|
@ -525,6 +525,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
|
input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
|
||||||
&transform, &async, &fence, &stickyTransform);
|
&transform, &async, &fence, &stickyTransform);
|
||||||
|
Region surfaceDamage = input.getSurfaceDamage();
|
||||||
|
|
||||||
if (fence == NULL) {
|
if (fence == NULL) {
|
||||||
BQ_LOGE("queueBuffer: fence is NULL");
|
BQ_LOGE("queueBuffer: fence is NULL");
|
||||||
|
@ -621,6 +622,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
|
||||||
item.mSlot = slot;
|
item.mSlot = slot;
|
||||||
item.mFence = fence;
|
item.mFence = fence;
|
||||||
item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
|
item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
|
||||||
|
item.mSurfaceDamage = surfaceDamage;
|
||||||
|
|
||||||
mStickyTransform = stickyTransform;
|
mStickyTransform = stickyTransform;
|
||||||
|
|
||||||
|
|
|
@ -446,7 +446,8 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
|
||||||
+ sizeof(transform)
|
+ sizeof(transform)
|
||||||
+ sizeof(stickyTransform)
|
+ sizeof(stickyTransform)
|
||||||
+ sizeof(async)
|
+ sizeof(async)
|
||||||
+ fence->getFlattenedSize();
|
+ fence->getFlattenedSize()
|
||||||
|
+ surfaceDamage.getFlattenedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
|
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
|
||||||
|
@ -467,7 +468,11 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
|
||||||
FlattenableUtils::write(buffer, size, transform);
|
FlattenableUtils::write(buffer, size, transform);
|
||||||
FlattenableUtils::write(buffer, size, stickyTransform);
|
FlattenableUtils::write(buffer, size, stickyTransform);
|
||||||
FlattenableUtils::write(buffer, size, async);
|
FlattenableUtils::write(buffer, size, async);
|
||||||
return fence->flatten(buffer, size, fds, count);
|
status_t result = fence->flatten(buffer, size, fds, count);
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return surfaceDamage.flatten(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
|
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
|
||||||
|
@ -497,7 +502,11 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
|
||||||
FlattenableUtils::read(buffer, size, async);
|
FlattenableUtils::read(buffer, size, async);
|
||||||
|
|
||||||
fence = new Fence();
|
fence = new Fence();
|
||||||
return fence->unflatten(buffer, size, fds, count);
|
status_t result = fence->unflatten(buffer, size, fds, count);
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return surfaceDamage.unflatten(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <utils/NativeHandle.h>
|
#include <utils/NativeHandle.h>
|
||||||
|
|
||||||
#include <ui/Fence.h>
|
#include <ui/Fence.h>
|
||||||
|
#include <ui/Region.h>
|
||||||
|
|
||||||
#include <gui/IProducerListener.h>
|
#include <gui/IProducerListener.h>
|
||||||
#include <gui/ISurfaceComposer.h>
|
#include <gui/ISurfaceComposer.h>
|
||||||
|
@ -320,6 +321,25 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
|
||||||
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
|
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
|
||||||
mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
|
mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
|
||||||
mSwapIntervalZero, fence, mStickyTransform);
|
mSwapIntervalZero, fence, mStickyTransform);
|
||||||
|
|
||||||
|
if (mDirtyRegion.bounds() == Rect::INVALID_RECT) {
|
||||||
|
input.setSurfaceDamage(Region::INVALID_REGION);
|
||||||
|
} else {
|
||||||
|
// The surface damage was specified using the OpenGL ES convention of
|
||||||
|
// the origin being in the bottom-left corner. Here we flip to the
|
||||||
|
// convention that the rest of the system uses (top-left corner) by
|
||||||
|
// subtracting all top/bottom coordinates from the buffer height.
|
||||||
|
Region flippedRegion;
|
||||||
|
for (auto rect : mDirtyRegion) {
|
||||||
|
auto top = buffer->height - rect.bottom;
|
||||||
|
auto bottom = buffer->height - rect.top;
|
||||||
|
Rect flippedRect{rect.left, top, rect.right, bottom};
|
||||||
|
flippedRegion.orSelf(flippedRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setSurfaceDamage(flippedRegion);
|
||||||
|
}
|
||||||
|
|
||||||
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
|
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
||||||
|
@ -336,6 +356,9 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
|
||||||
|
|
||||||
mConsumerRunningBehind = (numPendingBuffers >= 2);
|
mConsumerRunningBehind = (numPendingBuffers >= 2);
|
||||||
|
|
||||||
|
// Clear surface damage back to full-buffer
|
||||||
|
mDirtyRegion = Region::INVALID_REGION;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +476,9 @@ int Surface::perform(int operation, va_list args)
|
||||||
case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
|
case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
|
||||||
res = dispatchSetBuffersDataSpace(args);
|
res = dispatchSetBuffersDataSpace(args);
|
||||||
break;
|
break;
|
||||||
|
case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
|
||||||
|
res = dispatchSetSurfaceDamage(args);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
res = NAME_NOT_FOUND;
|
res = NAME_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
|
@ -556,6 +582,13 @@ int Surface::dispatchSetBuffersDataSpace(va_list args) {
|
||||||
return setBuffersDataSpace(dataspace);
|
return setBuffersDataSpace(dataspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Surface::dispatchSetSurfaceDamage(va_list args) {
|
||||||
|
android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
|
||||||
|
size_t numRects = va_arg(args, size_t);
|
||||||
|
setSurfaceDamage(rects, numRects);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
int Surface::connect(int api) {
|
int Surface::connect(int api) {
|
||||||
static sp<IProducerListener> listener = new DummyProducerListener();
|
static sp<IProducerListener> listener = new DummyProducerListener();
|
||||||
return connect(api, listener);
|
return connect(api, listener);
|
||||||
|
@ -582,7 +615,13 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) {
|
||||||
}
|
}
|
||||||
if (!err && api == NATIVE_WINDOW_API_CPU) {
|
if (!err && api == NATIVE_WINDOW_API_CPU) {
|
||||||
mConnectedToCpu = true;
|
mConnectedToCpu = true;
|
||||||
|
// Clear the dirty region in case we're switching from a non-CPU API
|
||||||
|
mDirtyRegion.clear();
|
||||||
|
} else if (!err) {
|
||||||
|
// Initialize the dirty region for tracking surface damage
|
||||||
|
mDirtyRegion = Region::INVALID_REGION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,6 +839,27 @@ void Surface::freeAllBuffers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
|
||||||
|
ATRACE_CALL();
|
||||||
|
ALOGV("Surface::setSurfaceDamage");
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (numRects == 0) {
|
||||||
|
mDirtyRegion = Region::INVALID_REGION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDirtyRegion.clear();
|
||||||
|
for (size_t r = 0; r < numRects; ++r) {
|
||||||
|
// We intentionally flip top and bottom here, since because they're
|
||||||
|
// specified with a bottom-left origin, top > bottom, which fails
|
||||||
|
// validation in the Region class. We will fix this up when we flip to a
|
||||||
|
// top-left origin in queueBuffer.
|
||||||
|
Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
|
||||||
|
mDirtyRegion.orSelf(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// the lock/unlock APIs must be used from the same thread
|
// the lock/unlock APIs must be used from the same thread
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
const Rect Rect::INVALID_RECT{0, 0, -1, -1};
|
||||||
|
|
||||||
static inline int32_t min(int32_t a, int32_t b) {
|
static inline int32_t min(int32_t a, int32_t b) {
|
||||||
return (a < b) ? a : b;
|
return (a < b) ? a : b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ enum {
|
||||||
direction_RTL
|
direction_RTL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Region Region::INVALID_REGION(Rect::INVALID_RECT);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
Region::Region() {
|
Region::Region() {
|
||||||
|
@ -517,9 +519,13 @@ bool Region::validate(const Region& reg, const char* name, bool silent)
|
||||||
Rect b(*prev);
|
Rect b(*prev);
|
||||||
while (cur != tail) {
|
while (cur != tail) {
|
||||||
if (cur->isValid() == false) {
|
if (cur->isValid() == false) {
|
||||||
|
// We allow this particular flavor of invalid Rect, since it is used
|
||||||
|
// as a signal value in various parts of the system
|
||||||
|
if (*cur != Rect::INVALID_RECT) {
|
||||||
ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
|
ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (cur->right > region_operator<Rect>::max_value) {
|
if (cur->right > region_operator<Rect>::max_value) {
|
||||||
ALOGE_IF(!silent, "%s: rect->right > max_value", name);
|
ALOGE_IF(!silent, "%s: rect->right > max_value", name);
|
||||||
result = false;
|
result = false;
|
||||||
|
@ -690,7 +696,9 @@ void Region::boolean_operation(int op, Region& dst,
|
||||||
const Region& lhs,
|
const Region& lhs,
|
||||||
const Rect& rhs, int dx, int dy)
|
const Rect& rhs, int dx, int dy)
|
||||||
{
|
{
|
||||||
if (!rhs.isValid()) {
|
// We allow this particular flavor of invalid Rect, since it is used as a
|
||||||
|
// signal value in various parts of the system
|
||||||
|
if (!rhs.isValid() && rhs != Rect::INVALID_RECT) {
|
||||||
ALOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}",
|
ALOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}",
|
||||||
op, rhs.left, rhs.top, rhs.right, rhs.bottom);
|
op, rhs.left, rhs.top, rhs.right, rhs.bottom);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue