Merge "Add some free zoom to lockHardwareCanvas" into lmp-mr1-dev

This commit is contained in:
John Reck
2014-10-23 21:59:25 +00:00
committed by Android (Google) Code Review
7 changed files with 63 additions and 27 deletions

View File

@ -374,6 +374,7 @@ static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfaceP
ContextFactory factory; ContextFactory factory;
RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
proxy->loadSystemProperties(); proxy->loadSystemProperties();
proxy->setSwapBehavior(kSwap_discardBuffer);
proxy->initialize(surface); proxy->initialize(surface);
// Shadows can't be used via this interface, so just set the light source // Shadows can't be used via this interface, so just set the light source
// to all 0s. (and width & height are unused, TODO remove them) // to all 0s. (and width & height are unused, TODO remove them)

View File

@ -42,7 +42,8 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
: mRenderThread(thread) : mRenderThread(thread)
, mEglManager(thread.eglManager()) , mEglManager(thread.eglManager())
, mEglSurface(EGL_NO_SURFACE) , mEglSurface(EGL_NO_SURFACE)
, mDirtyRegionsEnabled(false) , mBufferPreserved(false)
, mSwapBehavior(kSwap_default)
, mOpaque(!translucent) , mOpaque(!translucent)
, mCanvas(NULL) , mCanvas(NULL)
, mHaveNewSurface(false) , mHaveNewSurface(false)
@ -82,7 +83,8 @@ void CanvasContext::setSurface(ANativeWindow* window) {
} }
if (mEglSurface != EGL_NO_SURFACE) { if (mEglSurface != EGL_NO_SURFACE) {
mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface); const bool preserveBuffer = (mSwapBehavior != kSwap_discardBuffer);
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
mHaveNewSurface = true; mHaveNewSurface = true;
makeCurrent(); makeCurrent();
} else { } else {
@ -103,6 +105,10 @@ void CanvasContext::requireSurface() {
makeCurrent(); makeCurrent();
} }
void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
mSwapBehavior = swapBehavior;
}
bool CanvasContext::initialize(ANativeWindow* window) { bool CanvasContext::initialize(ANativeWindow* window) {
setSurface(window); setSurface(window);
if (mCanvas) return false; if (mCanvas) return false;
@ -200,7 +206,7 @@ void CanvasContext::draw() {
if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
mCanvas->setViewport(width, height); mCanvas->setViewport(width, height);
dirty.setEmpty(); dirty.setEmpty();
} else if (!mDirtyRegionsEnabled || mHaveNewSurface) { } else if (!mBufferPreserved || mHaveNewSurface) {
dirty.setEmpty(); dirty.setEmpty();
} else { } else {
if (!dirty.isEmpty() && !dirty.intersect(0, 0, width, height)) { if (!dirty.isEmpty() && !dirty.intersect(0, 0, width, height)) {

View File

@ -48,6 +48,11 @@ namespace renderthread {
class EglManager; class EglManager;
enum SwapBehavior {
kSwap_default,
kSwap_discardBuffer,
};
// This per-renderer class manages the bridge between the global EGL context // This per-renderer class manages the bridge between the global EGL context
// and the render surface. // and the render surface.
// TODO: Rename to Renderer or some other per-window, top-level manager // TODO: Rename to Renderer or some other per-window, top-level manager
@ -57,6 +62,9 @@ public:
IContextFactory* contextFactory); IContextFactory* contextFactory);
virtual ~CanvasContext(); virtual ~CanvasContext();
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
bool initialize(ANativeWindow* window); bool initialize(ANativeWindow* window);
void updateSurface(ANativeWindow* window); void updateSurface(ANativeWindow* window);
void pauseSurface(ANativeWindow* window); void pauseSurface(ANativeWindow* window);
@ -111,7 +119,8 @@ private:
EglManager& mEglManager; EglManager& mEglManager;
sp<ANativeWindow> mNativeWindow; sp<ANativeWindow> mNativeWindow;
EGLSurface mEglSurface; EGLSurface mEglSurface;
bool mDirtyRegionsEnabled; bool mBufferPreserved;
SwapBehavior mSwapBehavior;
bool mOpaque; bool mOpaque;
OpenGLRenderer* mCanvas; OpenGLRenderer* mCanvas;

View File

@ -70,12 +70,12 @@ EglManager::EglManager(RenderThread& thread)
, mEglConfig(0) , mEglConfig(0)
, mEglContext(EGL_NO_CONTEXT) , mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE) , mPBufferSurface(EGL_NO_SURFACE)
, mRequestDirtyRegions(load_dirty_regions_property()) , mAllowPreserveBuffer(load_dirty_regions_property())
, mCurrentSurface(EGL_NO_SURFACE) , mCurrentSurface(EGL_NO_SURFACE)
, mAtlasMap(NULL) , mAtlasMap(NULL)
, mAtlasMapSize(0) { , mAtlasMapSize(0) {
mCanSetDirtyRegions = mRequestDirtyRegions; mCanSetPreserveBuffer = mAllowPreserveBuffer;
ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false"); ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false");
} }
void EglManager::initialize() { void EglManager::initialize() {
@ -113,7 +113,7 @@ void EglManager::requireGlContext() {
} }
void EglManager::loadConfig() { void EglManager::loadConfig() {
EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; EGLint swapBehavior = mCanSetPreserveBuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
EGLint attribs[] = { EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8, EGL_RED_SIZE, 8,
@ -131,10 +131,10 @@ void EglManager::loadConfig() {
if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
|| num_configs != 1) { || num_configs != 1) {
// Failed to get a valid config // Failed to get a valid config
if (mCanSetDirtyRegions) { if (mCanSetPreserveBuffer) {
ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
// Try again without dirty regions enabled // Try again without dirty regions enabled
mCanSetDirtyRegions = false; mCanSetPreserveBuffer = false;
loadConfig(); loadConfig();
} else { } else {
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
@ -273,25 +273,30 @@ bool EglManager::swapBuffers(EGLSurface surface) {
return false; return false;
} }
bool EglManager::enableDirtyRegions(EGLSurface surface) { bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
if (!mRequestDirtyRegions) return false; if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false;
if (mCanSetDirtyRegions) { bool preserved = false;
if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { if (mCanSetPreserveBuffer) {
preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
if (CC_UNLIKELY(!preserved)) {
ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
(void*) surface, egl_error_str()); (void*) surface, egl_error_str());
return false;
} }
return true;
} }
// Perhaps it is already enabled? if (CC_UNLIKELY(!preserved)) {
EGLint value; // Maybe it's already set?
if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) { EGLint swapBehavior;
if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
} else {
ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
(void*) surface, egl_error_str()); (void*) surface, egl_error_str());
return false;
} }
return value == EGL_BUFFER_PRESERVED; }
return preserved;
} }
} /* namespace renderthread */ } /* namespace renderthread */

View File

@ -49,7 +49,8 @@ public:
void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
bool swapBuffers(EGLSurface surface); bool swapBuffers(EGLSurface surface);
bool enableDirtyRegions(EGLSurface surface); // Returns true iff the surface is now preserving buffers.
bool setPreserveBuffer(EGLSurface surface, bool preserve);
void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
@ -71,8 +72,8 @@ private:
EGLContext mEglContext; EGLContext mEglContext;
EGLSurface mPBufferSurface; EGLSurface mPBufferSurface;
const bool mRequestDirtyRegions; const bool mAllowPreserveBuffer;
bool mCanSetDirtyRegions; bool mCanSetPreserveBuffer;
EGLSurface mCurrentSurface; EGLSurface mCurrentSurface;

View File

@ -103,6 +103,18 @@ void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) {
post(task); post(task);
} }
CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
args->context->setSwapBehavior(args->swapBehavior);
return NULL;
}
void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
SETUP_TASK(setSwapBehavior);
args->context = mContext;
args->swapBehavior = swapBehavior;
post(task);
}
CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
bool needsRedraw = false; bool needsRedraw = false;
if (Caches::hasInstance()) { if (Caches::hasInstance()) {

View File

@ -31,6 +31,7 @@
#include "../Caches.h" #include "../Caches.h"
#include "../IContextFactory.h" #include "../IContextFactory.h"
#include "CanvasContext.h"
#include "DrawFrameTask.h" #include "DrawFrameTask.h"
namespace android { namespace android {
@ -44,7 +45,6 @@ class Rect;
namespace renderthread { namespace renderthread {
class CanvasContext;
class ErrorChannel; class ErrorChannel;
class RenderThread; class RenderThread;
class RenderProxyBridge; class RenderProxyBridge;
@ -63,6 +63,8 @@ public:
ANDROID_API virtual ~RenderProxy(); ANDROID_API virtual ~RenderProxy();
ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos); ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos);
// Won't take effect until next EGLSurface creation
ANDROID_API void setSwapBehavior(SwapBehavior swapBehavior);
ANDROID_API bool loadSystemProperties(); ANDROID_API bool loadSystemProperties();
ANDROID_API bool initialize(const sp<ANativeWindow>& window); ANDROID_API bool initialize(const sp<ANativeWindow>& window);