summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2010-08-24 16:23:12 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-08-24 16:23:12 -0700
commit8395b4625b96f2133e2e4f595fdc69fbe222e4fc (patch)
tree6b237941de4da8b1cb45be7f31ac2d695ee0f9ae
parent6b6ae996b2e84af030397cff3a7f0087de93e01c (diff)
parente96aa3e859cb747e241dfa2999fcd142a688ed57 (diff)
downloadframeworks_base-8395b4625b96f2133e2e4f595fdc69fbe222e4fc.zip
frameworks_base-8395b4625b96f2133e2e4f595fdc69fbe222e4fc.tar.gz
frameworks_base-8395b4625b96f2133e2e4f595fdc69fbe222e4fc.tar.bz2
Merge "fix [2931513] Add support for setting the orientation of an ANativeWindow" into gingerbread
-rw-r--r--include/private/surfaceflinger/SharedBufferStack.h18
-rw-r--r--include/surfaceflinger/Surface.h3
-rw-r--r--include/ui/egl/android_natives.h29
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp46
-rw-r--r--libs/surfaceflinger_client/Surface.cpp22
-rw-r--r--services/surfaceflinger/Layer.cpp9
-rw-r--r--services/surfaceflinger/LayerBase.cpp107
-rw-r--r--services/surfaceflinger/LayerBase.h8
-rw-r--r--services/surfaceflinger/LayerBlur.cpp2
-rw-r--r--services/surfaceflinger/LayerBuffer.cpp2
-rw-r--r--services/surfaceflinger/TextureManager.h3
11 files changed, 212 insertions, 37 deletions
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 1eb178e..d016dfa 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -54,11 +54,6 @@ class SharedClient;
// ----------------------------------------------------------------------------
-// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
-// 4 * (11 + 7 + (1 + 2*7)*16) * 31
-// 1032 * 31
-// = ~27 KiB (31992)
-
class SharedBufferStack
{
friend class SharedClient;
@@ -85,7 +80,7 @@ public:
};
struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
- static const unsigned int NUM_RECT_MAX = 6;
+ static const unsigned int NUM_RECT_MAX = 5;
uint32_t count;
SmallRect rects[NUM_RECT_MAX];
};
@@ -93,13 +88,18 @@ public:
struct BufferData {
FlatRegion dirtyRegion;
SmallRect crop;
+ uint8_t transform;
+ uint8_t reserved[3];
};
SharedBufferStack();
void init(int32_t identity);
status_t setDirtyRegion(int buffer, const Region& reg);
status_t setCrop(int buffer, const Rect& reg);
+ status_t setTransform(int buffer, uint8_t transform);
Region getDirtyRegion(int buffer) const;
+ Rect getCrop(int buffer) const;
+ uint32_t getTransform(int buffer) const;
// these attributes are part of the conditions/updates
volatile int32_t head; // server's current front buffer
@@ -117,7 +117,7 @@ public:
int32_t reserved32[1];
Statistics stats;
int32_t reserved;
- BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes
+ BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
};
// ----------------------------------------------------------------------------
@@ -206,7 +206,7 @@ public:
bool needNewBuffer(int buffer) const;
status_t setDirtyRegion(int buffer, const Region& reg);
status_t setCrop(int buffer, const Rect& reg);
-
+ status_t setTransform(int buffer, uint32_t transform);
class SetBufferCountCallback {
friend class SharedBufferClient;
@@ -275,6 +275,8 @@ public:
status_t reallocateAllExcept(int buffer);
int32_t getQueuedCount() const;
Region getDirtyRegion(int buffer) const;
+ Rect getCrop(int buffer) const;
+ uint32_t getTransform(int buffer) const;
status_t resize(int newNumBuffers);
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 294c867..7c5a39b 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -216,6 +216,7 @@ private:
int dispatch_crop(va_list args);
int dispatch_set_buffer_count(va_list args);
int dispatch_set_buffers_geometry(va_list args);
+ int dispatch_set_buffers_transform(va_list args);
void setUsage(uint32_t reqUsage);
int connect(int api);
@@ -223,6 +224,7 @@ private:
int crop(Rect const* rect);
int setBufferCount(int bufferCount);
int setBuffersGeometry(int w, int h, int format);
+ int setBuffersTransform(int transform);
/*
* private stuff...
@@ -278,6 +280,7 @@ private:
Rect mSwapRectangle;
int mConnected;
Rect mNextBufferCrop;
+ uint32_t mNextBufferTransform;
BufferInfo mBufferInfo;
// protected by mSurfaceLock. These are also used from lock/unlock
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index ca89b06..d59d72b 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -85,6 +85,7 @@ enum {
NATIVE_WINDOW_SET_CROP,
NATIVE_WINDOW_SET_BUFFER_COUNT,
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
};
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@@ -92,6 +93,20 @@ enum {
NATIVE_WINDOW_API_EGL = 1
};
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
+enum {
+ /* flip source image horizontally */
+ NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
+ /* flip source image vertically */
+ NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+ /* rotate source image 90 degrees clock-wise */
+ NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+ /* rotate source image 180 degrees */
+ NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+ /* rotate source image 270 degrees clock-wise */
+ NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+};
+
struct ANativeWindow
{
#ifdef __cplusplus
@@ -196,6 +211,7 @@ struct ANativeWindow
* NATIVE_WINDOW_SET_CROP
* NATIVE_WINDOW_SET_BUFFER_COUNT
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
+ * NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
*
*/
@@ -298,6 +314,19 @@ static inline int native_window_set_buffers_geometry(
w, h, format);
}
+/*
+ * native_window_set_buffers_transform(..., int transform)
+ * All buffers queued after this call will be displayed transformed according
+ * to the transform parameter specified.
+ */
+static inline int native_window_set_buffers_transform(
+ ANativeWindow* window,
+ int transform)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+ transform);
+}
+
// ---------------------------------------------------------------------------
/* FIXME: this is legacy for pixmaps */
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 156a7db..4ad9f86 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -75,6 +75,14 @@ status_t SharedBufferStack::setCrop(int buffer, const Rect& crop)
return NO_ERROR;
}
+status_t SharedBufferStack::setTransform(int buffer, uint8_t transform)
+{
+ if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+ return BAD_INDEX;
+ buffers[buffer].transform = transform;
+ return NO_ERROR;
+}
+
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
{
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
@@ -137,6 +145,26 @@ Region SharedBufferStack::getDirtyRegion(int buffer) const
return res;
}
+Rect SharedBufferStack::getCrop(int buffer) const
+{
+ Rect res(-1, -1);
+ if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+ return res;
+ res.left = buffers[buffer].crop.l;
+ res.top = buffers[buffer].crop.t;
+ res.right = buffers[buffer].crop.r;
+ res.bottom = buffers[buffer].crop.b;
+ return res;
+}
+
+uint32_t SharedBufferStack::getTransform(int buffer) const
+{
+ if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+ return 0;
+ return buffers[buffer].transform;
+}
+
+
// ----------------------------------------------------------------------------
SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
@@ -433,6 +461,12 @@ status_t SharedBufferClient::setCrop(int buf, const Rect& crop)
return stack.setCrop(buf, crop);
}
+status_t SharedBufferClient::setTransform(int buf, uint32_t transform)
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.setTransform(buf, uint8_t(transform));
+}
+
status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
{
SharedBufferStack& stack( *mSharedStack );
@@ -549,6 +583,18 @@ Region SharedBufferServer::getDirtyRegion(int buf) const
return stack.getDirtyRegion(buf);
}
+Rect SharedBufferServer::getCrop(int buf) const
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.getCrop(buf);
+}
+
+uint32_t SharedBufferServer::getTransform(int buf) const
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.getTransform(buf);
+}
+
/*
* NOTE: this is not thread-safe on the server-side, meaning
* 'head' cannot move during this operation. The client-side
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 5ab72cd..cb76091 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -422,8 +422,10 @@ void Surface::init()
const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
+ mNextBufferTransform = 0;
mConnected = 0;
mSwapRectangle.makeInvalid();
+ mNextBufferCrop = Rect(0,0);
// two buffers by default
mBuffers.setCapacity(2);
mBuffers.insertAt(0, 2);
@@ -631,6 +633,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
}
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
+ mSharedBufferClient->setTransform(bufIdx, mNextBufferTransform);
mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
err = mSharedBufferClient->queue(bufIdx);
@@ -685,6 +688,9 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
res = dispatch_set_buffers_geometry( args );
break;
+ case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+ res = dispatch_set_buffers_transform( args );
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -719,6 +725,11 @@ int Surface::dispatch_set_buffers_geometry(va_list args) {
return setBuffersGeometry(w, h, f);
}
+int Surface::dispatch_set_buffers_transform(va_list args) {
+ int transform = va_arg(args, int);
+ return setBuffersTransform(transform);
+}
+
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
@@ -765,6 +776,10 @@ int Surface::disconnect(int api)
int Surface::crop(Rect const* rect)
{
+ // empty/invalid rects are not allowed
+ if (rect->isEmpty())
+ return BAD_VALUE;
+
Mutex::Autolock _l(mSurfaceLock);
// TODO: validate rect size
mNextBufferCrop = *rect;
@@ -804,6 +819,13 @@ int Surface::setBuffersGeometry(int w, int h, int format)
return NO_ERROR;
}
+int Surface::setBuffersTransform(int transform)
+{
+ Mutex::Autolock _l(mSurfaceLock);
+ mNextBufferTransform = transform;
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
int Surface::getConnectedApi() const
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 629d993..6f3c66d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -473,9 +473,9 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
return;
}
- // get the dirty region
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
if (newFrontBuffer != NULL) {
+ // get the dirty region
// compute the posted region
const Region dirty(lcblk->getDirtyRegion(buf));
mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
@@ -511,6 +511,13 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// we now have the correct size, unfreeze the screen
mFreezeLock.clear();
}
+
+ // get the crop region
+ setBufferCrop( lcblk->getCrop(buf) );
+
+ // get the transformation
+ setBufferTransform( lcblk->getTransform(buf) );
+
} else {
// this should not happen unless we ran out of memory while
// allocating the buffer. we're hoping that things will get back
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 91ac915..6fc5010 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -54,6 +54,8 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
mFlags = hw.getFlags();
+ mBufferCrop.makeInvalid();
+ mBufferTransform = 0;
}
LayerBase::~LayerBase()
@@ -345,6 +347,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
clearWithOpenGL(clip,0,0,0,0);
}
+template <typename T>
+static inline
+void swap(T& a, T& b) {
+ T t(a);
+ a = b;
+ b = t;
+}
+
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
@@ -378,38 +388,73 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
}
}
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- const GLfloat texCoords[4][2] = {
- { 0, 0 },
- { 0, 1 },
- { 1, 1 },
- { 1, 0 }
+ /*
+ * compute texture coordinates
+ * here, we handle NPOT, cropping and buffer transformations
+ */
+
+ GLfloat cl, ct, cr, cb;
+ if (!mBufferCrop.isEmpty()) {
+ // source is cropped
+ const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
+ const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
+ cl = mBufferCrop.left * us;
+ ct = mBufferCrop.top * vs;
+ cr = mBufferCrop.right * us;
+ cb = mBufferCrop.bottom * vs;
+ } else {
+ cl = 0;
+ ct = 0;
+ cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
+ cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
+ }
+
+ struct TexCoords {
+ GLfloat u;
+ GLfloat v;
+ };
+
+ enum {
+ // name of the corners in the texture map
+ LB = 0, // left-bottom
+ LT = 1, // left-top
+ RT = 2, // right-top
+ RB = 3 // right-bottom
};
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ // vertices in screen space
+ int vLT = LB;
+ int vLB = LT;
+ int vRB = RT;
+ int vRT = RB;
// the texture's source is rotated
- switch (texture.transform) {
- case HAL_TRANSFORM_ROT_90:
- glTranslatef(0, 1, 0);
- glRotatef(-90, 0, 0, 1);
- break;
- case HAL_TRANSFORM_ROT_180:
- glTranslatef(1, 1, 0);
- glRotatef(-180, 0, 0, 1);
- break;
- case HAL_TRANSFORM_ROT_270:
- glTranslatef(1, 0, 0);
- glRotatef(-270, 0, 0, 1);
- break;
+ uint32_t transform = mBufferTransform;
+ if (transform & HAL_TRANSFORM_ROT_90) {
+ vLT = RB;
+ vLB = LB;
+ vRB = LT;
+ vRT = RT;
}
-
- if (texture.NPOTAdjust) {
- glScalef(texture.wScale, texture.hScale, 1.0f);
+ if (transform & HAL_TRANSFORM_FLIP_V) {
+ swap(vLT, vLB);
+ swap(vRB, vRT);
+ }
+ if (transform & HAL_TRANSFORM_FLIP_H) {
+ swap(vLT, vRB);
+ swap(vLB, vRT);
}
+ TexCoords texCoords[4];
+ texCoords[vLT].u = cl;
+ texCoords[vLT].v = ct;
+ texCoords[vLB].u = cl;
+ texCoords[vLB].v = cb;
+ texCoords[vRB].u = cr;
+ texCoords[vRB].v = cb;
+ texCoords[vRT].u = cr;
+ texCoords[vRT].v = ct;
+
if (needsDithering()) {
glEnable(GL_DITHER);
} else {
@@ -420,6 +465,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glVertexPointer(2, GL_FLOAT, 0, mVertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ Region::const_iterator it = clip.begin();
+ Region::const_iterator const end = clip.end();
while (it != end) {
const Rect& r = *it++;
const GLint sy = fbHeight - (r.top + r.height());
@@ -429,6 +476,16 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
+void LayerBase::setBufferCrop(const Rect& crop) {
+ if (!crop.isEmpty()) {
+ mBufferCrop = crop;
+ }
+}
+
+void LayerBase::setBufferTransform(uint32_t transform) {
+ mBufferTransform = transform;
+}
+
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 22bf857..8cba287 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -226,9 +226,17 @@ protected:
void clearWithOpenGL(const Region& clip) const;
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
+ // these must be called from the post/drawing thread
+ void setBufferCrop(const Rect& crop);
+ void setBufferTransform(uint32_t transform);
+
sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
+ // post/drawing thread
+ Rect mBufferCrop;
+ uint32_t mBufferTransform;
+
// cached during validateVisibility()
bool mNeedsFiltering;
int32_t mOrientation;
diff --git a/services/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp
index 64a43c7..2ee21b9 100644
--- a/services/surfaceflinger/LayerBlur.cpp
+++ b/services/surfaceflinger/LayerBlur.cpp
@@ -241,6 +241,8 @@ void LayerBlur::onDraw(const Region& clip) const
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
}
}
diff --git a/services/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp
index 5f83636..0240748 100644
--- a/services/surfaceflinger/LayerBuffer.cpp
+++ b/services/surfaceflinger/LayerBuffer.cpp
@@ -485,7 +485,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
mTextureManager.loadTexture(&mTexture, dirty, t);
}
- mTexture.transform = mBufferHeap.transform;
+ mLayer.setBufferTransform(mBufferHeap.transform);
mLayer.drawWithOpenGL(clip, mTexture);
}
diff --git a/services/surfaceflinger/TextureManager.h b/services/surfaceflinger/TextureManager.h
index c7c14e7..18c4348 100644
--- a/services/surfaceflinger/TextureManager.h
+++ b/services/surfaceflinger/TextureManager.h
@@ -40,12 +40,11 @@ class GraphicBuffer;
struct Image {
enum { TEXTURE_2D=0, TEXTURE_EXTERNAL=1 };
Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0),
- transform(0), dirty(1), target(TEXTURE_2D) { }
+ dirty(1), target(TEXTURE_2D) { }
GLuint name;
EGLImageKHR image;
GLuint width;
GLuint height;
- uint32_t transform;
unsigned dirty : 1;
unsigned target : 1;
};