Merge "SurfaceFlinger: Add sourceCrop to screenshot"
This commit is contained in:
commit
3d5c8a98c1
@ -41,6 +41,7 @@ class DisplayState;
|
||||
class DisplayInfo;
|
||||
class IDisplayEventConnection;
|
||||
class IMemoryHeap;
|
||||
class Rect;
|
||||
|
||||
/*
|
||||
* This class defines the Binder IPC interface for accessing various
|
||||
@ -131,11 +132,10 @@ public:
|
||||
*/
|
||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform) = 0;
|
||||
|
||||
|
||||
/* Clears the frame statistics for animations.
|
||||
*
|
||||
* Requires the ACCESS_SURFACE_FLINGER permission.
|
||||
|
@ -180,10 +180,12 @@ private:
|
||||
class ScreenshotClient
|
||||
{
|
||||
public:
|
||||
// if cropping isn't required, callers may pass in a default Rect, e.g.:
|
||||
// capture(display, producer, Rect(), reqWidth, ...);
|
||||
static status_t capture(
|
||||
const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform);
|
||||
|
||||
@ -197,13 +199,16 @@ public:
|
||||
ScreenshotClient();
|
||||
~ScreenshotClient();
|
||||
|
||||
// frees the previous screenshot and capture a new one
|
||||
status_t update(const sp<IBinder>& display, bool useIdentityTransform);
|
||||
// frees the previous screenshot and captures a new one
|
||||
// if cropping isn't required, callers may pass in a default Rect, e.g.:
|
||||
// update(display, Rect(), useIdentityTransform);
|
||||
status_t update(const sp<IBinder>& display,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, bool useIdentityTransform);
|
||||
status_t update(const sp<IBinder>& display,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
bool useIdentityTransform);
|
||||
status_t update(const sp<IBinder>& display,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform);
|
||||
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
|
||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform)
|
||||
{
|
||||
@ -112,6 +112,7 @@ public:
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(display);
|
||||
data.writeStrongBinder(producer->asBinder());
|
||||
data.write(sourceCrop);
|
||||
data.writeInt32(reqWidth);
|
||||
data.writeInt32(reqHeight);
|
||||
data.writeInt32(minLayerZ);
|
||||
@ -328,6 +329,8 @@ status_t BnSurfaceComposer::onTransact(
|
||||
sp<IBinder> display = data.readStrongBinder();
|
||||
sp<IGraphicBufferProducer> producer =
|
||||
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
|
||||
Rect sourceCrop;
|
||||
data.read(sourceCrop);
|
||||
uint32_t reqWidth = data.readInt32();
|
||||
uint32_t reqHeight = data.readInt32();
|
||||
uint32_t minLayerZ = data.readInt32();
|
||||
@ -335,7 +338,7 @@ status_t BnSurfaceComposer::onTransact(
|
||||
bool useIdentityTransform = static_cast<bool>(data.readInt32());
|
||||
|
||||
status_t res = captureScreen(display, producer,
|
||||
reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||
useIdentityTransform);
|
||||
reply->writeInt32(res);
|
||||
return NO_ERROR;
|
||||
|
@ -676,11 +676,11 @@ status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) {
|
||||
status_t ScreenshotClient::capture(
|
||||
const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform) {
|
||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
||||
if (s == NULL) return NO_INIT;
|
||||
return s->captureScreen(display, producer,
|
||||
return s->captureScreen(display, producer, sourceCrop,
|
||||
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
|
||||
}
|
||||
|
||||
@ -704,7 +704,7 @@ sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
|
||||
}
|
||||
|
||||
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform) {
|
||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
||||
@ -717,7 +717,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||
mHaveBuffer = false;
|
||||
}
|
||||
|
||||
status_t err = s->captureScreen(display, mProducer,
|
||||
status_t err = s->captureScreen(display, mProducer, sourceCrop,
|
||||
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
@ -729,16 +729,16 @@ status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||
status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
|
||||
bool useIdentityTransform) {
|
||||
return ScreenshotClient::update(display, 0, 0, 0, -1UL,
|
||||
return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1UL,
|
||||
useIdentityTransform);
|
||||
}
|
||||
|
||||
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||
status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
|
||||
uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
|
||||
return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL,
|
||||
useIdentityTransform);
|
||||
return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
|
||||
0, -1UL, useIdentityTransform);
|
||||
}
|
||||
|
||||
void ScreenshotClient::release() {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <gui/Surface.h>
|
||||
#include <gui/SurfaceComposerClient.h>
|
||||
#include <gui/BufferItemConsumer.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <private/gui/ComposerService.h>
|
||||
@ -94,7 +95,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
|
||||
sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
|
||||
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
|
||||
sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
|
||||
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer,
|
||||
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
|
||||
64, 64, 0, 0x7fffffff, false));
|
||||
|
||||
// Set the PROTECTED usage bit and verify that the screenshot fails. Note
|
||||
@ -123,7 +124,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
|
||||
&buf));
|
||||
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
|
||||
}
|
||||
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer,
|
||||
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
|
||||
64, 64, 0, 0x7fffffff, false));
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,8 @@ EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
|
||||
void DisplayDevice::setViewportAndProjection() const {
|
||||
size_t w = mDisplayWidth;
|
||||
size_t h = mDisplayHeight;
|
||||
mFlinger->getRenderEngine().setViewportAndProjection(w, h, w, h, false);
|
||||
Rect sourceCrop(0, 0, w, h);
|
||||
mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, false);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <utils/String8.h>
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
@ -72,13 +74,23 @@ size_t GLES11RenderEngine::getMaxViewportDims() const {
|
||||
}
|
||||
|
||||
void GLES11RenderEngine::setViewportAndProjection(
|
||||
size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
|
||||
size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
|
||||
glViewport(0, 0, vpw, vph);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
// put the origin in the left-bottom corner
|
||||
if (yswap) glOrthof(0, w, h, 0, 0, 1);
|
||||
else glOrthof(0, w, 0, h, 0, 1);
|
||||
|
||||
size_t l = sourceCrop.left;
|
||||
size_t r = sourceCrop.right;
|
||||
|
||||
// In GL, (0, 0) is the bottom-left corner, so flip y coordinates
|
||||
size_t t = hwh - sourceCrop.top;
|
||||
size_t b = hwh - sourceCrop.bottom;
|
||||
|
||||
if (yswap) {
|
||||
glOrthof(l, r, t, b, 0, 1);
|
||||
} else {
|
||||
glOrthof(l, r, b, t, 0, 1);
|
||||
}
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ protected:
|
||||
virtual ~GLES11RenderEngine();
|
||||
|
||||
virtual void dump(String8& result);
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph,
|
||||
Rect sourceCrop, size_t hwh, bool yswap);
|
||||
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
|
||||
virtual void setupDimLayerBlending(int alpha);
|
||||
virtual void setupLayerTexturing(const Texture& texture);
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Trace.h>
|
||||
|
||||
@ -78,10 +80,21 @@ size_t GLES20RenderEngine::getMaxViewportDims() const {
|
||||
}
|
||||
|
||||
void GLES20RenderEngine::setViewportAndProjection(
|
||||
size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
|
||||
size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
|
||||
|
||||
size_t l = sourceCrop.left;
|
||||
size_t r = sourceCrop.right;
|
||||
|
||||
// In GL, (0, 0) is the bottom-left corner, so flip y coordinates
|
||||
size_t t = hwh - sourceCrop.top;
|
||||
size_t b = hwh - sourceCrop.bottom;
|
||||
|
||||
mat4 m;
|
||||
if (yswap) m = mat4::ortho(0, w, h, 0, 0, 1);
|
||||
else m = mat4::ortho(0, w, 0, h, 0, 1);
|
||||
if (yswap) {
|
||||
m = mat4::ortho(l, r, t, b, 0, 1);
|
||||
} else {
|
||||
m = mat4::ortho(l, r, b, t, 0, 1);
|
||||
}
|
||||
|
||||
glViewport(0, 0, vpw, vph);
|
||||
mState.setProjectionMatrix(m);
|
||||
|
@ -64,7 +64,8 @@ protected:
|
||||
virtual ~GLES20RenderEngine();
|
||||
|
||||
virtual void dump(String8& result);
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph,
|
||||
Rect sourceCrop, size_t hwh, bool yswap);
|
||||
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
|
||||
virtual void setupDimLayerBlending(int alpha);
|
||||
virtual void setupLayerTexturing(const Texture& texture);
|
||||
|
@ -89,7 +89,8 @@ public:
|
||||
|
||||
// set-up
|
||||
virtual void checkErrors() const;
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap) = 0;
|
||||
virtual void setViewportAndProjection(size_t vpw, size_t vph,
|
||||
Rect sourceCrop, size_t hwh, bool yswap) = 0;
|
||||
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
|
||||
virtual void setupDimLayerBlending(int alpha) = 0;
|
||||
virtual void setupLayerTexturing(const Texture& texture) = 0;
|
||||
|
@ -2790,7 +2790,7 @@ public:
|
||||
|
||||
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform) {
|
||||
|
||||
@ -2816,6 +2816,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
SurfaceFlinger* flinger;
|
||||
sp<IBinder> display;
|
||||
sp<IGraphicBufferProducer> producer;
|
||||
Rect sourceCrop;
|
||||
uint32_t reqWidth, reqHeight;
|
||||
uint32_t minLayerZ,maxLayerZ;
|
||||
bool useIdentityTransform;
|
||||
@ -2824,11 +2825,11 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
MessageCaptureScreen(SurfaceFlinger* flinger,
|
||||
const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform)
|
||||
: flinger(flinger), display(display), producer(producer),
|
||||
reqWidth(reqWidth), reqHeight(reqHeight),
|
||||
sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
|
||||
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
||||
useIdentityTransform(useIdentityTransform),
|
||||
result(PERMISSION_DENIED)
|
||||
@ -2841,7 +2842,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
Mutex::Autolock _l(flinger->mStateLock);
|
||||
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
|
||||
result = flinger->captureScreenImplLocked(hw, producer,
|
||||
reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||
useIdentityTransform);
|
||||
static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
|
||||
return true;
|
||||
@ -2864,7 +2865,8 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
// which does the marshaling work forwards to our "fake remote" above.
|
||||
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
||||
display, IGraphicBufferProducer::asInterface( wrapper ),
|
||||
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
|
||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||
useIdentityTransform);
|
||||
|
||||
status_t res = postMessageAsync(msg);
|
||||
if (res == NO_ERROR) {
|
||||
@ -2876,7 +2878,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||
|
||||
void SurfaceFlinger::renderScreenImplLocked(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool yswap, bool useIdentityTransform)
|
||||
{
|
||||
@ -2888,11 +2890,32 @@ void SurfaceFlinger::renderScreenImplLocked(
|
||||
const uint32_t hw_h = hw->getHeight();
|
||||
const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
|
||||
|
||||
// if a default or invalid sourceCrop is passed in, set reasonable values
|
||||
if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
|
||||
!sourceCrop.isValid()) {
|
||||
sourceCrop.setLeftTop(Point(0, 0));
|
||||
sourceCrop.setRightBottom(Point(hw_w, hw_h));
|
||||
}
|
||||
|
||||
// ensure that sourceCrop is inside screen
|
||||
if (sourceCrop.left < 0) {
|
||||
ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
|
||||
}
|
||||
if (sourceCrop.right >= hw_w) {
|
||||
ALOGE("Invalid crop rect: r = %d (>= %d)", sourceCrop.right, hw_w);
|
||||
}
|
||||
if (sourceCrop.top < 0) {
|
||||
ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
|
||||
}
|
||||
if (sourceCrop.bottom >= hw_h) {
|
||||
ALOGE("Invalid crop rect: b = %d (>= %d)", sourceCrop.bottom, hw_h);
|
||||
}
|
||||
|
||||
// make sure to clear all GL error flags
|
||||
engine.checkErrors();
|
||||
|
||||
// set-up our viewport
|
||||
engine.setViewportAndProjection(reqWidth, reqHeight, hw_w, hw_h, yswap);
|
||||
engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, hw_h, yswap);
|
||||
engine.disableTexturing();
|
||||
|
||||
// redraw the screen entirely...
|
||||
@ -2923,7 +2946,7 @@ void SurfaceFlinger::renderScreenImplLocked(
|
||||
status_t SurfaceFlinger::captureScreenImplLocked(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform)
|
||||
{
|
||||
@ -2978,7 +3001,7 @@ 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, reqWidth, reqHeight,
|
||||
renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
|
||||
minLayerZ, maxLayerZ, true, useIdentityTransform);
|
||||
|
||||
// Create a sync point and wait on it, so we know the buffer is
|
||||
|
@ -202,7 +202,7 @@ private:
|
||||
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
|
||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform);
|
||||
// called when screen needs to turn off
|
||||
@ -311,14 +311,14 @@ private:
|
||||
|
||||
void renderScreenImplLocked(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool yswap, bool useIdentityTransform);
|
||||
|
||||
status_t captureScreenImplLocked(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
const sp<IGraphicBufferProducer>& producer,
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||
bool useIdentityTransform);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user