Bring back support for glReadPixels screenshot path
Squashed commit of the following:
commit 012d3fe41d1d6cd38a0858b59145e9a4447641fa
Author: Hashcode <hashcode0f@gmail.com>
Date: Sun Dec 8 19:36:50 2013 +0000
sf: Always use opengles for screen capture
Go back to the usage of GRALLOC_USAGE_HW_TEXTURE and GRALLOC_USAGE_HW_RENDERER
in captureScreenImplLocked regardless of useReadPixels value
This fixes the EGL_NO_IMAGE_KHR error returned from
eglCreateImageKHR (blank images returned from screenshot path)
Change-Id: I62fe90a081607b9e89c67f3dcfd34c84efc89d35
commit 4866ddf98ac98d8e22a1cd6a21894bb17f274588
Author: Ricardo Cerqueira <cyanogenmod@cerqueira.org>
Date: Thu Oct 31 03:53:39 2013 +0000
Revert "remove support for glReadPixels screenshot path"
This reverts commit 3ca76f416b
.
Conflicts:
include/gui/ISurfaceComposer.h
libs/gui/ISurfaceComposer.cpp
libs/gui/SurfaceComposerClient.cpp
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h
Change-Id: I8c239e533757af770e418dbb198f5a86c736961f
Change-Id: I8c239e533757af770e418dbb198f5a86c736961f
This commit is contained in:
parent
bcce313fea
commit
fd1fb639a1
@ -145,7 +145,8 @@ public:
|
|||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform,
|
bool useIdentityTransform,
|
||||||
Rotation rotation = eRotateNone) = 0;
|
Rotation rotation = eRotateNone,
|
||||||
|
bool isCpuConsumer = false) = 0;
|
||||||
|
|
||||||
/* Clears the frame statistics for animations.
|
/* Clears the frame statistics for animations.
|
||||||
*
|
*
|
||||||
|
@ -103,7 +103,8 @@ public:
|
|||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform,
|
bool useIdentityTransform,
|
||||||
ISurfaceComposer::Rotation rotation)
|
ISurfaceComposer::Rotation rotation,
|
||||||
|
bool isCpuConsumer)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||||
@ -116,6 +117,7 @@ public:
|
|||||||
data.writeUint32(maxLayerZ);
|
data.writeUint32(maxLayerZ);
|
||||||
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
|
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
|
||||||
data.writeInt32(static_cast<int32_t>(rotation));
|
data.writeInt32(static_cast<int32_t>(rotation));
|
||||||
|
data.writeInt32(isCpuConsumer);
|
||||||
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
|
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
|
||||||
return reply.readInt32();
|
return reply.readInt32();
|
||||||
}
|
}
|
||||||
@ -361,11 +363,13 @@ status_t BnSurfaceComposer::onTransact(
|
|||||||
uint32_t maxLayerZ = data.readUint32();
|
uint32_t maxLayerZ = data.readUint32();
|
||||||
bool useIdentityTransform = static_cast<bool>(data.readInt32());
|
bool useIdentityTransform = static_cast<bool>(data.readInt32());
|
||||||
int32_t rotation = data.readInt32();
|
int32_t rotation = data.readInt32();
|
||||||
|
bool isCpuConsumer = data.readInt32();
|
||||||
|
|
||||||
status_t res = captureScreen(display, producer,
|
status_t res = captureScreen(display, producer,
|
||||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
useIdentityTransform,
|
useIdentityTransform,
|
||||||
static_cast<ISurfaceComposer::Rotation>(rotation));
|
static_cast<ISurfaceComposer::Rotation>(rotation),
|
||||||
|
isCpuConsumer);
|
||||||
reply->writeInt32(res);
|
reply->writeInt32(res);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -691,7 +691,8 @@ 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, sourceCrop,
|
return s->captureScreen(display, producer, sourceCrop,
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
|
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
|
||||||
|
ISurfaceComposer::eRotateNone, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenshotClient::ScreenshotClient()
|
ScreenshotClient::ScreenshotClient()
|
||||||
@ -729,7 +730,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display,
|
|||||||
|
|
||||||
status_t err = s->captureScreen(display, mProducer, sourceCrop,
|
status_t err = s->captureScreen(display, mProducer, sourceCrop,
|
||||||
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
|
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
|
||||||
static_cast<ISurfaceComposer::Rotation>(rotation));
|
static_cast<ISurfaceComposer::Rotation>(rotation), true);
|
||||||
|
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
err = mCpuConsumer->lockNextBuffer(&mBuffer);
|
err = mCpuConsumer->lockNextBuffer(&mBuffer);
|
||||||
|
@ -210,28 +210,46 @@ void GLES11RenderEngine::disableBlending() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
|
void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
|
||||||
uint32_t* texName, uint32_t* fbName, uint32_t* status) {
|
uint32_t* texName, uint32_t* fbName, uint32_t* status,
|
||||||
|
bool useReadPixels, int reqWidth, int reqHeight) {
|
||||||
GLuint tname, name;
|
GLuint tname, name;
|
||||||
// turn our EGLImage into a texture
|
if (!useReadPixels) {
|
||||||
glGenTextures(1, &tname);
|
// turn our EGLImage into a texture
|
||||||
glBindTexture(GL_TEXTURE_2D, tname);
|
glGenTextures(1, &tname);
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
|
glBindTexture(GL_TEXTURE_2D, tname);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
|
||||||
|
|
||||||
// create a Framebuffer Object to render into
|
// create a Framebuffer Object to render into
|
||||||
glGenFramebuffersOES(1, &name);
|
glGenFramebuffersOES(1, &name);
|
||||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
|
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
|
||||||
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);
|
||||||
|
} else {
|
||||||
|
// since we're going to use glReadPixels() anyways,
|
||||||
|
// use an intermediate renderbuffer instead
|
||||||
|
glGenRenderbuffersOES(1, &tname);
|
||||||
|
glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
|
||||||
|
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
|
||||||
|
// create a FBO to render into
|
||||||
|
glGenFramebuffersOES(1, &name);
|
||||||
|
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
|
||||||
|
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
|
||||||
|
GL_RENDERBUFFER_OES, tname);
|
||||||
|
}
|
||||||
|
|
||||||
*status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
|
*status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
|
||||||
*texName = tname;
|
*texName = tname;
|
||||||
*fbName = name;
|
*fbName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
|
void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName,
|
||||||
|
bool useReadPixels) {
|
||||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
|
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
|
||||||
glDeleteFramebuffersOES(1, &fbName);
|
glDeleteFramebuffersOES(1, &fbName);
|
||||||
glDeleteTextures(1, &texName);
|
if (!useReadPixels)
|
||||||
|
glDeleteTextures(1, &texName);
|
||||||
|
else
|
||||||
|
glDeleteRenderbuffersOES(1, &texName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLES11RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
|
void GLES11RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
|
||||||
|
@ -40,8 +40,9 @@ class GLES11RenderEngine : public RenderEngine {
|
|||||||
GLint mMaxTextureSize;
|
GLint mMaxTextureSize;
|
||||||
|
|
||||||
virtual void bindImageAsFramebuffer(EGLImageKHR image,
|
virtual void bindImageAsFramebuffer(EGLImageKHR image,
|
||||||
uint32_t* texName, uint32_t* fbName, uint32_t* status);
|
uint32_t* texName, uint32_t* fbName, uint32_t* status, bool useReadPixels,
|
||||||
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
|
int reqWidth, int reqHeight);
|
||||||
|
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLES11RenderEngine();
|
GLES11RenderEngine();
|
||||||
|
@ -185,27 +185,44 @@ void GLES20RenderEngine::disableBlending() {
|
|||||||
|
|
||||||
|
|
||||||
void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
|
void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
|
||||||
uint32_t* texName, uint32_t* fbName, uint32_t* status) {
|
uint32_t* texName, uint32_t* fbName, uint32_t* status,
|
||||||
|
bool useReadPixels, int reqWidth, int reqHeight) {
|
||||||
GLuint tname, name;
|
GLuint tname, name;
|
||||||
// turn our EGLImage into a texture
|
if (!useReadPixels) {
|
||||||
glGenTextures(1, &tname);
|
// turn our EGLImage into a texture
|
||||||
glBindTexture(GL_TEXTURE_2D, tname);
|
glGenTextures(1, &tname);
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
|
glBindTexture(GL_TEXTURE_2D, tname);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
|
||||||
|
|
||||||
// create a Framebuffer Object to render into
|
// create a Framebuffer Object to render into
|
||||||
glGenFramebuffers(1, &name);
|
glGenFramebuffers(1, &name);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, name);
|
glBindFramebuffer(GL_FRAMEBUFFER, name);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
|
||||||
|
} else {
|
||||||
|
// since we're going to use glReadPixels() anyways,
|
||||||
|
// use an intermediate renderbuffer instead
|
||||||
|
glGenRenderbuffers(1, &tname);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, tname);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, reqWidth, reqHeight);
|
||||||
|
// create a FBO to render into
|
||||||
|
glGenFramebuffers(1, &name);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, name);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, tname);
|
||||||
|
}
|
||||||
|
|
||||||
*status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
*status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
*texName = tname;
|
*texName = tname;
|
||||||
*fbName = name;
|
*fbName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
|
void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName,
|
||||||
|
bool useReadPixels) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glDeleteFramebuffers(1, &fbName);
|
glDeleteFramebuffers(1, &fbName);
|
||||||
glDeleteTextures(1, &texName);
|
if (!useReadPixels)
|
||||||
|
glDeleteTextures(1, &texName);
|
||||||
|
else
|
||||||
|
glDeleteRenderbuffers(1, &texName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
|
void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
|
||||||
|
@ -55,8 +55,9 @@ class GLES20RenderEngine : public RenderEngine {
|
|||||||
Vector<Group> mGroupStack;
|
Vector<Group> mGroupStack;
|
||||||
|
|
||||||
virtual void bindImageAsFramebuffer(EGLImageKHR image,
|
virtual void bindImageAsFramebuffer(EGLImageKHR image,
|
||||||
uint32_t* texName, uint32_t* fbName, uint32_t* status);
|
uint32_t* texName, uint32_t* fbName, uint32_t* status,
|
||||||
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
|
bool useReadPixels, int reqWidth, int reqHeight);
|
||||||
|
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLES20RenderEngine();
|
GLES20RenderEngine();
|
||||||
|
@ -262,9 +262,11 @@ void RenderEngine::dump(String8& result) {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
|
RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
|
||||||
RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
|
RenderEngine& engine, EGLImageKHR image, bool useReadPixels,
|
||||||
|
int reqWidth, int reqHeight) : mEngine(engine), mUseReadPixels(useReadPixels)
|
||||||
{
|
{
|
||||||
mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
|
mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus,
|
||||||
|
useReadPixels, reqWidth, reqHeight);
|
||||||
|
|
||||||
ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
|
ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
|
||||||
"glCheckFramebufferStatusOES error %d", mStatus);
|
"glCheckFramebufferStatusOES error %d", mStatus);
|
||||||
@ -272,7 +274,7 @@ RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
|
|||||||
|
|
||||||
RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
|
RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
|
||||||
// back to main framebuffer
|
// back to main framebuffer
|
||||||
mEngine.unbindFramebuffer(mTexName, mFbName);
|
mEngine.unbindFramebuffer(mTexName, mFbName, mUseReadPixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
|
status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
|
||||||
|
@ -51,8 +51,11 @@ class RenderEngine {
|
|||||||
EGLContext mEGLContext;
|
EGLContext mEGLContext;
|
||||||
void setEGLHandles(EGLConfig config, EGLContext ctxt);
|
void setEGLHandles(EGLConfig config, EGLContext ctxt);
|
||||||
|
|
||||||
virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
|
virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
|
||||||
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
|
uint32_t* fbName, uint32_t* status, bool useReadPixels, int reqWidth,
|
||||||
|
int reqHeight) = 0;
|
||||||
|
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName,
|
||||||
|
bool useReadPixels) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RenderEngine();
|
RenderEngine();
|
||||||
@ -83,8 +86,10 @@ public:
|
|||||||
RenderEngine& mEngine;
|
RenderEngine& mEngine;
|
||||||
uint32_t mTexName, mFbName;
|
uint32_t mTexName, mFbName;
|
||||||
uint32_t mStatus;
|
uint32_t mStatus;
|
||||||
|
bool mUseReadPixels;
|
||||||
public:
|
public:
|
||||||
BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
|
BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image,
|
||||||
|
bool useReadPixels, int reqWidth, int reqHeight);
|
||||||
~BindImageAsFramebuffer();
|
~BindImageAsFramebuffer();
|
||||||
int getStatus() const;
|
int getStatus() const;
|
||||||
};
|
};
|
||||||
|
@ -3160,7 +3160,8 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
|
bool useIdentityTransform, ISurfaceComposer::Rotation rotation,
|
||||||
|
bool useReadPixels) {
|
||||||
|
|
||||||
if (CC_UNLIKELY(display == 0))
|
if (CC_UNLIKELY(display == 0))
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -3210,6 +3211,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
uint32_t minLayerZ,maxLayerZ;
|
uint32_t minLayerZ,maxLayerZ;
|
||||||
bool useIdentityTransform;
|
bool useIdentityTransform;
|
||||||
Transform::orientation_flags rotation;
|
Transform::orientation_flags rotation;
|
||||||
|
bool useReadPixels;
|
||||||
status_t result;
|
status_t result;
|
||||||
public:
|
public:
|
||||||
MessageCaptureScreen(SurfaceFlinger* flinger,
|
MessageCaptureScreen(SurfaceFlinger* flinger,
|
||||||
@ -3217,12 +3219,14 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform, Transform::orientation_flags rotation)
|
bool useIdentityTransform, Transform::orientation_flags rotation,
|
||||||
|
bool useReadPixels)
|
||||||
: flinger(flinger), display(display), producer(producer),
|
: flinger(flinger), display(display), producer(producer),
|
||||||
sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
|
sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
|
||||||
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
|
||||||
useIdentityTransform(useIdentityTransform),
|
useIdentityTransform(useIdentityTransform),
|
||||||
rotation(rotation),
|
rotation(rotation),
|
||||||
|
useReadPixels(useReadPixels),
|
||||||
result(PERMISSION_DENIED)
|
result(PERMISSION_DENIED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -3232,9 +3236,10 @@ 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));
|
||||||
|
bool useReadPixels = this->useReadPixels && !flinger->mGpuToCpuSupported;
|
||||||
result = flinger->captureScreenImplLocked(hw, producer,
|
result = flinger->captureScreenImplLocked(hw, producer,
|
||||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
useIdentityTransform, rotation);
|
useIdentityTransform, rotation, useReadPixels);
|
||||||
static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
|
static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3257,7 +3262,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
||||||
display, IGraphicBufferProducer::asInterface( wrapper ),
|
display, IGraphicBufferProducer::asInterface( wrapper ),
|
||||||
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
useIdentityTransform, rotationFlags);
|
useIdentityTransform, rotationFlags, useReadPixels);
|
||||||
|
|
||||||
status_t res = postMessageAsync(msg);
|
status_t res = postMessageAsync(msg);
|
||||||
if (res == NO_ERROR) {
|
if (res == NO_ERROR) {
|
||||||
@ -3347,7 +3352,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform, Transform::orientation_flags rotation)
|
bool useIdentityTransform, Transform::orientation_flags rotation,
|
||||||
|
bool useReadPixels)
|
||||||
{
|
{
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
|
|
||||||
@ -3399,7 +3405,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
if (image != EGL_NO_IMAGE_KHR) {
|
if (image != EGL_NO_IMAGE_KHR) {
|
||||||
// this binds the given EGLImage as a framebuffer for the
|
// this binds the given EGLImage as a framebuffer for the
|
||||||
// duration of this scope.
|
// duration of this scope.
|
||||||
RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
|
RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image,
|
||||||
|
useReadPixels, reqWidth, reqHeight);
|
||||||
if (imageBond.getStatus() == NO_ERROR) {
|
if (imageBond.getStatus() == NO_ERROR) {
|
||||||
// this will in fact render into our dequeued buffer
|
// this will in fact render into our dequeued buffer
|
||||||
// via an FBO, which means we didn't have to create
|
// via an FBO, which means we didn't have to create
|
||||||
@ -3446,6 +3453,15 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
|
ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (useReadPixels) {
|
||||||
|
sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
|
||||||
|
void* vaddr;
|
||||||
|
if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
|
||||||
|
getRenderEngine().readPixels(0, 0, buffer->stride, reqHeight,
|
||||||
|
(uint32_t *)vaddr);
|
||||||
|
buf->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (DEBUG_SCREENSHOTS) {
|
if (DEBUG_SCREENSHOTS) {
|
||||||
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
|
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
|
||||||
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
|
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
|
||||||
|
@ -212,7 +212,8 @@ private:
|
|||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
|
bool useIdentityTransform, ISurfaceComposer::Rotation rotation,
|
||||||
|
bool isCpuConsumer);
|
||||||
virtual status_t getDisplayStats(const sp<IBinder>& display,
|
virtual status_t getDisplayStats(const sp<IBinder>& display,
|
||||||
DisplayStatInfo* stats);
|
DisplayStatInfo* stats);
|
||||||
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
|
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
|
||||||
@ -366,7 +367,8 @@ private:
|
|||||||
const sp<IGraphicBufferProducer>& producer,
|
const sp<IGraphicBufferProducer>& producer,
|
||||||
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
|
||||||
uint32_t minLayerZ, uint32_t maxLayerZ,
|
uint32_t minLayerZ, uint32_t maxLayerZ,
|
||||||
bool useIdentityTransform, Transform::orientation_flags rotation);
|
bool useIdentityTransform, Transform::orientation_flags rotation,
|
||||||
|
bool useReadPixels);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* EGL
|
* EGL
|
||||||
|
Loading…
Reference in New Issue
Block a user