summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2013-07-10 23:10:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-07-10 23:10:58 +0000
commitbb7272f137ad3558bba5ee3a31dcfe4f41cc797f (patch)
tree82b6b0634484ca46ea6608edaba07843b7b43b10
parente7a8b17e37ef359567fbbd9beb8c2445494f6402 (diff)
parent6b44267a3beb457e220cad0666c039d3a765cdb2 (diff)
downloadframeworks_native-bb7272f137ad3558bba5ee3a31dcfe4f41cc797f.zip
frameworks_native-bb7272f137ad3558bba5ee3a31dcfe4f41cc797f.tar.gz
frameworks_native-bb7272f137ad3558bba5ee3a31dcfe4f41cc797f.tar.bz2
Merge "fix SF buffer cropping"
-rw-r--r--services/surfaceflinger/DisplayHardware/FloatRect.h42
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp22
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h3
-rw-r--r--services/surfaceflinger/Layer.cpp41
-rw-r--r--services/surfaceflinger/Layer.h9
5 files changed, 79 insertions, 38 deletions
diff --git a/services/surfaceflinger/DisplayHardware/FloatRect.h b/services/surfaceflinger/DisplayHardware/FloatRect.h
new file mode 100644
index 0000000..b08a951
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/FloatRect.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_FLOAT_RECT
+#define ANDROID_SF_FLOAT_RECT
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+class FloatRect
+{
+public:
+ float left;
+ float top;
+ float right;
+ float bottom;
+
+ inline FloatRect() { }
+ inline FloatRect(const Rect& other)
+ : left(other.left), top(other.top), right(other.right), bottom(other.bottom) { }
+
+ inline float getWidth() const { return right - left; }
+ inline float getHeight() const { return bottom - top; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_SF_FLOAT_RECT
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 5082192..1cdabc4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+#include <math.h>
#include <utils/CallStack.h>
#include <utils/Errors.h>
@@ -880,10 +881,25 @@ public:
getLayer()->transform = transform;
}
virtual void setFrame(const Rect& frame) {
- reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
+ getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
}
- virtual void setCrop(const Rect& crop) {
- reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
+ virtual void setCrop(const FloatRect& crop) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+ getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
+ } else {
+ /*
+ * Since h/w composer didn't support a flot crop rect before version 1.3,
+ * using integer coordinates instead produces a different output from the GL code in
+ * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
+ * window size ratio is large and a window crop is defined
+ * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
+ */
+ hwc_rect_t& r = getLayer()->sourceCrop;
+ r.left = int(ceilf(crop.left));
+ r.top = int(ceilf(crop.top));
+ r.right = int(floorf(crop.right));
+ r.bottom= int(floorf(crop.bottom));
+ }
}
virtual void setVisibleRegionScreen(const Region& reg) {
// Region::getSharedBuffer creates a reference to the underlying
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a20da08..0462bcc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -47,6 +47,7 @@ namespace android {
class GraphicBuffer;
class Fence;
+class FloatRect;
class Region;
class String8;
class SurfaceFlinger;
@@ -158,7 +159,7 @@ public:
virtual void setBlending(uint32_t blending) = 0;
virtual void setTransform(uint32_t transform) = 0;
virtual void setFrame(const Rect& frame) = 0;
- virtual void setCrop(const Rect& crop) = 0;
+ virtual void setCrop(const FloatRect& crop) = 0;
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3605dd4..34003b8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -257,10 +257,6 @@ Rect Layer::getContentCrop() const {
return crop;
}
-uint32_t Layer::getContentTransform() const {
- return mCurrentTransform;
-}
-
static Rect reduce(const Rect& win, const Region& exclude) {
if (CC_LIKELY(exclude.isEmpty())) {
return win;
@@ -281,18 +277,10 @@ Rect Layer::computeBounds() const {
return reduce(win, s.activeTransparentRegion);
}
-Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
- /*
- * The way we compute the crop (aka. texture coordinates when we have a
- * Layer) produces a different output from the GL code in
- * drawWithOpenGL() due to HWC being limited to integers. The difference
- * can be large if getContentTransform() contains a large scale factor.
- * See comments in drawWithOpenGL() for more details.
- */
-
+FloatRect Layer::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());
+ FloatRect crop(getContentCrop());
// the active.crop is the area of the window that gets cropped, but not
// scaled in any ways.
@@ -300,10 +288,10 @@ Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
// apply the projection's clipping to the window crop in
// layerstack space, and convert-back to layer space.
- // if there are no window scaling (or content scaling) involved,
- // this operation will map to full pixels in the buffer.
- // NOTE: should we revert to GL composition if a scaling is involved
- // since it cannot be represented in the HWC API?
+ // if there are no window scaling involved, this operation will map to full
+ // pixels in the buffer.
+ // FIXME: the 3 lines below can produce slightly incorrect clipping when we have
+ // a viewport clipping and a window transform. we should use floating point to fix this.
Rect activeCrop(s.transform.transform(s.active.crop));
activeCrop.intersect(hw->getViewport(), &activeCrop);
activeCrop = s.transform.inverse().transform(activeCrop);
@@ -319,7 +307,7 @@ Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
// 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();
+ uint32_t invTransform = mCurrentTransform;
int winWidth = s.active.w;
int winHeight = s.active.h;
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -331,15 +319,14 @@ Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
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);
+ // below, crop is intersected with winCrop expressed in crop's coordinate space
+ float xScale = crop.getWidth() / float(winWidth);
+ float yScale = crop.getHeight() / 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));
+ float insetL = winCrop.left * xScale;
+ float insetT = winCrop.top * yScale;
+ float insetR = (winWidth - winCrop.right ) * xScale;
+ float insetB = (winHeight - winCrop.bottom) * yScale;
crop.left += insetL;
crop.top += insetT;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e7e9585..0ceb15e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -43,6 +43,7 @@
#include "Transform.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/FloatRect.h"
namespace android {
@@ -279,12 +280,6 @@ public:
*/
Rect getContentCrop() const;
- /*
- * returns the transform bits (90 rotation / h-flip / v-flip) of the
- * layer's content
- */
- uint32_t getContentTransform() const;
-
// -----------------------------------------------------------------------
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
@@ -334,7 +329,7 @@ private:
bool needsFiltering(const sp<const DisplayDevice>& hw) const;
uint32_t getEffectiveUsage(uint32_t usage) const;
- Rect computeCrop(const sp<const DisplayDevice>& hw) const;
+ FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
bool isCropped() const;
static bool getOpacityForFormat(uint32_t format);