Merge "rework how we take screenshots for a CPU consumer" into jb-mr2-dev
This commit is contained in:
commit
ff7c2342e2
@ -95,14 +95,6 @@ public:
|
|||||||
virtual bool authenticateSurfaceTexture(
|
virtual bool authenticateSurfaceTexture(
|
||||||
const sp<IGraphicBufferProducer>& surface) const = 0;
|
const sp<IGraphicBufferProducer>& surface) const = 0;
|
||||||
|
|
||||||
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
|
|
||||||
* This function will fail if there is a secure window on screen.
|
|
||||||
*/
|
|
||||||
virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
|
|
||||||
uint32_t* width, uint32_t* height, PixelFormat* format,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
|
|
||||||
|
|
||||||
/* triggers screen off and waits for it to complete
|
/* triggers screen off and waits for it to complete
|
||||||
* requires ACCESS_SURFACE_FLINGER permission.
|
* requires ACCESS_SURFACE_FLINGER permission.
|
||||||
*/
|
*/
|
||||||
@ -123,7 +115,8 @@ public:
|
|||||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
|
bool isCpuConsumer) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -141,7 +134,6 @@ public:
|
|||||||
GET_BUILT_IN_DISPLAY,
|
GET_BUILT_IN_DISPLAY,
|
||||||
SET_TRANSACTION_STATE,
|
SET_TRANSACTION_STATE,
|
||||||
AUTHENTICATE_SURFACE,
|
AUTHENTICATE_SURFACE,
|
||||||
CAPTURE_SCREEN_DEPRECATED,
|
|
||||||
BLANK,
|
BLANK,
|
||||||
UNBLANK,
|
UNBLANK,
|
||||||
GET_DISPLAY_INFO,
|
GET_DISPLAY_INFO,
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <ui/PixelFormat.h>
|
#include <ui/PixelFormat.h>
|
||||||
|
|
||||||
|
#include <gui/CpuConsumer.h>
|
||||||
#include <gui/SurfaceControl.h>
|
#include <gui/SurfaceControl.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
@ -38,7 +39,6 @@ namespace android {
|
|||||||
|
|
||||||
class DisplayInfo;
|
class DisplayInfo;
|
||||||
class Composer;
|
class Composer;
|
||||||
class IMemoryHeap;
|
|
||||||
class ISurfaceComposerClient;
|
class ISurfaceComposerClient;
|
||||||
class IGraphicBufferProducer;
|
class IGraphicBufferProducer;
|
||||||
class Region;
|
class Region;
|
||||||
@ -164,10 +164,9 @@ public:
|
|||||||
uint32_t minLayerZ, uint32_t maxLayerZ);
|
uint32_t minLayerZ, uint32_t maxLayerZ);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sp<IMemoryHeap> mHeap;
|
mutable sp<CpuConsumer> mCpuConsumer;
|
||||||
uint32_t mWidth;
|
CpuConsumer::LockedBuffer mBuffer;
|
||||||
uint32_t mHeight;
|
bool mHaveBuffer;
|
||||||
PixelFormat mFormat;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScreenshotClient();
|
ScreenshotClient();
|
||||||
@ -180,6 +179,8 @@ public:
|
|||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ);
|
uint32_t minLayerZ, uint32_t maxLayerZ);
|
||||||
|
|
||||||
|
sp<CpuConsumer> getCpuConsumer() const;
|
||||||
|
|
||||||
// release memory occupied by the screenshot
|
// release memory occupied by the screenshot
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
|
@ -102,31 +102,11 @@ public:
|
|||||||
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
|
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t captureScreen(
|
|
||||||
const sp<IBinder>& display, sp<IMemoryHeap>* heap,
|
|
||||||
uint32_t* width, uint32_t* height, PixelFormat* format,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
|
||||||
{
|
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
|
||||||
data.writeStrongBinder(display);
|
|
||||||
data.writeInt32(reqWidth);
|
|
||||||
data.writeInt32(reqHeight);
|
|
||||||
data.writeInt32(minLayerZ);
|
|
||||||
data.writeInt32(maxLayerZ);
|
|
||||||
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_DEPRECATED, data, &reply);
|
|
||||||
*heap = interface_cast<IMemoryHeap>(reply.readStrongBinder());
|
|
||||||
*width = reply.readInt32();
|
|
||||||
*height = reply.readInt32();
|
|
||||||
*format = reply.readInt32();
|
|
||||||
return reply.readInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
|
bool isCpuConsumer)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||||
@ -136,6 +116,7 @@ public:
|
|||||||
data.writeInt32(reqHeight);
|
data.writeInt32(reqHeight);
|
||||||
data.writeInt32(minLayerZ);
|
data.writeInt32(minLayerZ);
|
||||||
data.writeInt32(maxLayerZ);
|
data.writeInt32(maxLayerZ);
|
||||||
|
data.writeInt32(isCpuConsumer);
|
||||||
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
|
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
|
||||||
return reply.readInt32();
|
return reply.readInt32();
|
||||||
}
|
}
|
||||||
@ -285,24 +266,6 @@ status_t BnSurfaceComposer::onTransact(
|
|||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
bootFinished();
|
bootFinished();
|
||||||
} break;
|
} break;
|
||||||
case CAPTURE_SCREEN_DEPRECATED: {
|
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
|
||||||
sp<IBinder> display = data.readStrongBinder();
|
|
||||||
uint32_t reqWidth = data.readInt32();
|
|
||||||
uint32_t reqHeight = data.readInt32();
|
|
||||||
uint32_t minLayerZ = data.readInt32();
|
|
||||||
uint32_t maxLayerZ = data.readInt32();
|
|
||||||
sp<IMemoryHeap> heap;
|
|
||||||
uint32_t w, h;
|
|
||||||
PixelFormat f;
|
|
||||||
status_t res = captureScreen(display, &heap, &w, &h, &f,
|
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
|
||||||
reply->writeStrongBinder(heap->asBinder());
|
|
||||||
reply->writeInt32(w);
|
|
||||||
reply->writeInt32(h);
|
|
||||||
reply->writeInt32(f);
|
|
||||||
reply->writeInt32(res);
|
|
||||||
} break;
|
|
||||||
case CAPTURE_SCREEN: {
|
case CAPTURE_SCREEN: {
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
sp<IBinder> display = data.readStrongBinder();
|
sp<IBinder> display = data.readStrongBinder();
|
||||||
@ -312,8 +275,10 @@ status_t BnSurfaceComposer::onTransact(
|
|||||||
uint32_t reqHeight = data.readInt32();
|
uint32_t reqHeight = data.readInt32();
|
||||||
uint32_t minLayerZ = data.readInt32();
|
uint32_t minLayerZ = data.readInt32();
|
||||||
uint32_t maxLayerZ = data.readInt32();
|
uint32_t maxLayerZ = data.readInt32();
|
||||||
|
bool isCpuConsumer = data.readInt32();
|
||||||
status_t res = captureScreen(display, producer,
|
status_t res = captureScreen(display, producer,
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
|
isCpuConsumer);
|
||||||
reply->writeInt32(res);
|
reply->writeInt32(res);
|
||||||
} break;
|
} break;
|
||||||
case AUTHENTICATE_SURFACE: {
|
case AUTHENTICATE_SURFACE: {
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <ui/DisplayInfo.h>
|
#include <ui/DisplayInfo.h>
|
||||||
|
|
||||||
|
#include <gui/CpuConsumer.h>
|
||||||
#include <gui/IGraphicBufferProducer.h>
|
#include <gui/IGraphicBufferProducer.h>
|
||||||
#include <gui/ISurfaceComposer.h>
|
#include <gui/ISurfaceComposer.h>
|
||||||
#include <gui/ISurfaceComposerClient.h>
|
#include <gui/ISurfaceComposerClient.h>
|
||||||
@ -617,30 +618,21 @@ status_t ScreenshotClient::capture(
|
|||||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
||||||
if (s == NULL) return NO_INIT;
|
if (s == NULL) return NO_INIT;
|
||||||
return s->captureScreen(display, producer,
|
return s->captureScreen(display, producer,
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenshotClient::ScreenshotClient()
|
ScreenshotClient::ScreenshotClient()
|
||||||
: mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) {
|
: mHaveBuffer(false) {
|
||||||
|
memset(&mBuffer, 0, sizeof(mBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t ScreenshotClient::update(const sp<IBinder>& display) {
|
sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
|
||||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
if (mCpuConsumer == NULL) {
|
||||||
if (s == NULL) return NO_INIT;
|
mCpuConsumer = new CpuConsumer(1);
|
||||||
mHeap = 0;
|
mCpuConsumer->setName(String8("ScreenshotClient"));
|
||||||
return s->captureScreen(display, &mHeap,
|
}
|
||||||
&mWidth, &mHeight, &mFormat, 0, 0,
|
return mCpuConsumer;
|
||||||
0, -1UL);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight) {
|
|
||||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
|
||||||
if (s == NULL) return NO_INIT;
|
|
||||||
mHeap = 0;
|
|
||||||
return s->captureScreen(display, &mHeap,
|
|
||||||
&mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
|
|
||||||
0, -1UL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||||
@ -648,38 +640,66 @@ status_t ScreenshotClient::update(const sp<IBinder>& display,
|
|||||||
uint32_t minLayerZ, uint32_t maxLayerZ) {
|
uint32_t minLayerZ, uint32_t maxLayerZ) {
|
||||||
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
sp<ISurfaceComposer> s(ComposerService::getComposerService());
|
||||||
if (s == NULL) return NO_INIT;
|
if (s == NULL) return NO_INIT;
|
||||||
mHeap = 0;
|
sp<CpuConsumer> cpuConsumer = getCpuConsumer();
|
||||||
return s->captureScreen(display, &mHeap,
|
|
||||||
&mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
|
if (mHaveBuffer) {
|
||||||
minLayerZ, maxLayerZ);
|
mCpuConsumer->unlockBuffer(mBuffer);
|
||||||
|
memset(&mBuffer, 0, sizeof(mBuffer));
|
||||||
|
mHaveBuffer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t err = s->captureScreen(display,cpuConsumer->getBufferQueue(),
|
||||||
|
reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
|
||||||
|
|
||||||
|
if (err == NO_ERROR) {
|
||||||
|
err = mCpuConsumer->lockNextBuffer(&mBuffer);
|
||||||
|
if (err == NO_ERROR) {
|
||||||
|
mHaveBuffer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ScreenshotClient::update(const sp<IBinder>& display) {
|
||||||
|
return ScreenshotClient::update(display, 0, 0, 0, -1UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ScreenshotClient::update(const sp<IBinder>& display,
|
||||||
|
uint32_t reqWidth, uint32_t reqHeight) {
|
||||||
|
return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotClient::release() {
|
void ScreenshotClient::release() {
|
||||||
mHeap = 0;
|
if (mHaveBuffer) {
|
||||||
|
mCpuConsumer->unlockBuffer(mBuffer);
|
||||||
|
memset(&mBuffer, 0, sizeof(mBuffer));
|
||||||
|
mHaveBuffer = false;
|
||||||
|
}
|
||||||
|
mCpuConsumer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void const* ScreenshotClient::getPixels() const {
|
void const* ScreenshotClient::getPixels() const {
|
||||||
return mHeap->getBase();
|
return mBuffer.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ScreenshotClient::getWidth() const {
|
uint32_t ScreenshotClient::getWidth() const {
|
||||||
return mWidth;
|
return mBuffer.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ScreenshotClient::getHeight() const {
|
uint32_t ScreenshotClient::getHeight() const {
|
||||||
return mHeight;
|
return mBuffer.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelFormat ScreenshotClient::getFormat() const {
|
PixelFormat ScreenshotClient::getFormat() const {
|
||||||
return mFormat;
|
return mBuffer.format;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ScreenshotClient::getStride() const {
|
uint32_t ScreenshotClient::getStride() const {
|
||||||
return mWidth;
|
return mBuffer.stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ScreenshotClient::getSize() const {
|
size_t ScreenshotClient::getSize() const {
|
||||||
return mHeap->getSize();
|
return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -2416,7 +2416,6 @@ status_t SurfaceFlinger::onTransact(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CAPTURE_SCREEN:
|
case CAPTURE_SCREEN:
|
||||||
case CAPTURE_SCREEN_DEPRECATED:
|
|
||||||
{
|
{
|
||||||
// codes that require permission check
|
// codes that require permission check
|
||||||
IPCThreadState* ipc = IPCThreadState::self();
|
IPCThreadState* ipc = IPCThreadState::self();
|
||||||
@ -2511,7 +2510,8 @@ void SurfaceFlinger::repaintEverything() {
|
|||||||
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ) {
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
|
bool isCpuConsumer) {
|
||||||
|
|
||||||
if (CC_UNLIKELY(display == 0))
|
if (CC_UNLIKELY(display == 0))
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -2525,16 +2525,18 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
sp<IGraphicBufferProducer> producer;
|
sp<IGraphicBufferProducer> producer;
|
||||||
uint32_t reqWidth, reqHeight;
|
uint32_t reqWidth, reqHeight;
|
||||||
uint32_t minLayerZ,maxLayerZ;
|
uint32_t minLayerZ,maxLayerZ;
|
||||||
|
bool isCpuConsumer;
|
||||||
status_t result;
|
status_t result;
|
||||||
public:
|
public:
|
||||||
MessageCaptureScreen(SurfaceFlinger* flinger,
|
MessageCaptureScreen(SurfaceFlinger* flinger,
|
||||||
const sp<IBinder>& display,
|
const sp<IBinder>& display,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer)
|
||||||
: flinger(flinger), display(display), producer(producer),
|
: flinger(flinger), display(display), producer(producer),
|
||||||
reqWidth(reqWidth), reqHeight(reqHeight),
|
reqWidth(reqWidth), reqHeight(reqHeight),
|
||||||
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
||||||
|
isCpuConsumer(isCpuConsumer),
|
||||||
result(PERMISSION_DENIED)
|
result(PERMISSION_DENIED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -2544,14 +2546,24 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
virtual bool handler() {
|
virtual bool handler() {
|
||||||
Mutex::Autolock _l(flinger->mStateLock);
|
Mutex::Autolock _l(flinger->mStateLock);
|
||||||
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
|
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
|
||||||
result = flinger->captureScreenImplLocked(hw, producer,
|
// TODO: if we know the GL->CPU path works, we can call
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
// captureScreenImplLocked() directly, instead of using the
|
||||||
|
// "CpuConsumer" version, which is much less efficient -- it is
|
||||||
|
// however needed by some older drivers.
|
||||||
|
if (isCpuConsumer) {
|
||||||
|
result = flinger->captureScreenImplCpuConsumerLocked(hw,
|
||||||
|
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
||||||
|
} else {
|
||||||
|
result = flinger->captureScreenImplLocked(hw,
|
||||||
|
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
||||||
display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
|
isCpuConsumer);
|
||||||
status_t res = postMessageSync(msg);
|
status_t res = postMessageSync(msg);
|
||||||
if (res == NO_ERROR) {
|
if (res == NO_ERROR) {
|
||||||
res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
|
res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
|
||||||
@ -2655,18 +2667,15 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
}
|
}
|
||||||
|
|
||||||
eglDestroySurface(mEGLDisplay, eglSurface);
|
eglDestroySurface(mEGLDisplay, eglSurface);
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Capture screen into an IMemoryHeap (legacy)
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
status_t SurfaceFlinger::captureScreenImplLocked(
|
status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked(
|
||||||
const sp<const DisplayDevice>& hw,
|
const sp<const DisplayDevice>& hw,
|
||||||
sp<IMemoryHeap>* heap,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t* w, uint32_t* h, PixelFormat* f,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t sw, uint32_t sh,
|
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
uint32_t minLayerZ, uint32_t maxLayerZ)
|
||||||
{
|
{
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
@ -2689,7 +2698,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
|
|
||||||
// call the new screenshot taking code, passing a BufferQueue to it
|
// call the new screenshot taking code, passing a BufferQueue to it
|
||||||
status_t result = captureScreenImplLocked(hw,
|
status_t result = captureScreenImplLocked(hw,
|
||||||
consumer->getBufferQueue(), sw, sh, minLayerZ, maxLayerZ);
|
consumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
||||||
|
|
||||||
if (result == NO_ERROR) {
|
if (result == NO_ERROR) {
|
||||||
result = consumer->updateTexImage();
|
result = consumer->updateTexImage();
|
||||||
@ -2701,31 +2710,64 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
|
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
|
||||||
GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
|
GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
|
||||||
|
|
||||||
sp<GraphicBuffer> buf(consumer->getCurrentBuffer());
|
reqWidth = consumer->getCurrentBuffer()->getWidth();
|
||||||
sw = buf->getWidth();
|
reqHeight = consumer->getCurrentBuffer()->getHeight();
|
||||||
sh = buf->getHeight();
|
|
||||||
size_t size = sw * sh * 4;
|
|
||||||
|
|
||||||
// allocate shared memory large enough to hold the
|
{
|
||||||
// screen capture
|
// in this block we render the screenshot into the
|
||||||
sp<MemoryHeapBase> base(
|
// CpuConsumer using glReadPixels from our GLConsumer,
|
||||||
new MemoryHeapBase(size, 0, "screen-capture") );
|
// Some older drivers don't support the GL->CPU path so
|
||||||
void* const ptr = base->getBase();
|
// have to wrap it with a CPU->CPU path, which is what
|
||||||
if (ptr != MAP_FAILED) {
|
// glReadPixels essentially is
|
||||||
// capture the screen with glReadPixels()
|
|
||||||
ScopedTrace _t(ATRACE_TAG, "glReadPixels");
|
sp<Surface> sur = new Surface(producer);
|
||||||
glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
|
ANativeWindow* window = sur.get();
|
||||||
if (glGetError() == GL_NO_ERROR) {
|
ANativeWindowBuffer* buffer;
|
||||||
*heap = base;
|
void* vaddr;
|
||||||
*w = sw;
|
|
||||||
*h = sh;
|
if (native_window_api_connect(window,
|
||||||
*f = PIXEL_FORMAT_RGBA_8888;
|
NATIVE_WINDOW_API_CPU) == NO_ERROR) {
|
||||||
result = NO_ERROR;
|
int err = 0;
|
||||||
} else {
|
err = native_window_set_buffers_dimensions(window,
|
||||||
result = NO_MEMORY;
|
reqWidth, reqHeight);
|
||||||
|
err |= native_window_set_buffers_format(window,
|
||||||
|
HAL_PIXEL_FORMAT_RGBA_8888);
|
||||||
|
err |= native_window_set_usage(window,
|
||||||
|
GRALLOC_USAGE_SW_READ_OFTEN |
|
||||||
|
GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||||
|
|
||||||
|
if (err == NO_ERROR) {
|
||||||
|
if (native_window_dequeue_buffer_and_wait(window,
|
||||||
|
&buffer) == NO_ERROR) {
|
||||||
|
sp<GraphicBuffer> buf =
|
||||||
|
static_cast<GraphicBuffer*>(buffer);
|
||||||
|
if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
|
||||||
|
&vaddr) == NO_ERROR) {
|
||||||
|
if (buffer->stride != int(reqWidth)) {
|
||||||
|
// we're unlucky here, glReadPixels is
|
||||||
|
// not able to deal with a stride not
|
||||||
|
// equal to the width.
|
||||||
|
uint32_t* tmp = new uint32_t[reqWidth*reqHeight];
|
||||||
|
if (tmp != NULL) {
|
||||||
|
glReadPixels(0, 0, reqWidth, reqHeight,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE, tmp);
|
||||||
|
for (size_t y=0 ; y<reqHeight ; y++) {
|
||||||
|
memcpy((uint32_t*)vaddr + y*buffer->stride,
|
||||||
|
tmp + y*reqWidth, reqWidth*4);
|
||||||
|
}
|
||||||
|
delete [] tmp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glReadPixels(0, 0, reqWidth, reqHeight,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
|
||||||
|
}
|
||||||
|
buf->unlock();
|
||||||
|
}
|
||||||
|
window->queueBuffer(window, buffer, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result = NO_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// back to main framebuffer
|
// back to main framebuffer
|
||||||
@ -2742,63 +2784,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|
||||||
sp<IMemoryHeap>* heap,
|
|
||||||
uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
|
||||||
{
|
|
||||||
if (CC_UNLIKELY(display == 0))
|
|
||||||
return BAD_VALUE;
|
|
||||||
|
|
||||||
class MessageCaptureScreen : public MessageBase {
|
|
||||||
SurfaceFlinger* flinger;
|
|
||||||
sp<IBinder> display;
|
|
||||||
sp<IMemoryHeap>* heap;
|
|
||||||
uint32_t* outWidth;
|
|
||||||
uint32_t* outHeight;
|
|
||||||
PixelFormat* outFormat;
|
|
||||||
uint32_t reqWidth;
|
|
||||||
uint32_t reqHeight;
|
|
||||||
uint32_t minLayerZ;
|
|
||||||
uint32_t maxLayerZ;
|
|
||||||
status_t result;
|
|
||||||
public:
|
|
||||||
MessageCaptureScreen(SurfaceFlinger* flinger,
|
|
||||||
const sp<IBinder>& display, sp<IMemoryHeap>* heap,
|
|
||||||
uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ)
|
|
||||||
: flinger(flinger), display(display), heap(heap),
|
|
||||||
outWidth(outWidth), outHeight(outHeight), outFormat(outFormat),
|
|
||||||
reqWidth(reqWidth), reqHeight(reqHeight),
|
|
||||||
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
|
||||||
result(PERMISSION_DENIED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
status_t getResult() const {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
virtual bool handler() {
|
|
||||||
Mutex::Autolock _l(flinger->mStateLock);
|
|
||||||
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
|
|
||||||
result = flinger->captureScreenImplLocked(hw, heap,
|
|
||||||
outWidth, outHeight, outFormat,
|
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sp<MessageBase> msg = new MessageCaptureScreen(this, display, heap,
|
|
||||||
outWidth, outHeight, outFormat,
|
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ);
|
|
||||||
status_t res = postMessageSync(msg);
|
|
||||||
if (res == NO_ERROR) {
|
|
||||||
res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
SurfaceFlinger::LayerVector::LayerVector() {
|
SurfaceFlinger::LayerVector::LayerVector() {
|
||||||
|
@ -185,14 +185,10 @@ private:
|
|||||||
virtual bool authenticateSurfaceTexture(
|
virtual bool authenticateSurfaceTexture(
|
||||||
const sp<IGraphicBufferProducer>& bufferProducer) const;
|
const sp<IGraphicBufferProducer>& bufferProducer) const;
|
||||||
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
|
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
|
||||||
virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
|
|
||||||
uint32_t* width, uint32_t* height, PixelFormat* format,
|
|
||||||
uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
|
|
||||||
uint32_t maxLayerZ);
|
|
||||||
virtual status_t captureScreen(const sp<IBinder>& display,
|
virtual status_t captureScreen(const sp<IBinder>& display,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ);
|
uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
|
||||||
// called when screen needs to turn off
|
// called when screen needs to turn off
|
||||||
virtual void blank(const sp<IBinder>& display);
|
virtual void blank(const sp<IBinder>& display);
|
||||||
// called when screen is turning back on
|
// called when screen is turning back on
|
||||||
@ -297,17 +293,17 @@ private:
|
|||||||
|
|
||||||
status_t captureScreenImplLocked(
|
status_t captureScreenImplLocked(
|
||||||
const sp<const DisplayDevice>& hw,
|
const sp<const DisplayDevice>& hw,
|
||||||
sp<IMemoryHeap>* heap,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t* width, uint32_t* height, PixelFormat* format,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ);
|
||||||
uint32_t maxLayerZ);
|
|
||||||
|
|
||||||
status_t captureScreenImplLocked(
|
status_t captureScreenImplCpuConsumerLocked(
|
||||||
const sp<const DisplayDevice>& hw,
|
const sp<const DisplayDevice>& hw,
|
||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
uint32_t reqWidth, uint32_t reqHeight,
|
uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ);
|
uint32_t minLayerZ, uint32_t maxLayerZ);
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* EGL
|
* EGL
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user