diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index d0031fb3d..430a409fc 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -62,6 +62,13 @@ public: eDisplayIdHdmi = 1 }; + enum Rotation { + eRotateNone = 0, + eRotate90 = 1, + eRotate180 = 2, + eRotate270 = 3 + }; + /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission */ @@ -130,7 +137,8 @@ public: const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform) = 0; + bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 46801686b..4d65c5647 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -106,7 +106,8 @@ public: const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform) + bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -118,6 +119,7 @@ public: data.writeInt32(minLayerZ); data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); + data.writeInt32(static_cast(rotation)); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); return reply.readInt32(); } @@ -329,10 +331,12 @@ status_t BnSurfaceComposer::onTransact( uint32_t minLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); bool useIdentityTransform = static_cast(data.readInt32()); + uint32_t rotation = data.readInt32(); status_t res = captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform); + useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index bf42b77d1..564f9748e 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -288,7 +288,8 @@ void DisplayDevice::setViewportAndProjection() const { size_t w = mDisplayWidth; size_t h = mDisplayHeight; Rect sourceCrop(0, 0, w, h); - mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, false); + mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, + false, Transform::ROT_0); } // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp index d1e324c7c..c2768f33a 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "GLES11RenderEngine.h" #include "Mesh.h" @@ -74,7 +75,8 @@ size_t GLES11RenderEngine::getMaxViewportDims() const { } void GLES11RenderEngine::setViewportAndProjection( - size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) { + size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, + Transform::orientation_flags rotation) { glViewport(0, 0, vpw, vph); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -91,6 +93,23 @@ void GLES11RenderEngine::setViewportAndProjection( } else { glOrthof(l, r, b, t, 0, 1); } + + switch (rotation) { + case Transform::ROT_0: + break; + case Transform::ROT_90: + glRotatef(90, 0, 0, 1); + break; + case Transform::ROT_180: + glRotatef(180, 0, 0, 1); + break; + case Transform::ROT_270: + glRotatef(270, 0, 0, 1); + break; + default: + break; + } + glMatrixMode(GL_MODELVIEW); } diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h index 1a945929f..87eb3e4e4 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h @@ -22,6 +22,7 @@ #include #include +#include #include "RenderEngine.h" @@ -50,7 +51,7 @@ protected: virtual void dump(String8& result); virtual void setViewportAndProjection(size_t vpw, size_t vph, - Rect sourceCrop, size_t hwh, bool yswap); + Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation); virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha); virtual void setupDimLayerBlending(int alpha); virtual void setupLayerTexturing(const Texture& texture); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 8c1f04e56..8ebafbced 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include "GLES20RenderEngine.h" #include "Program.h" @@ -80,7 +82,8 @@ size_t GLES20RenderEngine::getMaxViewportDims() const { } void GLES20RenderEngine::setViewportAndProjection( - size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) { + size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, + Transform::orientation_flags rotation) { size_t l = sourceCrop.left; size_t r = sourceCrop.right; @@ -96,6 +99,24 @@ void GLES20RenderEngine::setViewportAndProjection( m = mat4::ortho(l, r, b, t, 0, 1); } + // Apply custom rotation to the projection. + float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; + switch (rotation) { + case Transform::ROT_0: + break; + case Transform::ROT_90: + m = mat4::rotate(rot90InRadians, vec3(0,0,1)) * m; + break; + case Transform::ROT_180: + m = mat4::rotate(rot90InRadians * 2.0f, vec3(0,0,1)) * m; + break; + case Transform::ROT_270: + m = mat4::rotate(rot90InRadians * 3.0f, vec3(0,0,1)) * m; + break; + default: + break; + } + glViewport(0, 0, vpw, vph); mState.setProjectionMatrix(m); mVpWidth = vpw; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index b6d32fce2..3d6243e2e 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -22,6 +22,7 @@ #include #include +#include #include "RenderEngine.h" #include "ProgramCache.h" @@ -65,7 +66,7 @@ protected: virtual void dump(String8& result); virtual void setViewportAndProjection(size_t vpw, size_t vph, - Rect sourceCrop, size_t hwh, bool yswap); + Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation); virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha); virtual void setupDimLayerBlending(int alpha); virtual void setupLayerTexturing(const Texture& texture); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index a2d824235..acbff9b5a 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -24,6 +24,7 @@ #include #include #include +#include #define EGL_NO_CONFIG ((EGLConfig)0) @@ -90,7 +91,7 @@ public: // set-up virtual void checkErrors() const; virtual void setViewportAndProjection(size_t vpw, size_t vph, - Rect sourceCrop, size_t hwh, bool yswap) = 0; + Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0; virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0; virtual void setupDimLayerBlending(int alpha) = 0; virtual void setupLayerTexturing(const Texture& texture) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 70a19e981..4ac9df0a4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2938,7 +2938,7 @@ status_t SurfaceFlinger::captureScreen(const sp& display, const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform) { + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; @@ -2958,6 +2958,27 @@ status_t SurfaceFlinger::captureScreen(const sp& display, } } + // Convert to surfaceflinger's internal rotation type. + Transform::orientation_flags rotationFlags; + switch (rotation) { + case ISurfaceComposer::eRotateNone: + rotationFlags = Transform::ROT_0; + break; + case ISurfaceComposer::eRotate90: + rotationFlags = Transform::ROT_90; + break; + case ISurfaceComposer::eRotate180: + rotationFlags = Transform::ROT_180; + break; + case ISurfaceComposer::eRotate270: + rotationFlags = Transform::ROT_270; + break; + default: + rotationFlags = Transform::ROT_0; + ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); + break; + } + class MessageCaptureScreen : public MessageBase { SurfaceFlinger* flinger; sp display; @@ -2966,6 +2987,7 @@ status_t SurfaceFlinger::captureScreen(const sp& display, uint32_t reqWidth, reqHeight; uint32_t minLayerZ,maxLayerZ; bool useIdentityTransform; + Transform::orientation_flags rotation; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, @@ -2973,11 +2995,12 @@ status_t SurfaceFlinger::captureScreen(const sp& display, const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform) + bool useIdentityTransform, Transform::orientation_flags rotation) : flinger(flinger), display(display), producer(producer), sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), useIdentityTransform(useIdentityTransform), + rotation(rotation), result(PERMISSION_DENIED) { } @@ -2989,7 +3012,7 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp hw(flinger->getDisplayDevice(display)); result = flinger->captureScreenImplLocked(hw, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform); + useIdentityTransform, rotation); static_cast(producer->asBinder().get())->exit(result); return true; } @@ -3012,7 +3035,7 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp msg = new MessageCaptureScreen(this, display, IGraphicBufferProducer::asInterface( wrapper ), sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform); + useIdentityTransform, rotationFlags); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3026,7 +3049,7 @@ void SurfaceFlinger::renderScreenImplLocked( const sp& hw, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool yswap, bool useIdentityTransform) + bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) { ATRACE_CALL(); RenderEngine& engine(getRenderEngine()); @@ -3061,7 +3084,8 @@ void SurfaceFlinger::renderScreenImplLocked( engine.checkErrors(); // set-up our viewport - engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, hw_h, yswap); + engine.setViewportAndProjection( + reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); engine.disableTexturing(); // redraw the screen entirely... @@ -3094,7 +3118,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform) + bool useIdentityTransform, Transform::orientation_flags rotation) { ATRACE_CALL(); @@ -3148,8 +3172,9 @@ status_t SurfaceFlinger::captureScreenImplLocked( // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, true, useIdentityTransform); + renderScreenImplLocked( + hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true, + useIdentityTransform, rotation); // Attempt to create a sync khr object that can produce a sync point. If that // isn't available, create a non-dupable sync object in the fallback path and diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d5547b37a..26f0acfa3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -205,7 +205,7 @@ private: const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform); + bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t getDisplayConfigs(const sp& display, Vector* configs); virtual int getActiveConfig(const sp& display); @@ -313,14 +313,14 @@ private: const sp& hw, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool yswap, bool useIdentityTransform); + bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation); status_t captureScreenImplLocked( const sp& hw, const sp& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform); + bool useIdentityTransform, Transform::orientation_flags rotation); /* ------------------------------------------------------------------------ * EGL