Skip to content

Commit

Permalink
Revert "remove support for glReadPixels screenshot path"
Browse files Browse the repository at this point in the history
This reverts commit 3ca76f4.
  • Loading branch information
rmcc authored and hyperb1iss committed Nov 12, 2013
1 parent 49b2104 commit 5f695d3
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 50 deletions.
3 changes: 2 additions & 1 deletion include/gui/ISurfaceComposer.h
Expand Up @@ -120,7 +120,8 @@ class ISurfaceComposer: public IInterface {
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
uint32_t minLayerZ, uint32_t maxLayerZ,
bool isCpuConsumer) = 0;
};

// ----------------------------------------------------------------------------
Expand Down
8 changes: 6 additions & 2 deletions libs/gui/ISurfaceComposer.cpp
Expand Up @@ -105,7 +105,8 @@ class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ)
uint32_t minLayerZ, uint32_t maxLayerZ,
bool isCpuConsumer)
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
Expand All @@ -115,6 +116,7 @@ class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
data.writeInt32(reqHeight);
data.writeInt32(minLayerZ);
data.writeInt32(maxLayerZ);
data.writeInt32(isCpuConsumer);
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
return reply.readInt32();
}
Expand Down Expand Up @@ -285,8 +287,10 @@ status_t BnSurfaceComposer::onTransact(
uint32_t reqHeight = data.readInt32();
uint32_t minLayerZ = data.readInt32();
uint32_t maxLayerZ = data.readInt32();
bool isCpuConsumer = data.readInt32();
status_t res = captureScreen(display, producer,
reqWidth, reqHeight, minLayerZ, maxLayerZ);
reqWidth, reqHeight, minLayerZ, maxLayerZ,
isCpuConsumer);
reply->writeInt32(res);
return NO_ERROR;
}
Expand Down
5 changes: 3 additions & 2 deletions libs/gui/SurfaceComposerClient.cpp
Expand Up @@ -694,7 +694,8 @@ status_t ScreenshotClient::capture(
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
return s->captureScreen(display, producer,
reqWidth, reqHeight, minLayerZ, maxLayerZ);
reqWidth, reqHeight, minLayerZ, maxLayerZ,
false);
}

ScreenshotClient::ScreenshotClient()
Expand Down Expand Up @@ -736,7 +737,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display,
}

status_t err = s->captureScreen(display, mBufferQueue,
reqWidth, reqHeight, minLayerZ, maxLayerZ);
reqWidth, reqHeight, minLayerZ, maxLayerZ, true);

if (err == NO_ERROR) {
err = mCpuConsumer->lockNextBuffer(&mBuffer);
Expand Down
43 changes: 30 additions & 13 deletions services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
Expand Up @@ -185,28 +185,45 @@ void GLES11RenderEngine::disableBlending() {
}

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;
// turn our EGLImage into a texture
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);

// create a Framebuffer Object to render into
glGenFramebuffersOES(1, &name);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
if (!useReadPixels) {
// turn our EGLImage into a texture
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);

// create a Framebuffer Object to render into
glGenFramebuffersOES(1, &name);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
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);
*texName = tname;
*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);
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) {
Expand Down
4 changes: 2 additions & 2 deletions services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
Expand Up @@ -39,8 +39,8 @@ class GLES11RenderEngine : public RenderEngine {
GLint mMaxTextureSize;

virtual void bindImageAsFramebuffer(EGLImageKHR image,
uint32_t* texName, uint32_t* fbName, uint32_t* status);
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
uint32_t* texName, uint32_t* fbName, uint32_t* status, bool useReadPixels, int reqWidth, int reqHeight);
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels);

public:
GLES11RenderEngine();
Expand Down
41 changes: 29 additions & 12 deletions services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
Expand Up @@ -151,27 +151,44 @@ void GLES20RenderEngine::disableBlending() {


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;
// turn our EGLImage into a texture
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);

// create a Framebuffer Object to render into
glGenFramebuffers(1, &name);
glBindFramebuffer(GL_FRAMEBUFFER, name);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
if (!useReadPixels) {
// turn our EGLImage into a texture
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);

// create a Framebuffer Object to render into
glGenFramebuffers(1, &name);
glBindFramebuffer(GL_FRAMEBUFFER, name);
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);
*texName = tname;
*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);
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) {
Expand Down
5 changes: 3 additions & 2 deletions services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
Expand Up @@ -54,8 +54,9 @@ class GLES20RenderEngine : public RenderEngine {
Vector<Group> mGroupStack;

virtual void bindImageAsFramebuffer(EGLImageKHR image,
uint32_t* texName, uint32_t* fbName, uint32_t* status);
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
uint32_t* texName, uint32_t* fbName, uint32_t* status,
bool useReadPixels, int reqWidth, int reqHeight);
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName, bool useReadPixels);

public:
GLES20RenderEngine();
Expand Down
8 changes: 5 additions & 3 deletions services/surfaceflinger/RenderEngine/RenderEngine.cpp
Expand Up @@ -217,17 +217,19 @@ void RenderEngine::dump(String8& result) {
// ---------------------------------------------------------------------------

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,
"glCheckFramebufferStatusOES error %d", mStatus);
}

RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
// back to main framebuffer
mEngine.unbindFramebuffer(mTexName, mFbName);
mEngine.unbindFramebuffer(mTexName, mFbName, mUseReadPixels);
}

status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
Expand Down
7 changes: 4 additions & 3 deletions services/surfaceflinger/RenderEngine/RenderEngine.h
Expand Up @@ -47,8 +47,8 @@ class RenderEngine {
EGLContext mEGLContext;
void setEGLContext(EGLContext ctxt);

virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, 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:
RenderEngine();
Expand Down Expand Up @@ -76,8 +76,9 @@ class RenderEngine {
RenderEngine& mEngine;
uint32_t mTexName, mFbName;
uint32_t mStatus;
bool mUseReadPixels;
public:
BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image, bool useReadPixels, int reqWidth, int reqHeight);
~BindImageAsFramebuffer();
int getStatus() const;
};
Expand Down
34 changes: 26 additions & 8 deletions services/surfaceflinger/SurfaceFlinger.cpp
Expand Up @@ -2973,7 +2973,8 @@ class GraphicProducerWrapper : public BBinder, public MessageHandler {
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ) {
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useReadPixels) {

if (CC_UNLIKELY(display == 0))
return BAD_VALUE;
Expand All @@ -2999,16 +3000,18 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
sp<IGraphicBufferProducer> producer;
uint32_t reqWidth, reqHeight;
uint32_t minLayerZ,maxLayerZ;
bool useReadPixels;
status_t result;
public:
MessageCaptureScreen(SurfaceFlinger* flinger,
const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ)
uint32_t minLayerZ, uint32_t maxLayerZ, bool useReadPixels)
: flinger(flinger), display(display), producer(producer),
reqWidth(reqWidth), reqHeight(reqHeight),
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
useReadPixels(useReadPixels),
result(PERMISSION_DENIED)
{
}
Expand All @@ -3018,8 +3021,10 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
bool useReadPixels = this->useReadPixels && !flinger->mGpuToCpuSupported;
result = flinger->captureScreenImplLocked(hw,
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
useReadPixels);
static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
return true;
}
Expand All @@ -3041,7 +3046,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);
reqWidth, reqHeight, minLayerZ, maxLayerZ,
useReadPixels);

status_t res = postMessageAsync(msg);
if (res == NO_ERROR) {
Expand Down Expand Up @@ -3101,7 +3107,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
const sp<const DisplayDevice>& hw,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ)
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useReadPixels)
{
ATRACE_CALL();

Expand All @@ -3125,8 +3132,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(

status_t result = NO_ERROR;
if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) == NO_ERROR) {
uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
if (!useReadPixels) {
usage |= GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
}

int err = 0;
err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
Expand All @@ -3148,7 +3157,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(
if (image != EGL_NO_IMAGE_KHR) {
// this binds the given EGLImage as a framebuffer for the
// duration of this scope.
RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image, useReadPixels, reqWidth, reqHeight);
if (imageBond.getStatus() == NO_ERROR) {
// this will in fact render into our dequeued buffer
// via an FBO, which means we didn't have to create
Expand Down Expand Up @@ -3178,6 +3187,15 @@ status_t SurfaceFlinger::captureScreenImplLocked(
// not fatal
}

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) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
Expand Down
5 changes: 3 additions & 2 deletions services/surfaceflinger/SurfaceFlinger.h
Expand Up @@ -207,7 +207,7 @@ class SurfaceFlinger : public BnSurfaceComposer,
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
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
virtual void blank(const sp<IBinder>& display);
// called when screen is turning back on
Expand Down Expand Up @@ -321,7 +321,8 @@ class SurfaceFlinger : public BnSurfaceComposer,
const sp<const DisplayDevice>& hw,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ);
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useReadPixels);

/* ------------------------------------------------------------------------
* EGL
Expand Down

0 comments on commit 5f695d3

Please sign in to comment.