refactor the crop region for hwc is calculated/set
- the crop region is now always calculated and set
in LayerBase::setGeometry which uses new virtuals to
access the "content" crop and transform (which are
provided by the Layer subclass)
Change-Id: Ib7769bdec0917dd248f926600c14ddf9ea84897a
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 439acb5..c9f1eb5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
-#include <math.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
@@ -200,48 +199,27 @@
return NO_ERROR;
}
-Rect Layer::computeBufferCrop() const {
- // Start with the SurfaceFlingerConsumer's buffer crop...
+Rect Layer::getContentCrop() const {
+ // this is the crop rectangle that applies to the buffer
+ // itself (as opposed to the window)
Rect crop;
if (!mCurrentCrop.isEmpty()) {
+ // if the buffer crop is defined, we use that
crop = mCurrentCrop;
- } else if (mActiveBuffer != NULL){
- crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+ } else if (mActiveBuffer != NULL) {
+ // otherwise we use the whole buffer
+ crop = mActiveBuffer->getBounds();
} else {
+ // if we don't have a buffer yet, we use an empty/invalid crop
crop.makeInvalid();
- return crop;
}
-
- // ... then reduce that in the same proportions as the window crop reduces
- // the window size.
- const State& s(drawingState());
- if (!s.active.crop.isEmpty()) {
- // Transform the window crop to match the buffer coordinate system,
- // which means using the inverse of the current transform set on the
- // SurfaceFlingerConsumer.
- uint32_t invTransform = mCurrentTransform;
- int winWidth = s.active.w;
- int winHeight = s.active.h;
- if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
- winWidth = s.active.h;
- winHeight = s.active.w;
- }
- Rect winCrop = s.active.crop.transform(invTransform,
- s.active.w, s.active.h);
-
- float xScale = float(crop.width()) / float(winWidth);
- float yScale = float(crop.height()) / float(winHeight);
- crop.left += int(ceilf(float(winCrop.left) * xScale));
- crop.top += int(ceilf(float(winCrop.top) * yScale));
- crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
- crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
- }
-
return crop;
}
+uint32_t Layer::getContentTransform() const {
+ return mCurrentTransform;
+}
+
void Layer::setGeometry(
const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer)
@@ -278,7 +256,6 @@
} else {
layer.setTransform(finalTransform);
}
- layer.setCrop(computeBufferCrop());
}
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a82767b..242493d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -103,6 +103,9 @@
// the current orientation of the display device.
virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+ virtual Rect getContentCrop() const;
+ virtual uint32_t getContentTransform() const;
+
protected:
virtual void onFirstRef();
virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -115,7 +118,6 @@
uint32_t getEffectiveUsage(uint32_t usage) const;
bool isCropped() const;
- Rect computeBufferCrop() const;
static bool getOpacityForFormat(uint32_t format);
// Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index ba56c23..572e7c8 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
+#include <math.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -267,6 +268,61 @@
return result;
}
+
+Rect LayerBase::getContentCrop() const {
+ // regular layers just use their active area as the content crop
+ const State& s(drawingState());
+ return Rect(s.active.w, s.active.h);
+}
+
+uint32_t LayerBase::getContentTransform() const {
+ // regular layers don't have a content transform
+ return 0;
+}
+
+Rect LayerBase::computeCrop(const sp<const DisplayDevice>& hw) const {
+ // the content crop is the area of the content that gets scaled to the
+ // layer's size.
+ Rect crop(getContentCrop());
+
+ // the active.crop is the area of the window that gets cropped, but not
+ // scaled in any ways.
+ const State& s(drawingState());
+ Rect activeCrop(s.active.crop);
+ if (!activeCrop.isEmpty()) {
+ // Transform the window crop to match the buffer coordinate system,
+ // which means using the inverse of the current transform set on the
+ // SurfaceFlingerConsumer.
+ uint32_t invTransform = getContentTransform();
+ int winWidth = s.active.w;
+ int winHeight = s.active.h;
+ if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+ NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ winWidth = s.active.h;
+ winHeight = s.active.w;
+ }
+ const Rect winCrop = activeCrop.transform(
+ invTransform, s.active.w, s.active.h);
+
+ // the code below essentially performs a scaled intersection
+ // of crop and winCrop
+ float xScale = float(crop.width()) / float(winWidth);
+ float yScale = float(crop.height()) / float(winHeight);
+
+ int insetL = int(ceilf( winCrop.left * xScale));
+ int insetT = int(ceilf( winCrop.top * yScale));
+ int insetR = int(ceilf((winWidth - winCrop.right ) * xScale));
+ int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
+
+ crop.left += insetL;
+ crop.top += insetT;
+ crop.right -= insetR;
+ crop.bottom -= insetB;
+ }
+ return crop;
+}
+
void LayerBase::setGeometry(
const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer)
@@ -290,15 +346,13 @@
}
- Rect bounds(computeBounds());
-
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
- const Transform& tr = hw->getTransform();
- Rect frame(tr.transform(s.transform.transform(bounds)));
- layer.setFrame(frame);
- layer.setCrop(bounds);
+ Rect frame(s.transform.transform(computeBounds()));
+ const Transform& tr(hw->getTransform());
+ layer.setFrame(tr.transform(frame));
+ layer.setCrop(computeCrop(hw));
}
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index c2624df..ecae2d9 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -260,6 +260,18 @@
*/
virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { }
+ /**
+ * returns the rectangle that crops the content of the layer and scales it
+ * to the layer's size.
+ */
+ virtual Rect getContentCrop() const;
+
+ /*
+ * returns the transform bits (90 rotation / h-flip / v-flip) of the
+ * layer's content
+ */
+ virtual uint32_t getContentTransform() const;
+
/** always call base class first */
virtual void dump(String8& result, char* scratch, size_t size) const;
virtual void shortDump(String8& result, char* scratch, size_t size) const;
@@ -282,6 +294,9 @@
void setFiltering(bool filtering);
bool getFiltering() const;
+private:
+ Rect computeCrop(const sp<const DisplayDevice>& hw) const;
+
protected:
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;