summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gui/ISurfaceComposer.h1
-rw-r--r--include/gui/Surface.h1
-rw-r--r--include/gui/SurfaceComposerClient.h1
-rw-r--r--include/private/gui/LayerState.h3
-rw-r--r--include/ui/Rect.h2
-rw-r--r--libs/gui/Surface.cpp6
-rw-r--r--libs/gui/SurfaceComposerClient.cpp17
-rw-r--r--libs/ui/Rect.cpp2
-rw-r--r--services/surfaceflinger/Layer.cpp103
-rw-r--r--services/surfaceflinger/Layer.h1
-rw-r--r--services/surfaceflinger/LayerBase.cpp54
-rw-r--r--services/surfaceflinger/LayerBase.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp4
13 files changed, 122 insertions, 75 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index f3c0ecbc81..7320e4d1f3 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -67,6 +67,7 @@ public:
eTransparentRegionChanged = 0x00000020,
eVisibilityChanged = 0x00000040,
eFreezeTintChanged = 0x00000080,
+ eCropChanged = 0x00000100,
};
enum {
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 1f90c595aa..50bdf710f3 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -72,6 +72,7 @@ public:
status_t setAlpha(float alpha=1.0f);
status_t setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
status_t setFreezeTint(uint32_t tint);
+ status_t setCrop(const Rect& crop);
static status_t writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel);
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index d971031c01..3bd10de915 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -127,6 +127,7 @@ public:
status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
status_t setPosition(SurfaceID id, float x, float y);
status_t setSize(SurfaceID id, uint32_t w, uint32_t h);
+ status_t setCrop(SurfaceID id, const Rect& crop);
status_t destroySurface(SurfaceID sid);
private:
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index ca277e02b9..9151c1192f 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -23,6 +23,7 @@
#include <utils/Errors.h>
#include <ui/Region.h>
+#include <ui/Rect.h>
#include <gui/ISurface.h>
namespace android {
@@ -40,6 +41,7 @@ struct layer_state_t {
{
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
+ crop.makeInvalid();
}
status_t write(Parcel& output) const;
@@ -64,6 +66,7 @@ struct layer_state_t {
uint8_t mask;
uint8_t reserved;
matrix22_t matrix;
+ Rect crop;
// non POD must be last. see write/read
Region transparentRegion;
};
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index bd820618f3..308da7b673 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -147,7 +147,7 @@ public:
// a ROT90 then the output rectangle is defined in a space extending to
// (height, width). Otherwise the output rectangle is in the same space as
// the input.
- Rect transform(uint32_t xform, int32_t width, int32_t height);
+ Rect transform(uint32_t xform, int32_t width, int32_t height) const;
};
ANDROID_BASIC_TYPES_TRAITS(Rect)
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 059f3136df..d7590f013c 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -164,6 +164,12 @@ status_t SurfaceControl::setFreezeTint(uint32_t tint) {
const sp<SurfaceComposerClient>& client(mClient);
return client->setFreezeTint(mToken, tint);
}
+status_t SurfaceControl::setCrop(const Rect& crop) {
+ status_t err = validate();
+ if (err < 0) return err;
+ const sp<SurfaceComposerClient>& client(mClient);
+ return client->setCrop(mToken, crop);
+}
status_t SurfaceControl::validate() const
{
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index ceb1ba6d89..8fa21671eb 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -125,6 +125,8 @@ public:
const sp<SurfaceComposerClient>& client, SurfaceID id,
uint32_t tint);
status_t setOrientation(int orientation);
+ status_t setCrop(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ const Rect& crop);
static void closeGlobalTransaction(bool synchronous) {
Composer::getInstance().closeGlobalTransactionImpl(synchronous);
@@ -290,6 +292,17 @@ status_t Composer::setOrientation(int orientation) {
return NO_ERROR;
}
+status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, const Rect& crop) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eCropChanged;
+ s->crop = crop;
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
SurfaceComposerClient::SurfaceComposerClient()
@@ -398,6 +411,10 @@ void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
// ----------------------------------------------------------------------------
+status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) {
+ return getComposer().setCrop(this, id, crop);
+}
+
status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
return getComposer().setFreezeTint(this, id, tint);
}
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 65fe5f9da8..c4dd55ba34 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -93,7 +93,7 @@ bool Rect::intersect(const Rect& with, Rect* result) const
return !(result->isEmpty());
}
-Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) {
+Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const {
Rect result(*this);
if (xform & HAL_TRANSFORM_FLIP_H) {
result = Rect(width - result.right, result.top,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6bc80eea9c..2899db742c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -141,47 +141,6 @@ void Layer::setName(const String8& name) {
void Layer::validateVisibility(const Transform& globalTransform) {
LayerBase::validateVisibility(globalTransform);
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
- !mCurrentCrop.isEmpty()) {
- // We need to shrink the window size to match the buffer crop
- // rectangle.
- const Layer::State& s(drawingState());
- const Transform tr(globalTransform * s.transform);
- float windowWidth = s.w;
- float windowHeight = s.h;
- float bufferWidth = mActiveBuffer->getWidth();
- float bufferHeight = mActiveBuffer->getHeight();
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float tmp = bufferWidth;
- bufferWidth = bufferHeight;
- bufferHeight = tmp;
- }
- float xScale = float(windowWidth) / float(bufferWidth);
- float yScale = float(windowHeight) / float(bufferHeight);
-
- // Compute the crop in post-transform coordinates.
- Rect crop(mCurrentCrop.transform(mCurrentTransform,
- mActiveBuffer->getWidth(), mActiveBuffer->getHeight()));
-
- float left = ceil(xScale * float(crop.left));
- float right = floor(xScale * float(crop.right));
- float top = ceil(yScale * float(crop.top));
- float bottom = floor(yScale * float(crop.bottom));
-
- tr.transform(mVertices[0], left, top);
- tr.transform(mVertices[1], left, bottom);
- tr.transform(mVertices[2], right, bottom);
- tr.transform(mVertices[3], right, top);
-
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const uint32_t hw_h = hw.getHeight();
- for (size_t i=0 ; i<4 ; i++)
- mVertices[i][1] = hw_h - mVertices[i][1];
-
- mTransformedBounds = tr.transform(
- Rect(int(left), int(top), int(right), int(bottom)));
- }
-
// This optimization allows the SurfaceTexture to bake in
// the rotation so hardware overlays can be used
mSurfaceTexture->setTransformHint(getTransformHint());
@@ -259,6 +218,46 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
return NO_ERROR;
}
+Rect Layer::computeBufferCrop() const {
+ // Start with the SurfaceTexture's buffer crop...
+ Rect crop;
+ if (!mCurrentCrop.isEmpty()) {
+ crop = mCurrentCrop;
+ } else if (mActiveBuffer != NULL){
+ crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+ } else {
+ crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
+ }
+
+ // ... then reduce that in the same proportions as the window crop reduces
+ // the window size.
+ const State& s(drawingState());
+ if (!s.crop.isEmpty()) {
+ // Transform the window crop to match the buffer coordinate system,
+ // which means using the inverse of the current transform set on the
+ // SurfaceTexture.
+ uint32_t invTransform = mCurrentTransform;
+ int winWidth = s.w;
+ int winHeight = s.h;
+ if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+ NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ winWidth = s.h;
+ winHeight = s.w;
+ }
+ Rect winCrop = s.crop.transform(invTransform, s.w, s.h);
+
+ float xScale = float(crop.width()) / float(winWidth);
+ float yScale = float(crop.height()) / float(winHeight);
+ crop.left += int(ceil(float(winCrop.left) * xScale));
+ crop.top += int(ceil(float(winCrop.top) * yScale));
+ crop.right -= int(ceil(float(winWidth - winCrop.right) * xScale));
+ crop.bottom -= int(ceil(float(winHeight - winCrop.bottom) * yScale));
+ }
+
+ return crop;
+}
+
void Layer::setGeometry(hwc_layer_t* hwcl)
{
LayerBaseClient::setGeometry(hwcl);
@@ -293,23 +292,11 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
hwcl->transform = finalTransform;
}
- if (isCropped()) {
- hwcl->sourceCrop.left = mCurrentCrop.left;
- hwcl->sourceCrop.top = mCurrentCrop.top;
- hwcl->sourceCrop.right = mCurrentCrop.right;
- hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
- } else {
- const sp<GraphicBuffer>& buffer(mActiveBuffer);
- hwcl->sourceCrop.left = 0;
- hwcl->sourceCrop.top = 0;
- if (buffer != NULL) {
- hwcl->sourceCrop.right = buffer->width;
- hwcl->sourceCrop.bottom = buffer->height;
- } else {
- hwcl->sourceCrop.right = mTransformedBounds.width();
- hwcl->sourceCrop.bottom = mTransformedBounds.height();
- }
- }
+ Rect crop = computeBufferCrop();
+ hwcl->sourceCrop.left = crop.left;
+ hwcl->sourceCrop.top = crop.top;
+ hwcl->sourceCrop.right = crop.right;
+ hwcl->sourceCrop.bottom = crop.bottom;
}
void Layer::setPerFrameData(hwc_layer_t* hwcl) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1188621b81..393599f3a8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -101,6 +101,7 @@ private:
uint32_t getEffectiveUsage(uint32_t usage) const;
uint32_t getTransformHint() const;
bool isCropped() const;
+ Rect computeBufferCrop() const;
static bool getOpacityForFormat(uint32_t format);
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 694ecdef34..81031b14fb 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -93,6 +93,7 @@ void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
mCurrentState.flags = layerFlags;
mCurrentState.sequence = 0;
mCurrentState.transform.set(0, 0);
+ mCurrentState.crop.makeInvalid();
// drawing state & current state are identical
mDrawingState = mCurrentState;
@@ -172,6 +173,14 @@ bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
requestTransaction();
return true;
}
+bool LayerBase::setCrop(const Rect& crop) {
+ if (mCurrentState.crop == crop)
+ return false;
+ mCurrentState.sequence++;
+ mCurrentState.crop = crop;
+ requestTransaction();
+ return true;
+}
Rect LayerBase::visibleBounds() const
{
@@ -229,15 +238,18 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
const bool transformed = tr.transformed();
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t hw_h = hw.getHeight();
+ const Rect& crop(s.crop);
- uint32_t w = s.w;
- uint32_t h = s.h;
+ Rect win(s.w, s.h);
+ if (!crop.isEmpty()) {
+ win.intersect(crop, &win);
+ }
mNumVertices = 4;
- tr.transform(mVertices[0], 0, 0);
- tr.transform(mVertices[1], 0, h);
- tr.transform(mVertices[2], w, h);
- tr.transform(mVertices[3], w, 0);
+ tr.transform(mVertices[0], win.left, win.top);
+ tr.transform(mVertices[1], win.left, win.bottom);
+ tr.transform(mVertices[2], win.right, win.bottom);
+ tr.transform(mVertices[3], win.right, win.top);
for (size_t i=0 ; i<4 ; i++)
mVertices[i][1] = hw_h - mVertices[i][1];
@@ -260,7 +272,7 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
mOrientation = tr.getOrientation();
mPlaneOrientation = planeTransform.getOrientation();
mTransform = tr;
- mTransformedBounds = tr.makeBounds(w, h);
+ mTransformedBounds = tr.transform(win);
}
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
@@ -391,15 +403,27 @@ void LayerBase::drawWithOpenGL(const Region& clip) const
GLfloat v;
};
+ Rect crop(s.w, s.h);
+ if (!s.crop.isEmpty()) {
+ crop = s.crop;
+ }
+ GLfloat left = GLfloat(crop.left) / GLfloat(s.w);
+ GLfloat top = GLfloat(crop.top) / GLfloat(s.h);
+ GLfloat right = GLfloat(crop.right) / GLfloat(s.w);
+ GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.h);
+
TexCoords texCoords[4];
- texCoords[0].u = 0;
- texCoords[0].v = 1;
- texCoords[1].u = 0;
- texCoords[1].v = 0;
- texCoords[2].u = 1;
- texCoords[2].v = 0;
- texCoords[3].u = 1;
- texCoords[3].v = 1;
+ texCoords[0].u = left;
+ texCoords[0].v = top;
+ texCoords[1].u = left;
+ texCoords[1].v = bottom;
+ texCoords[2].u = right;
+ texCoords[2].v = bottom;
+ texCoords[3].u = right;
+ texCoords[3].v = top;
+ for (int i = 0; i < 4; i++) {
+ texCoords[i].v = 1.0f - texCoords[i].v;
+ }
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d123d9bc9a..31f6dfdc64 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -78,6 +78,7 @@ public:
uint32_t tint;
Transform transform;
Region transparentRegion;
+ Rect crop;
};
virtual void setName(const String8& name);
@@ -91,6 +92,7 @@ public:
bool setMatrix(const layer_state_t::matrix22_t& matrix);
bool setTransparentRegionHint(const Region& opaque);
bool setFlags(uint8_t flags, uint8_t mask);
+ bool setCrop(const Rect& crop);
void commitTransaction();
bool requestTransaction();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0d4d2b97ae..35a7fd51b0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1352,6 +1352,10 @@ uint32_t SurfaceFlinger::setClientStateLocked(
if (layer->setFlags(s.flags, s.mask))
flags |= eTraversalNeeded;
}
+ if (what & eCropChanged) {
+ if (layer->setCrop(s.crop))
+ flags |= eTraversalNeeded;
+ }
}
return flags;
}