frameworks/native: Propagate dirty region in hwc_layer.
This change propagates dirty rect value of each layer down to HWC
in hwc_layer structure.
Conflicts:
include/gui/IGraphicBufferProducer.h
libs/gui/BufferQueueProducer.cpp
libs/gui/Surface.cpp
services/surfaceflinger/Layer.cpp
services/surfaceflinger/Layer.h
Change-Id: I91d87facf4a321b92539de5353faf09b553d4919
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5effd10..a78f1c9 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -59,6 +59,9 @@
// mCrop is the current crop rectangle for this buffer slot.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle for this buffer slot.
+ Rect mDirtyRect;
+
// mTransform is the current transform flags for this buffer slot.
// refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
uint32_t mTransform;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index f91fe46..bd7b973 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -176,6 +176,9 @@
// getCurrentCrop returns the cropping rectangle of the current buffer.
Rect getCurrentCrop() const;
+ // getDirtyRegion returns the dirty rect associated with the current buffer.
+ Rect getCurrentDirtyRect() const;
+
// getCurrentTransform returns the transform of the current buffer.
uint32_t getCurrentTransform() const;
@@ -369,6 +372,10 @@
// It gets set each time updateTexImage is called.
Rect mCurrentCrop;
+ //mCurrentDirtyRect is the dirty rectangle associated with the current
+ //buffer.
+ Rect mCurrentDirtyRect;
+
// mCurrentTransform is the transform identifier for the current texture. It
// gets set each time updateTexImage is called.
uint32_t mCurrentTransform;
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 15f51fe..e083f71 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -67,6 +67,9 @@
// mCrop is the current crop rectangle for this buffer slot.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle for this buffer slot.
+ Rect mDirtyRect;
+
// mTransform is the current transform flags for this buffer slot.
// refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
uint32_t mTransform;
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 4e9e810..48e32cc 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -281,6 +281,14 @@
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
async(async), fence(fence) { }
+
+ inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
+ const Rect& crop, const Rect& dirtyRect, int scalingMode, uint32_t transform, bool async,
+ const sp<Fence>& fence, uint32_t sticky = 0)
+ : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
+ dirtyRect(dirtyRect),scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
+ async(async), fence(fence) { }
+
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
bool* outAsync, sp<Fence>* outFence,
@@ -297,6 +305,24 @@
}
}
+ inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
+ Rect* outCrop, Rect* outDirtyRect, int* outScalingMode, uint32_t* outTransform,
+ bool* outAsync, sp<Fence>* outFence,
+ uint32_t* outStickyTransform = NULL) const {
+ *outTimestamp = timestamp;
+ *outIsAutoTimestamp = bool(isAutoTimestamp);
+ *outCrop = crop;
+ *outDirtyRect = dirtyRect;
+ *outScalingMode = scalingMode;
+ *outTransform = transform;
+ *outAsync = bool(async);
+ *outFence = fence;
+ if (outStickyTransform != NULL) {
+ *outStickyTransform = stickyTransform;
+ }
+ }
+
+
// Flattenable protocol
size_t getFlattenedSize() const;
size_t getFdCount() const;
@@ -307,6 +333,7 @@
int64_t timestamp;
int isAutoTimestamp;
Rect crop;
+ Rect dirtyRect;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index f2cf018..31138e1 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -101,6 +101,10 @@
*/
void allocateBuffers();
+ /* sets dirty rectangle of the buffer that gets queued next for the
+ * Surface */
+ status_t setDirtyRect(const Rect* dirtyRect);
+
protected:
virtual ~Surface();
@@ -226,6 +230,10 @@
// that gets queued. It is set by calling setCrop.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle set for the next buffer that gets
+ // queued. It is set by calling setDirtyRect.
+ Rect mDirtyRect;
+
// mScalingMode is the scaling mode that will be used for the next
// buffers that get queued. It is set by calling setScalingMode.
int mScalingMode;
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index d3fa43e..5924b05 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -34,6 +34,7 @@
mAcquireCalled(false),
mTransformToDisplayInverse(false) {
mCrop.makeInvalid();
+ mDirtyRect.makeInvalid();
}
BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
@@ -41,6 +42,7 @@
bufferItem.mGraphicBuffer = mGraphicBuffer;
bufferItem.mFence = mFence;
bufferItem.mCrop = mCrop;
+ bufferItem.mDirtyRect = mDirtyRect;
bufferItem.mTransform = mTransform;
bufferItem.mScalingMode = mScalingMode;
bufferItem.mTimestamp = mTimestamp;
@@ -55,6 +57,7 @@
size_t BufferItem::getPodSize() const {
size_t c = sizeof(mCrop) +
+ sizeof(mDirtyRect) +
sizeof(mTransform) +
sizeof(mScalingMode) +
sizeof(mTimestamp) +
@@ -125,6 +128,7 @@
}
FlattenableUtils::write(buffer, size, mCrop);
+ FlattenableUtils::write(buffer, size, mDirtyRect);
FlattenableUtils::write(buffer, size, mTransform);
FlattenableUtils::write(buffer, size, mScalingMode);
FlattenableUtils::write(buffer, size, mTimestamp);
@@ -167,6 +171,7 @@
}
FlattenableUtils::read(buffer, size, mCrop);
+ FlattenableUtils::read(buffer, size, mDirtyRect);
FlattenableUtils::read(buffer, size, mTransform);
FlattenableUtils::read(buffer, size, mScalingMode);
FlattenableUtils::read(buffer, size, mTimestamp);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index d2fd3b0..6f2d214 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -512,12 +512,14 @@
int64_t timestamp;
bool isAutoTimestamp;
Rect crop;
+ Rect dirtyRect;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
bool async;
sp<Fence> fence;
- input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
+
+ input.deflate(×tamp, &isAutoTimestamp, &crop, &dirtyRect, &scalingMode, &transform,
&async, &fence, &stickyTransform);
if (fence == NULL) {
@@ -601,6 +603,7 @@
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
+ item.mDirtyRect = dirtyRect;
item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
item.mTransformToDisplayInverse =
bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index ccafe81..215cc74 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -141,6 +141,7 @@
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+ mCurrentDirtyRect.clear();
}
GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
@@ -437,6 +438,7 @@
mCurrentTimestamp = item.mTimestamp;
mCurrentFence = item.mFence;
mCurrentFrameNumber = item.mFrameNumber;
+ mCurrentDirtyRect = item.mDirtyRect;
computeCurrentTransformMatrixLocked();
@@ -983,6 +985,11 @@
return NO_ERROR;
}
+Rect GLConsumer::getCurrentDirtyRect() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentDirtyRect;
+}
+
void GLConsumer::freeBufferLocked(int slotIndex) {
ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
if (slotIndex == mCurrentTexture) {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 1e28f9b..649ab3b 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -433,6 +433,7 @@
return sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ sizeof(crop)
+ + sizeof(dirtyRect)
+ sizeof(scalingMode)
+ sizeof(transform)
+ sizeof(stickyTransform)
@@ -453,6 +454,7 @@
FlattenableUtils::write(buffer, size, timestamp);
FlattenableUtils::write(buffer, size, isAutoTimestamp);
FlattenableUtils::write(buffer, size, crop);
+ FlattenableUtils::write(buffer, size, dirtyRect);
FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
@@ -467,6 +469,7 @@
sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ sizeof(crop)
+ + sizeof(dirtyRect)
+ sizeof(scalingMode)
+ sizeof(transform)
+ sizeof(stickyTransform)
@@ -479,6 +482,7 @@
FlattenableUtils::read(buffer, size, timestamp);
FlattenableUtils::read(buffer, size, isAutoTimestamp);
FlattenableUtils::read(buffer, size, crop);
+ FlattenableUtils::read(buffer, size, dirtyRect);
FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform);
FlattenableUtils::read(buffer, size, stickyTransform);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 295f3f9..c7b7bb4 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -65,6 +65,7 @@
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
mCrop.clear();
+ mDirtyRect.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0;
mStickyTransform = 0;
@@ -175,6 +176,12 @@
return c->perform(operation, args);
}
+status_t Surface::setDirtyRect(const Rect* dirtyRect) {
+ Mutex::Autolock lock(mMutex);
+ mDirtyRect = *dirtyRect;
+ return NO_ERROR;
+}
+
int Surface::setSwapInterval(int interval) {
ATRACE_CALL();
// EGL specification states:
@@ -318,10 +325,13 @@
Rect crop;
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
+ Rect dirtyRect = mDirtyRect.isEmpty() ?
+ Rect(buffer->width, buffer->height) : mDirtyRect;
+
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
- crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
+ crop, dirtyRect, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
fence, mStickyTransform);
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
if (err != OK) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index edfed49..64714cd 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -1020,11 +1020,28 @@
SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
}
+
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
getLayer()->compositionType = HWC_SIDEBAND;
getLayer()->sidebandStream = stream->handle();
}
+
+ virtual void setDirtyRect(const Rect& dirtyRect) {
+ Rect srcCrop;
+ srcCrop.left = int(ceilf(getLayer()->sourceCropf.left));
+ srcCrop.right = int(ceilf(getLayer()->sourceCropf.right));
+ srcCrop.top = int(ceilf(getLayer()->sourceCropf.top));
+ srcCrop.bottom = int(ceilf(getLayer()->sourceCropf.bottom));
+
+ /* DirtyRect is generated for the full buffer resolution. Crop the value
+ * for the hwc_layer_1_t::sourceCrop resolution before sending to HWC.
+ */
+ Rect finalDR;
+ srcCrop.intersect(dirtyRect, &finalDR);
+ getLayer()->dirtyRect = reinterpret_cast<hwc_rect_t const&>(finalDR);
+ }
+
virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
if (buffer == 0 || buffer->handle == 0) {
getLayer()->compositionType = HWC_FRAMEBUFFER;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5cb56a0..9e21909 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -169,6 +169,7 @@
virtual void setCrop(const FloatRect& crop) = 0;
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
+ virtual void setDirtyRect(const Rect& dirtyRect) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
virtual void setPlaneAlpha(uint8_t alpha) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c3d45ee..a154493 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -458,7 +458,7 @@
uint32_t transform;
bool async;
input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode,
- &transform, &async, &mFbFence);
+ &transform, &async, &mFbFence);
mFbProducerSlot = pslot;
mOutputFence = mFbFence;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index fa07656..03e1ea4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -80,7 +80,8 @@
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client),
- mPotentialCursor(false)
+ mPotentialCursor(false),
+ mTransformHint(0)
{
mCurrentCrop.makeInvalid();
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
@@ -474,6 +475,55 @@
// layer yet, or if we ran out of memory
layer.setBuffer(mActiveBuffer);
}
+
+ Rect dirtyRect = mSurfaceFlingerConsumer->getCurrentDirtyRect();
+ if((mActiveBuffer != NULL) && mTransformHint &&
+ (mTransformHint != NATIVE_WINDOW_TRANSFORM_FLIP_H) &&
+ (mTransformHint != NATIVE_WINDOW_TRANSFORM_FLIP_V)) {
+ /* DirtyRect is generated by HWR without any knowledge of GPU
+ * pre-rotation. In case of pre-rotation, dirtyRect needs to be rotated
+ * accordingly.
+ *
+ * TODO: Generate and update dirtyRect from EGL and remove this code.
+ */
+
+ Rect srcRect = mActiveBuffer->getBounds();
+ Rect tempDR = dirtyRect;
+ int srcW = srcRect.getWidth();
+ int srcH = srcRect.getHeight();
+
+ if(mTransformHint & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ swap(srcW, srcH);
+ }
+
+ int setOffsetW = -srcW/2;
+ int setOffsetH = -srcH/2;
+
+ int resetOffsetW = srcW/2;
+ int resetOffsetH = srcH/2;
+
+ if(mTransformHint & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ swap(resetOffsetW, resetOffsetH);
+ }
+
+ /* - Move 2D space origin to srcRect origin.
+ * - Rotate
+ * - Move back the origin
+ */
+ Transform setOrigin;
+ setOrigin.set(setOffsetW, setOffsetH);
+ tempDR = setOrigin.transform(tempDR);
+ Transform rotate(mTransformHint);
+ tempDR = rotate.transform(tempDR);
+ Transform resetOrigin;
+ resetOrigin.set(resetOffsetW, resetOffsetH);
+ dirtyRect = resetOrigin.transform(tempDR);
+ }
+ layer.setDirtyRect(dirtyRect);
+
+ // NOTE: buffer can be NULL if the client never drew into this
+ // layer yet, or if we ran out of memory
+ layer.setBuffer(mActiveBuffer);
}
void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
@@ -1260,7 +1310,7 @@
return usage;
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) {
uint32_t orientation = 0;
if (!mFlinger->mDebugDisableTransformHint) {
// The transform hint is used to improve performance, but we can
@@ -1273,6 +1323,7 @@
}
}
mSurfaceFlingerConsumer->setTransformHint(orientation);
+ mTransformHint = orientation;
}
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f0fe58a..8804d9c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -273,7 +273,7 @@
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
- void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+ void updateTransformHint(const sp<const DisplayDevice>& hw);
/*
* returns the rectangle that crops the content of the layer and scales it
@@ -403,6 +403,9 @@
// This layer can be a cursor on some displays.
bool mPotentialCursor;
+
+ // Transform hint assigned for the layer
+ uint32_t mTransformHint;
};
// ---------------------------------------------------------------------------