From 97c602c5af5f3ffd69009bf496d86347b71a2b4c Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 19 Jul 2011 15:24:46 -0700 Subject: [PATCH] implement: "Add an ANativeWindow API for SurfaceFlinger to suggest an optimal buffer orientation" Bug: 4487161 Change-Id: I883f34efe542c2a566d04966f873374f40c50092 --- include/gui/ISurfaceTexture.h | 7 +++- include/gui/SurfaceTexture.h | 3 +- include/gui/SurfaceTextureClient.h | 12 ++++++ libs/gui/ISurfaceTexture.cpp | 13 +++++- libs/gui/SurfaceTexture.cpp | 8 +++- libs/gui/SurfaceTextureClient.cpp | 40 ++++++++++++------- libs/ui/FramebufferNativeWindow.cpp | 12 ++++++ services/surfaceflinger/Layer.cpp | 31 ++++++++------ .../surfaceflinger/SurfaceTextureLayer.cpp | 14 +++++++ services/surfaceflinger/SurfaceTextureLayer.h | 3 ++ services/surfaceflinger/Transform.cpp | 37 +---------------- services/surfaceflinger/clz.h | 35 ++++++++++++++++ 12 files changed, 147 insertions(+), 68 deletions(-) diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h index 37a9b4a24..e76442549 100644 --- a/include/gui/ISurfaceTexture.h +++ b/include/gui/ISurfaceTexture.h @@ -78,7 +78,12 @@ protected: // client for this buffer. The timestamp is measured in nanoseconds, and // must be monotonically increasing. Its other properties (zero point, etc) // are client-dependent, and should be documented by the client. - virtual status_t queueBuffer(int slot, int64_t timestamp) = 0; + // + // outWidth, outHeight and outTransform are filed with the default width + // default height of the window and current transform applied to buffers, + // respectively. + virtual status_t queueBuffer(int slot, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) = 0; // cancelBuffer indicates that the client does not wish to fill in the // buffer associated with slot and transfers ownership of the slot back to diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index e46765e32..945f4bcd6 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -84,7 +84,8 @@ public: // nanoseconds, and must be monotonically increasing. Its other semantics // (zero point, etc) are client-dependent and should be documented by the // client. - virtual status_t queueBuffer(int buf, int64_t timestamp); + virtual status_t queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); virtual void cancelBuffer(int buf); virtual status_t setCrop(const Rect& reg); virtual status_t setTransform(uint32_t transform); diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index 76e7119fe..829d8abf7 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -151,6 +151,18 @@ private: // dequeued format or to mReqFormat if no buffer was dequeued. uint32_t mQueryFormat; + // mDefaultWidth is default width of the window, regardless of the + // set_dimension call + uint32_t mDefaultWidth; + + // mDefaultHeight is default width of the window, regardless of the + // set_dimension call + uint32_t mDefaultHeight; + + // mTransformHint is the transform probably applied to buffers of this + // window. this is only a hint, actual transform may differ. + uint32_t mTransformHint; + // mMutex is the mutex used to prevent concurrent access to the member // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index b4b749280..be90e2eec 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -93,12 +93,16 @@ public: return result; } - virtual status_t queueBuffer(int buf, int64_t timestamp) { + virtual status_t queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); data.writeInt64(timestamp); remote()->transact(QUEUE_BUFFER, data, &reply); + *outWidth = reply.readInt32(); + *outHeight = reply.readInt32(); + *outTransform = reply.readInt32(); status_t result = reply.readInt32(); return result; } @@ -226,7 +230,12 @@ status_t BnSurfaceTexture::onTransact( CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); int64_t timestamp = data.readInt64(); - status_t result = queueBuffer(buf, timestamp); + uint32_t outWidth, outHeight, outTransform; + status_t result = queueBuffer(buf, timestamp, + &outWidth, &outHeight, &outTransform); + reply->writeInt32(outWidth); + reply->writeInt32(outHeight); + reply->writeInt32(outTransform); reply->writeInt32(result); return NO_ERROR; } break; diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 3ab6c79d7..0f08570ef 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -402,7 +402,8 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { return err; } -status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { +status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { LOGV("SurfaceTexture::queueBuffer"); sp listener; @@ -463,6 +464,11 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { if (listener != 0) { listener->onFrameAvailable(); } + + *outWidth = mDefaultWidth; + *outHeight = mDefaultHeight; + *outTransform = 0; + return OK; } diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 68475e961..1dc6cd2cf 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -222,26 +222,38 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { if (i < 0) { return i; } - mSurfaceTexture->queueBuffer(i, timestamp); + mSurfaceTexture->queueBuffer(i, timestamp, + &mDefaultWidth, &mDefaultHeight, &mTransformHint); return OK; } int SurfaceTextureClient::query(int what, int* value) const { LOGV("SurfaceTextureClient::query"); - switch (what) { - case NATIVE_WINDOW_FORMAT: - if (mReqFormat) { - *value = mReqFormat; - return NO_ERROR; + { // scope for the lock + Mutex::Autolock lock(mMutex); + switch (what) { + case NATIVE_WINDOW_FORMAT: + if (mReqFormat) { + *value = mReqFormat; + return NO_ERROR; + } + break; + case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: + *value = 0; + return NO_ERROR; + case NATIVE_WINDOW_CONCRETE_TYPE: + *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; + return NO_ERROR; + case NATIVE_WINDOW_DEFAULT_WIDTH: + *value = mDefaultWidth; + return NO_ERROR; + case NATIVE_WINDOW_DEFAULT_HEIGHT: + *value = mDefaultHeight; + return NO_ERROR; + case NATIVE_WINDOW_TRANSFORM_HINT: + *value = mTransformHint; + return NO_ERROR; } - break; - case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: - // TODO: this is not needed anymore - *value = 0; - return NO_ERROR; - case NATIVE_WINDOW_CONCRETE_TYPE: - *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; - return NO_ERROR; } return mSurfaceTexture->query(what, value); } diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index e2772a7fc..412552ec8 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -289,6 +289,18 @@ int FramebufferNativeWindow::query(const ANativeWindow* window, case NATIVE_WINDOW_CONCRETE_TYPE: *value = NATIVE_WINDOW_FRAMEBUFFER; return NO_ERROR; + case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: + *value = 0; + return NO_ERROR; + case NATIVE_WINDOW_DEFAULT_WIDTH: + *value = fb->width; + return NO_ERROR; + case NATIVE_WINDOW_DEFAULT_HEIGHT: + *value = fb->height; + return NO_ERROR; + case NATIVE_WINDOW_TRANSFORM_HINT: + *value = 0; + return NO_ERROR; } *value = 0; return BAD_VALUE; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c29aecab9..e0268fa06 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -44,10 +44,6 @@ namespace android { -template inline T min(T a, T b) { - return a newFrontBuffer(mActiveBuffer); - if ((newFrontBuffer->getWidth() == front.requested_w && - newFrontBuffer->getHeight() == front.requested_h) || - isFixedSize()) + + if ((front.w != front.requested_w) || + (front.h != front.requested_h)) { - if ((front.w != front.requested_w) || - (front.h != front.requested_h)) + // check that we received a buffer of the right size + // (Take the buffer's orientation into account) + sp newFrontBuffer(mActiveBuffer); + uint32_t bufWidth = newFrontBuffer->getWidth(); + uint32_t bufHeight = newFrontBuffer->getHeight(); + if (mCurrentTransform & Transform::ROT_90) { + swap(bufWidth, bufHeight); + } + + if (isFixedSize() || + (bufWidth == front.requested_w && + bufHeight == front.requested_h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed @@ -483,10 +488,10 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // recompute visible region recomputeVisibleRegions = true; - } - // we now have the correct size, unfreeze the screen - mFreezeLock.clear(); + // we now have the correct size, unfreeze the screen + mFreezeLock.clear(); + } } } } diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index a586d590f..11f61ccb1 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -52,6 +52,20 @@ status_t SurfaceTextureLayer::setBufferCount(int bufferCount) { return res; } +status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { + + status_t res = SurfaceTexture::queueBuffer(buf, timestamp, + outWidth, outHeight, outTransform); + + sp layer(mLayer.promote()); + if (layer != NULL) { + *outTransform = layer->getOrientation(); + } + + return res; +} + status_t SurfaceTextureLayer::dequeueBuffer(int *buf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h index 7faff548f..29a9cbeaa 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.h +++ b/services/surfaceflinger/SurfaceTextureLayer.h @@ -45,6 +45,9 @@ public: virtual status_t setBufferCount(int bufferCount); protected: + virtual status_t queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); + virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); }; diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 4cedcbf86..24d5f9ac9 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -20,6 +20,7 @@ #include #include +#include "clz.h" #include "Transform.h" // --------------------------------------------------------------------------- @@ -28,42 +29,6 @@ namespace android { // --------------------------------------------------------------------------- -template -static inline T min(T a, T b) { - return a -static inline T min(T a, T b, T c) { - return min(a, min(b, c)); -} -template -static inline T min(T a, T b, T c, T d) { - return min(a, b, min(c, d)); -} - -template -static inline T max(T a, T b) { - return a>b ? a : b; -} -template -static inline T max(T a, T b, T c) { - return max(a, max(b, c)); -} -template -static inline T max(T a, T b, T c, T d) { - return max(a, b, max(c, d)); -} - -template -static inline -void swap(T& a, T& b) { - T t(a); - a = b; - b = t; -} - -// --------------------------------------------------------------------------- - Transform::Transform() { reset(); } diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h index ca445553f..a4c5262dd 100644 --- a/services/surfaceflinger/clz.h +++ b/services/surfaceflinger/clz.h @@ -24,6 +24,41 @@ int inline clz(int32_t x) { return __builtin_clz(x); } +template +static inline T min(T a, T b) { + return a +static inline T min(T a, T b, T c) { + return min(a, min(b, c)); +} +template +static inline T min(T a, T b, T c, T d) { + return min(a, b, min(c, d)); +} + +template +static inline T max(T a, T b) { + return a>b ? a : b; +} +template +static inline T max(T a, T b, T c) { + return max(a, max(b, c)); +} +template +static inline T max(T a, T b, T c, T d) { + return max(a, b, max(c, d)); +} + +template +static inline +void swap(T& a, T& b) { + T t(a); + a = b; + b = t; +} + + }; // namespace android #endif /* ANDROID_SURFACE_FLINGER_CLZ_H */