Add rotation to surfaceflingers screen cap.

+ This is needed so that activity manager does not
  have to do cpu side rotations when capturing recents
  thumbnails.

Change-Id: If998008e675ad01305db8399fd643cf4608b7025
This commit is contained in:
Riley Andrews 2014-09-04 16:20:31 -07:00
parent 7eff26a02a
commit c3ebe66b49
10 changed files with 102 additions and 21 deletions

View File

@ -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<IGraphicBufferProducer>& 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.
*

View File

@ -106,7 +106,8 @@ public:
const sp<IGraphicBufferProducer>& 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<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(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<bool>(data.readInt32());
uint32_t rotation = data.readInt32();
status_t res = captureScreen(display, producer,
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
useIdentityTransform);
useIdentityTransform,
static_cast<ISurfaceComposer::Rotation>(rotation));
reply->writeInt32(res);
return NO_ERROR;
}

View File

@ -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);
}
// ----------------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
#include <utils/String8.h>
#include <cutils/compiler.h>
#include <gui/ISurfaceComposer.h>
#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);
}

View File

@ -22,6 +22,7 @@
#include <sys/types.h>
#include <GLES/gl.h>
#include <Transform.h>
#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);

View File

@ -25,6 +25,8 @@
#include <utils/Trace.h>
#include <cutils/compiler.h>
#include <gui/ISurfaceComposer.h>
#include <math.h>
#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<float>(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;

View File

@ -22,6 +22,7 @@
#include <sys/types.h>
#include <GLES2/gl2.h>
#include <Transform.h>
#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);

View File

@ -24,6 +24,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <ui/mat4.h>
#include <Transform.h>
#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;

View File

@ -2938,7 +2938,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& 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<IBinder>& 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<IBinder> display;
@ -2966,6 +2987,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& 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<IBinder>& display,
const sp<IGraphicBufferProducer>& 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<IBinder>& display,
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
result = flinger->captureScreenImplLocked(hw, producer,
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
useIdentityTransform);
useIdentityTransform, rotation);
static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
return true;
}
@ -3012,7 +3035,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
sp<MessageBase> 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<const DisplayDevice>& 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<IGraphicBufferProducer>& 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

View File

@ -205,7 +205,7 @@ private:
const sp<IGraphicBufferProducer>& 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<IBinder>& display,
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
@ -313,14 +313,14 @@ private:
const sp<const DisplayDevice>& 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<const DisplayDevice>& hw,
const sp<IGraphicBufferProducer>& producer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useIdentityTransform);
bool useIdentityTransform, Transform::orientation_flags rotation);
/* ------------------------------------------------------------------------
* EGL