Merge "Init displays to null layer stack" into jb-mr2-dev
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/CpuConsumer.h b/include/gui/CpuConsumer.h
index a08c718..93dff32 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -57,7 +57,7 @@
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
// how many buffers can be locked for user access at the same time.
- CpuConsumer(uint32_t maxLockedBuffers);
+ CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode = true);
virtual ~CpuConsumer();
@@ -92,7 +92,11 @@
// Array for tracking pointers passed to the consumer, matching the
// mSlots indexing
- void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS];
+ struct LockedSlot {
+ sp<GraphicBuffer> mGraphicBuffer;
+ void *mBufferPointer;
+ } mLockedSlots[BufferQueue::NUM_BUFFER_SLOTS];
+
// Count of currently locked buffers
uint32_t mCurrentLockedBuffers;
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 @@
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/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 710e1af..1ee6673 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -29,22 +29,34 @@
namespace android {
-CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
+CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) :
ConsumerBase(new BufferQueue(true) ),
mMaxLockedBuffers(maxLockedBuffers),
mCurrentLockedBuffers(0)
{
-
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- mBufferPointers[i] = NULL;
+ for (size_t i=0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ mLockedSlots[i].mBufferPointer = NULL;
}
- mBufferQueue->setSynchronousMode(true);
+ mBufferQueue->setSynchronousMode(synchronousMode);
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers);
}
CpuConsumer::~CpuConsumer() {
+ status_t err;
+ for (size_t i=0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ if (mLockedSlots[i].mBufferPointer != NULL) {
+ mLockedSlots[i].mBufferPointer = NULL;
+ err = mLockedSlots[i].mGraphicBuffer->unlock();
+ mLockedSlots[i].mGraphicBuffer.clear();
+ if (err != OK) {
+ CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
+ i);
+ }
+
+ }
+ }
}
void CpuConsumer::setName(const String8& name) {
@@ -86,18 +98,22 @@
}
}
+ void *bufferPointer = NULL;
err = mSlots[buf].mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
- &mBufferPointers[buf]);
+ &bufferPointer);
- if (mBufferPointers[buf] != NULL && err != OK) {
+ if (bufferPointer != NULL && err != OK) {
CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err),
err);
return err;
}
+ mLockedSlots[buf].mBufferPointer = bufferPointer;
+ mLockedSlots[buf].mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
+ nativeBuffer->data =
+ reinterpret_cast<uint8_t*>(bufferPointer);
nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth();
nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
@@ -121,15 +137,16 @@
void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) {
- if (bufPtr == mBufferPointers[slotIndex]) break;
+ if (bufPtr == mLockedSlots[slotIndex].mBufferPointer) break;
}
if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) {
CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
return BAD_VALUE;
}
- mBufferPointers[slotIndex] = NULL;
- err = mSlots[slotIndex].mGraphicBuffer->unlock();
+ mLockedSlots[slotIndex].mBufferPointer = NULL;
+ err = mLockedSlots[slotIndex].mGraphicBuffer->unlock();
+ mLockedSlots[slotIndex].mGraphicBuffer.clear();
if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex);
return err;
@@ -142,17 +159,6 @@
}
void CpuConsumer::freeBufferLocked(int slotIndex) {
- if (mBufferPointers[slotIndex] != NULL) {
- status_t err;
- CC_LOGW("Buffer %d freed while locked by consumer", slotIndex);
- mBufferPointers[slotIndex] = NULL;
- err = mSlots[slotIndex].mGraphicBuffer->unlock();
- if (err != OK) {
- CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
- slotIndex);
- }
- mCurrentLockedBuffers--;
- }
ConsumerBase::freeBufferLocked(slotIndex);
}
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 @@
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 @@
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 4fc9c6a..ed2768c 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -287,7 +287,8 @@
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 @@
}
void DisplayDevice::setProjection(int orientation,
- const Rect& viewport, const Rect& frame) {
+ const Rect& newViewport, const Rect& newFrame) {
+ Rect viewport(newViewport);
+ Rect frame(newFrame);
+
+ const int w = mDisplayWidth;
+ const int h = mDisplayHeight;
+
+ Transform R;
+ DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
+
+ 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);
+ }
+
+ 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;
- updateGeometryTransform();
-}
-
-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);
- }
-
- 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);
- }
- }
-
- 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(mViewport);
- if (mScissor.isEmpty()) {
- mScissor.set(getBounds());
- }
- }
}
void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 856366b..91f34db 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -109,8 +109,8 @@
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; }
@@ -201,8 +201,6 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
*/
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;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c8d2eb6..5cc74a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1384,7 +1384,7 @@
// 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
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 @@
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 @@
Rect transform(const Rect& bounds) const;
Transform operator * (const Transform& rhs) const;
+ Transform inverse() const;
+
// for debugging
void dump(const char* name) const;