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:
parent
7eff26a02a
commit
c3ebe66b49
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user