summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/dumpstate/dumpstate.c2
-rw-r--r--cmds/installd/commands.c2
-rw-r--r--cmds/installd/installd.c2
-rw-r--r--include/gui/SurfaceControl.h2
-rw-r--r--libs/gui/Surface.cpp2
-rw-r--r--libs/gui/SurfaceControl.cpp2
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp131
-rw-r--r--services/surfaceflinger/DisplayDevice.h12
-rw-r--r--services/surfaceflinger/Layer.cpp47
-rw-r--r--services/surfaceflinger/Layer.h4
-rw-r--r--services/surfaceflinger/LayerBase.cpp119
-rw-r--r--services/surfaceflinger/LayerBase.h15
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp12
-rw-r--r--services/surfaceflinger/Transform.cpp38
-rw-r--r--services/surfaceflinger/Transform.h2
15 files changed, 262 insertions, 130 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 1b8f755..9a1839d 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -25,7 +25,7 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
-#include <linux/capability.h>
+#include <sys/capability.h>
#include <linux/prctl.h>
#include <cutils/properties.h>
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index c272e47..a58eca8 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <linux/capability.h>
+#include <sys/capability.h>
#include "installd.h"
#include <diskusage/dirsize.h>
#include <selinux/android.h>
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 2285e79..f81dfe5 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <linux/capability.h>
+#include <sys/capability.h>
#include <linux/prctl.h>
#include "installd.h"
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 9268e7d..f70888d 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -57,7 +57,7 @@ public:
status_t setLayerStack(int32_t layerStack);
status_t setLayer(int32_t layer);
- status_t setPosition(float x, float y);
+ status_t setPosition(int32_t x, int32_t y);
status_t setSize(uint32_t w, uint32_t h);
status_t hide();
status_t show();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 410ad5d..950d16a 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -735,7 +735,7 @@ status_t Surface::writeToParcel(
sp<Surface> Surface::readFromParcel(const Parcel& data) {
sp<IBinder> binder(data.readStrongBinder());
sp<IGraphicBufferProducer> bp(interface_cast<IGraphicBufferProducer>(binder));
- return new Surface(bp);
+ return bp != NULL ? new Surface(bp): NULL;
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index e621b22..ef52269 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -106,7 +106,7 @@ status_t SurfaceControl::setLayer(int32_t layer) {
const sp<SurfaceComposerClient>& client(mClient);
return client->setLayer(mSurface, layer);
}
-status_t SurfaceControl::setPosition(float x, float y) {
+status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
status_t err = validate();
if (err < 0) return err;
const sp<SurfaceComposerClient>& client(mClient);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9466944..ed2768c 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -89,7 +89,7 @@ DisplayDevice::DisplayDevice(
mIsSecure(isSecure),
mSecureLayerVisible(false),
mScreenAcquired(false),
- mLayerStack(0),
+ mLayerStack(NO_LAYER_STACK),
mOrientation()
{
init(config);
@@ -196,13 +196,13 @@ void DisplayDevice::flip(const Region& dirty) const
EGLDisplay dpy = mDisplay;
EGLSurface surface = mSurface;
-#ifdef EGL_ANDROID_swap_rectangle
+#ifdef EGL_ANDROID_swap_rectangle
if (mFlags & SWAP_RECTANGLE) {
const Region newDirty(dirty.intersect(bounds()));
const Rect b(newDirty.getBounds());
eglSetSwapRectangleANDROID(dpy, surface,
b.left, b.top, b.width(), b.height());
- }
+ }
#endif
mPageFlipCount++;
@@ -287,7 +287,8 @@ void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& lay
mSecureLayerVisible = false;
size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
- if (layers[i]->isSecure()) {
+ const sp<LayerBase>& layer(layers[i]);
+ if (layer->isSecure()) {
mSecureLayerVisible = true;
}
}
@@ -365,74 +366,72 @@ status_t DisplayDevice::orientationToTransfrom(
}
void DisplayDevice::setProjection(int orientation,
- const Rect& viewport, const Rect& frame) {
- mOrientation = orientation;
- mViewport = viewport;
- mFrame = frame;
- updateGeometryTransform();
-}
+ const Rect& newViewport, const Rect& newFrame) {
+ Rect viewport(newViewport);
+ Rect frame(newFrame);
-void DisplayDevice::updateGeometryTransform() {
- int w = mDisplayWidth;
- int h = mDisplayHeight;
- Transform TL, TP, R, S;
- if (DisplayDevice::orientationToTransfrom(
- mOrientation, w, h, &R) == NO_ERROR) {
- dirtyRegion.set(bounds());
-
- Rect viewport(mViewport);
- Rect frame(mFrame);
-
- if (!frame.isValid()) {
- // the destination frame can be invalid if it has never been set,
- // in that case we assume the whole display frame.
- frame = Rect(w, h);
- }
+ const int w = mDisplayWidth;
+ const int h = mDisplayHeight;
- if (viewport.isEmpty()) {
- // viewport can be invalid if it has never been set, in that case
- // we assume the whole display size.
- // it's also invalid to have an empty viewport, so we handle that
- // case in the same way.
- viewport = Rect(w, h);
- if (R.getOrientation() & Transform::ROT_90) {
- // viewport is always specified in the logical orientation
- // of the display (ie: post-rotation).
- swap(viewport.right, viewport.bottom);
- }
- }
+ Transform R;
+ DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
- float src_width = viewport.width();
- float src_height = viewport.height();
- float dst_width = frame.width();
- float dst_height = frame.height();
- if (src_width != dst_width || src_height != dst_height) {
- float sx = dst_width / src_width;
- float sy = dst_height / src_height;
- S.set(sx, 0, 0, sy);
- }
+ if (!frame.isValid()) {
+ // the destination frame can be invalid if it has never been set,
+ // in that case we assume the whole display frame.
+ frame = Rect(w, h);
+ }
- float src_x = viewport.left;
- float src_y = viewport.top;
- float dst_x = frame.left;
- float dst_y = frame.top;
- TL.set(-src_x, -src_y);
- TP.set(dst_x, dst_y);
-
- // The viewport and frame are both in the logical orientation.
- // Apply the logical translation, scale to physical size, apply the
- // physical translation and finally rotate to the physical orientation.
- mGlobalTransform = R * TP * S * TL;
-
- const uint8_t type = mGlobalTransform.getType();
- mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
- (type >= Transform::SCALE));
-
- mScissor = mGlobalTransform.transform(mViewport);
- if (mScissor.isEmpty()) {
- mScissor.set(getBounds());
+ if (viewport.isEmpty()) {
+ // viewport can be invalid if it has never been set, in that case
+ // we assume the whole display size.
+ // it's also invalid to have an empty viewport, so we handle that
+ // case in the same way.
+ viewport = Rect(w, h);
+ if (R.getOrientation() & Transform::ROT_90) {
+ // viewport is always specified in the logical orientation
+ // of the display (ie: post-rotation).
+ swap(viewport.right, viewport.bottom);
}
}
+
+ dirtyRegion.set(getBounds());
+
+ Transform TL, TP, S;
+ float src_width = viewport.width();
+ float src_height = viewport.height();
+ float dst_width = frame.width();
+ float dst_height = frame.height();
+ if (src_width != dst_width || src_height != dst_height) {
+ float sx = dst_width / src_width;
+ float sy = dst_height / src_height;
+ S.set(sx, 0, 0, sy);
+ }
+
+ float src_x = viewport.left;
+ float src_y = viewport.top;
+ float dst_x = frame.left;
+ float dst_y = frame.top;
+ TL.set(-src_x, -src_y);
+ TP.set(dst_x, dst_y);
+
+ // The viewport and frame are both in the logical orientation.
+ // Apply the logical translation, scale to physical size, apply the
+ // physical translation and finally rotate to the physical orientation.
+ mGlobalTransform = R * TP * S * TL;
+
+ const uint8_t type = mGlobalTransform.getType();
+ mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
+ (type >= Transform::SCALE));
+
+ mScissor = mGlobalTransform.transform(viewport);
+ if (mScissor.isEmpty()) {
+ mScissor.set(getBounds());
+ }
+
+ mOrientation = orientation;
+ mViewport = viewport;
+ mFrame = frame;
}
void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bb6eb70..91f34db 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -65,6 +65,10 @@ public:
SWAP_RECTANGLE = 0x00080000,
};
+ enum {
+ NO_LAYER_STACK = 0xFFFFFFFF,
+ };
+
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -105,8 +109,8 @@ public:
int getOrientation() const { return mOrientation; }
const Transform& getTransform() const { return mGlobalTransform; }
- const Rect& getViewport() const { return mViewport; }
- const Rect& getFrame() const { return mFrame; }
+ const Rect getViewport() const { return mViewport; }
+ const Rect getFrame() const { return mFrame; }
const Rect& getScissor() const { return mScissor; }
bool needsFiltering() const { return mNeedsFiltering; }
@@ -117,7 +121,7 @@ public:
void swapBuffers(HWComposer& hwc) const;
status_t compositionComplete() const;
-
+
// called after h/w composer has completed its set() call
void onSwapBuffersCompleted(HWComposer& hwc) const;
@@ -197,8 +201,6 @@ private:
static status_t orientationToTransfrom(int orientation,
int w, int h, Transform* tr);
- void updateGeometryTransform();
-
uint32_t mLayerStack;
int mOrientation;
// user-provided visible area of the layer stack
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 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
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 @@ void Layer::setGeometry(
} 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 5fd7e59..e57fb59 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -103,6 +103,9 @@ public:
// 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;
@@ -119,7 +122,6 @@ private:
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 dfdbf30..db2b20e 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>
@@ -259,7 +260,7 @@ Rect LayerBase::computeBounds() const {
if (!s.active.crop.isEmpty()) {
win.intersect(s.active.crop, &win);
}
- return s.transform.transform(win);
+ return win;
}
Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
@@ -267,6 +268,83 @@ Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
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 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.
+ */
+
+ // 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());
+
+ // 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?
+ Rect activeCrop(s.transform.transform(s.active.crop));
+ activeCrop.intersect(hw->getViewport(), &activeCrop);
+ activeCrop = s.transform.inverse().transform(activeCrop);
+
+ // paranoia: make sure the window-crop is constrained in the
+ // window's bounds
+ activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+
+ 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)
@@ -289,13 +367,15 @@ void LayerBase::setGeometry(
HWC_BLENDING_COVERAGE);
}
- const Transform& tr = hw->getTransform();
- Rect transformedBounds(computeBounds());
- transformedBounds = tr.transform(transformedBounds);
- // scaling is already applied in transformedBounds
- layer.setFrame(transformedBounds);
- layer.setCrop(transformedBounds.getBounds());
+ // apply the layer's transform, followed by the display's global transform
+ // here we're guaranteed that the layer's transform preserves rects
+
+ Rect frame(s.transform.transform(computeBounds()));
+ frame.intersect(hw->getViewport(), &frame);
+ const Transform& tr(hw->getTransform());
+ layer.setFrame(tr.transform(frame));
+ layer.setCrop(computeCrop(hw));
}
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
@@ -303,8 +383,11 @@ void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
// we have to set the visible region on every frame because
// we currently free it during onLayerDisplayed(), which is called
// after HWComposer::commit() -- every frame.
+ // Apply this display's projection's viewport to the visible region
+ // before giving it to the HWC HAL.
const Transform& tr = hw->getTransform();
- layer.setVisibleRegionScreen(tr.transform(visibleRegion));
+ Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
+ layer.setVisibleRegionScreen(visible);
}
void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
@@ -404,10 +487,22 @@ void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region&
GLfloat v;
};
- Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
- }
+
+ /*
+ * NOTE: the way we compute the texture coordinates here produces
+ * different results than when we take the HWC path -- in the later case
+ * the "source crop" is rounded to texel boundaries.
+ * This can produce significantly different results when the texture
+ * is scaled by a large amount.
+ *
+ * The GL code below is more logical (imho), and the difference with
+ * HWC is due to a limitation of the HWC API to integers -- a question
+ * is suspend is wether we should ignore this problem or revert to
+ * GL composition when a buffer scaling is applied (maybe with some
+ * minimal value)? Or, we could make GL behave like HWC -- but this feel
+ * like more of a hack.
+ */
+ const Rect win(computeBounds());
GLfloat left = GLfloat(win.left) / GLfloat(s.active.w);
GLfloat top = GLfloat(win.top) / GLfloat(s.active.h);
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 @@ public:
*/
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 @@ public:
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;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0971faa..8fa0800 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1347,7 +1347,7 @@ void SurfaceFlinger::computeVisibleRegions(
// start with the whole surface at its current location
const Layer::State& s(layer->drawingState());
- // only consider the layers on the given later stack
+ // only consider the layers on the given layer stack
if (s.layerStack != layerStack)
continue;
@@ -1384,7 +1384,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque();
- Rect bounds(layer->computeBounds());
+ Rect bounds(s.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
@@ -2073,12 +2073,14 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer)
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
- // reset screen orientation
+ // reset screen orientation and use primary layer stack
Vector<ComposerState> state;
Vector<DisplayState> displays;
DisplayState d;
- d.what = DisplayState::eDisplayProjectionChanged;
+ d.what = DisplayState::eDisplayProjectionChanged |
+ DisplayState::eLayerStackChanged;
d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
+ d.layerStack = 0;
d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid();
d.viewport.makeInvalid();
@@ -2922,7 +2924,7 @@ SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
}
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
- : type(type), layerStack(0), orientation(0) {
+ : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0) {
viewport.makeInvalid();
frame.makeInvalid();
}
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index aca90e0..315720e 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -298,6 +298,44 @@ uint32_t Transform::type() const
return mType;
}
+Transform Transform::inverse() const {
+ // our 3x3 matrix is always of the form of a 2x2 transformation
+ // followed by a translation: T*M, therefore:
+ // (T*M)^-1 = M^-1 * T^-1
+ Transform result;
+ if (mType <= TRANSLATE) {
+ // 1 0 x
+ // 0 1 y
+ // 0 0 1
+ result = *this;
+ result.mMatrix[2][0] = -result.mMatrix[2][0];
+ result.mMatrix[2][1] = -result.mMatrix[2][1];
+ } else {
+ // a c x
+ // b d y
+ // 0 0 1
+ const mat33& M(mMatrix);
+ const float a = M[0][0];
+ const float b = M[1][0];
+ const float c = M[0][1];
+ const float d = M[1][1];
+ const float x = M[2][0];
+ const float y = M[2][1];
+
+ Transform R, T;
+ const float idet = 1.0 / (a*d - b*c);
+ R.mMatrix[0][0] = d*idet; R.mMatrix[0][1] = -c*idet;
+ R.mMatrix[1][0] = -b*idet; R.mMatrix[1][1] = a*idet;
+ R.mType = mType &= ~TRANSLATE;
+
+ T.mMatrix[2][0] = -x;
+ T.mMatrix[2][1] = -y;
+ T.mType = TRANSLATE;
+ result = R * T;
+ }
+ return result;
+}
+
uint32_t Transform::getType() const {
return type() & 0xFF;
}
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 4fe261a..c4efade 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -80,6 +80,8 @@ public:
Rect transform(const Rect& bounds) const;
Transform operator * (const Transform& rhs) const;
+ Transform inverse() const;
+
// for debugging
void dump(const char* name) const;