diff options
author | Pawit Pornkitprasan <p.pawit@gmail.com> | 2014-11-18 08:38:33 +0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-03-22 02:33:40 -0700 |
commit | cf8339b7657a2866dce3e4bd94a3cd0e4a01cd2c (patch) | |
tree | 8b542ae044cf0c45a8f2e37813d9eb8ace1e31c0 | |
parent | 4b444cbcae307bf59dab5361ecfe5cc0b27924d0 (diff) | |
download | android_frameworks_native-cf8339b7657a2866dce3e4bd94a3cd0e4a01cd2c.tar.gz android_frameworks_native-cf8339b7657a2866dce3e4bd94a3cd0e4a01cd2c.tar.bz2 android_frameworks_native-cf8339b7657a2866dce3e4bd94a3cd0e4a01cd2c.zip |
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 3ca76f416bc8665a97636ca8a2d0128b9da9d92c.
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
-rw-r--r-- | include/gui/ISurfaceComposer.h | 3 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 8 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp | 43 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES11RenderEngine.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp | 41 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/RenderEngine.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/RenderEngine.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 27 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 6 |
11 files changed, 108 insertions, 49 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 51717a412..640f4b3d8 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -145,7 +145,8 @@ public: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + Rotation rotation, + bool isCpuConsumer) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ebb687a28..0bb6ff211 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -108,7 +108,8 @@ public: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) + ISurfaceComposer::Rotation rotation, + bool isCpuConsumer) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -121,6 +122,7 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); + data.writeInt32(isCpuConsumer); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); return reply.readInt32(); } @@ -359,11 +361,13 @@ status_t BnSurfaceComposer::onTransact( uint32_t maxLayerZ = data.readInt32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); uint32_t rotation = data.readInt32(); + bool isCpuConsumer = data.readInt32(); status_t res = captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast<ISurfaceComposer::Rotation>(rotation)); + static_cast<ISurfaceComposer::Rotation>(rotation), + isCpuConsumer); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9e0704ac8..69fb4d1fb 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -695,7 +695,8 @@ status_t ScreenshotClient::capture( sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, + ISurfaceComposer::eRotateNone, false); } ScreenshotClient::ScreenshotClient() @@ -733,7 +734,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, status_t err = s->captureScreen(display, mProducer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast<ISurfaceComposer::Rotation>(rotation)); + static_cast<ISurfaceComposer::Rotation>(rotation), true); if (err == NO_ERROR) { err = mCpuConsumer->lockNextBuffer(&mBuffer); diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp index c2768f33a..ff0036f0f 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp @@ -216,28 +216,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) { diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h index 87eb3e4e4..5c3fdeca8 100644 --- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h @@ -40,8 +40,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(); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index c131e0b7c..13c29676e 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -197,27 +197,44 @@ void GLES20RenderEngine::endTileComposition(unsigned int preserveMask) { 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) { diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index d85be082d..92dfc03ae 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -55,8 +55,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(); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index a77e0e9d2..ee0c243aa 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -262,9 +262,11 @@ 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); @@ -272,7 +274,7 @@ RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { // back to main framebuffer - mEngine.unbindFramebuffer(mTexName, mFbName); + mEngine.unbindFramebuffer(mTexName, mFbName, mUseReadPixels); } status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 00e829267..30bb92a20 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -51,8 +51,8 @@ class RenderEngine { EGLContext mEGLContext; void setEGLHandles(EGLConfig config, 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(); @@ -83,8 +83,9 @@ public: 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; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index db2c53521..69e7c4066 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3415,7 +3415,8 @@ 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, ISurfaceComposer::Rotation rotation) { + bool useIdentityTransform, ISurfaceComposer::Rotation rotation, + bool useReadPixels) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; @@ -3465,6 +3466,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, uint32_t minLayerZ,maxLayerZ; bool useIdentityTransform; Transform::orientation_flags rotation; + bool useReadPixels; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, @@ -3472,12 +3474,14 @@ 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, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) : flinger(flinger), display(display), producer(producer), sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), useIdentityTransform(useIdentityTransform), rotation(rotation), + useReadPixels(useReadPixels), result(PERMISSION_DENIED) { } @@ -3487,9 +3491,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, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotation); + useIdentityTransform, rotation, useReadPixels); static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); return true; } @@ -3512,7 +3517,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, rotationFlags); + useIdentityTransform, rotationFlags, useReadPixels); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3618,7 +3623,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation) + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels) { ATRACE_CALL(); @@ -3665,7 +3671,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 @@ -3701,7 +3707,14 @@ status_t SurfaceFlinger::captureScreenImplLocked( ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError()); // 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); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ecc189b9e..5db008a87 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -212,7 +212,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, 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, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp<IBinder>& display, @@ -347,7 +348,8 @@ private: const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation); + bool useIdentityTransform, Transform::orientation_flags rotation, + bool useReadPixels); /* ------------------------------------------------------------------------ * EGL |