Merge "Add some free zoom to lockHardwareCanvas" into lmp-mr1-dev
This commit is contained in:
@ -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)
|
||||||
|
@ -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)) {
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user