Add eglSwapBuffersWithDamageKHR support

BUG: 20761426
Disabled temporarily

Change-Id: I0b6b6f0eebab886145e13fa35aefe76826965cf5
This commit is contained in:
John Reck
2015-05-08 10:04:36 -07:00
parent a0698b617f
commit d04794a9a3
6 changed files with 76 additions and 32 deletions

View File

@@ -28,6 +28,8 @@ bool Properties::drawReorderDisabled = false;
bool Properties::debugLayersUpdates = false;
bool Properties::debugOverdraw = false;
bool Properties::showDirtyRegions = false;
bool Properties::skipEmptyFrames = true;
bool Properties::swapBuffersWithDamage = false;
DebugLevel Properties::debugLevel = kDebugDisabled;
OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default;
@@ -101,6 +103,9 @@ bool Properties::load() {
debugLevel = (DebugLevel) atoi(property);
}
skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true);
swapBuffersWithDamage = property_get_bool(PROPERTY_SWAP_WITH_DAMAGE, false);
return (prevDebugLayersUpdates != debugLayersUpdates)
|| (prevDebugOverdraw != debugOverdraw)
|| (prevDebugStencilClip != debugStencilClip);

View File

@@ -158,6 +158,21 @@ enum DebugLevel {
*/
#define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder"
/**
* Setting this property will enable or disable the dropping of frames with
* empty damage. Default is "true".
*/
#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage"
/**
* Setting this property will enable usage of EGL_KHR_swap_buffers_with_damage
* See: https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt
* Default is "false" temporarily
* TODO: Change to "true", make sure to remove the log in EglManager::swapBuffers
* before changing this to default to true!
*/
#define PROPERTY_SWAP_WITH_DAMAGE "debug.hwui.swap_with_damage"
///////////////////////////////////////////////////////////////////////////////
// Runtime configuration properties
///////////////////////////////////////////////////////////////////////////////
@@ -288,6 +303,10 @@ public:
static bool debugLayersUpdates;
static bool debugOverdraw;
static bool showDirtyRegions;
// TODO: Remove after stabilization period
static bool skipEmptyFrames;
// TODO: Remove after stabilization period
static bool swapBuffersWithDamage;
static DebugLevel debugLevel;
static OverdrawColorSet overdrawColorSet;

View File

@@ -16,36 +16,25 @@
#include "CanvasContext.h"
#include "AnimationContext.h"
#include "Caches.h"
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
#include "Properties.h"
#include "RenderThread.h"
#include "../AnimationContext.h"
#include "../Caches.h"
#include "../DeferredLayerUpdater.h"
#include "../renderstate/RenderState.h"
#include "../renderstate/Stencil.h"
#include "../LayerRenderer.h"
#include "../OpenGLRenderer.h"
#include "renderstate/RenderState.h"
#include "renderstate/Stencil.h"
#include <algorithm>
#include <strings.h>
#include <cutils/properties.h>
#include <private/hwui/DrawGlInfo.h>
#include <strings.h>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage"
static bool sInitialized = false;
static bool sSkipEmptyDamage = true;
static void initGlobals() {
if (sInitialized) return;
sInitialized = true;
sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE,
sSkipEmptyDamage);
}
namespace android {
namespace uirenderer {
namespace renderthread {
@@ -58,9 +47,6 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
, mRootRenderNode(rootRenderNode)
, mJankTracker(thread.timeLord().frameIntervalNanos()) {
// Done lazily at first draw instead of at library load to avoid
// running pre-zygote fork
initGlobals();
mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
}
@@ -106,8 +92,8 @@ void CanvasContext::setSurface(ANativeWindow* window) {
}
}
void CanvasContext::swapBuffers() {
if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) {
void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height) {
if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface, dirty, width, height))) {
setSurface(nullptr);
}
mHaveNewSurface = false;
@@ -222,7 +208,7 @@ void CanvasContext::draw() {
SkRect dirty;
mDamageAccumulator.finish(&dirty);
if (dirty.isEmpty() && sSkipEmptyDamage) {
if (dirty.isEmpty() && Properties::skipEmptyFrames) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
return;
}
@@ -267,7 +253,7 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markSwapBuffers();
if (drew) {
swapBuffers();
swapBuffers(dirty, width, height);
} else {
mEglManager.cancelFrame();
}

View File

@@ -29,6 +29,7 @@
#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkBitmap.h>
#include <SkRect.h>
#include <utils/Functor.h>
#include <utils/Vector.h>
@@ -117,7 +118,7 @@ private:
friend class android::uirenderer::RenderState;
void setSurface(ANativeWindow* window);
void swapBuffers();
void swapBuffers(const SkRect& dirty, EGLint width, EGLint height);
void requireSurface();
void requireGlContext();

View File

@@ -16,9 +16,10 @@
#include "EglManager.h"
#include "../Caches.h"
#include "../renderstate/RenderState.h"
#include "Caches.h"
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
#include <cutils/log.h>
#include <cutils/properties.h>
@@ -261,7 +262,8 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
mInFrame = true;
}
bool EglManager::swapBuffers(EGLSurface surface) {
bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty,
EGLint width, EGLint height) {
mInFrame = false;
#if WAIT_FOR_GPU_COMPLETION
@@ -271,7 +273,37 @@ bool EglManager::swapBuffers(EGLSurface surface) {
}
#endif
#ifdef EGL_KHR_swap_buffers_with_damage
if (CC_UNLIKELY(Properties::swapBuffersWithDamage)) {
SkIRect idirty;
dirty.roundOut(&idirty);
/*
* EGL_KHR_swap_buffers_with_damage spec states:
*
* The rectangles are specified relative to the bottom-left of the surface
* and the x and y components of each rectangle specify the bottom-left
* position of that rectangle.
*
* HWUI does everything with 0,0 being top-left, so need to map
* the rect
*/
EGLint y = height - (idirty.y() + idirty.height());
// layout: {x, y, width, height}
EGLint rects[4] = { idirty.x(), y, idirty.width(), idirty.height() };
EGLint numrects = dirty.isEmpty() ? 0 : 1;
// TODO: Remove prior to enabling this path by default
ALOGD("Swap buffers with damage %d: %d, %d, %d, %d (src="
RECT_STRING ")",
dirty.isEmpty() ? 0 : 1, rects[0], rects[1], rects[2], rects[3],
SK_RECT_ARGS(dirty));
eglSwapBuffersWithDamageKHR(mEglDisplay, surface, rects, numrects);
} else {
eglSwapBuffers(mEglDisplay, surface);
}
#else
eglSwapBuffers(mEglDisplay, surface);
#endif
EGLint err = eglGetError();
if (CC_LIKELY(err == EGL_SUCCESS)) {
return true;

View File

@@ -18,6 +18,7 @@
#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkRect.h>
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
@@ -47,7 +48,7 @@ public:
// Returns true if the current surface changed, false if it was already current
bool makeCurrent(EGLSurface surface);
void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
bool swapBuffers(EGLSurface surface);
bool swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height);
void cancelFrame();
// Returns true iff the surface is now preserving buffers.