summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2014-06-30 16:20:04 -0700
committerJohn Reck <jreck@google.com>2014-06-30 16:36:26 -0700
commitf47a594f5250b1914c36423ee6b371f0b8db09d0 (patch)
treef86289c7b515c2111fde3ce11e7fca384bc2f603
parentdd59aba6c7e142eae14d5f29ea6873a5b9790174 (diff)
downloadframeworks_base-f47a594f5250b1914c36423ee6b371f0b8db09d0.zip
frameworks_base-f47a594f5250b1914c36423ee6b371f0b8db09d0.tar.gz
frameworks_base-f47a594f5250b1914c36423ee6b371f0b8db09d0.tar.bz2
Fix onTrimMemory for HardwareRenderer
Also fixes detachFunctor possibly drawing after return Bug: 15189843 Bug: 15990672 Change-Id: I64c48cb674c461a8eeaba407b697e09f72c98ce3
-rw-r--r--core/java/android/app/ActivityThread.java9
-rw-r--r--core/java/android/view/GLES20Canvas.java25
-rw-r--r--core/java/android/view/HardwareRenderer.java40
-rw-r--r--core/java/android/view/ThreadedRenderer.java21
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/android/view/ViewRootImpl.java14
-rw-r--r--core/java/android/view/WindowManagerGlobal.java46
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp21
-rw-r--r--libs/hwui/RenderNode.cpp19
-rw-r--r--libs/hwui/TreeInfo.h3
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp34
-rw-r--r--libs/hwui/renderthread/CanvasContext.h4
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp33
-rw-r--r--libs/hwui/renderthread/RenderProxy.h4
-rw-r--r--opengl/java/android/opengl/ManagedEGLContext.java137
15 files changed, 142 insertions, 272 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f5514f8..422d88c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3962,10 +3962,6 @@ public final class ActivityThread {
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
- // Cleanup hardware accelerated stuff
- // TODO: Do we actually want to do this in response to all config changes?
- WindowManagerGlobal.getInstance().trimLocalMemory();
-
freeTextLayoutCachesIfNeeded(configDiff);
if (callbacks != null) {
@@ -4100,9 +4096,6 @@ public final class ActivityThread {
final void handleTrimMemory(int level) {
if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
- final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
- windowManager.startTrimMemory(level);
-
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
final int N = callbacks.size();
@@ -4110,7 +4103,7 @@ public final class ActivityThread {
callbacks.get(i).onTrimMemory(level);
}
- windowManager.endTrimMemory();
+ WindowManagerGlobal.getInstance().trimMemory(level);
}
private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index dcd9ba9..d7d3c72 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -203,31 +203,6 @@ class GLES20Canvas extends HardwareCanvas {
private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
///////////////////////////////////////////////////////////////////////////
- // Memory
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- * Must match Caches::FlushMode values
- *
- * @see #flushCaches(int)
- */
- static final int FLUSH_CACHES_LAYERS = 0;
-
- /**
- * Must match Caches::FlushMode values
- *
- * @see #flushCaches(int)
- */
- static final int FLUSH_CACHES_MODERATE = 1;
-
- /**
- * Must match Caches::FlushMode values
- *
- * @see #flushCaches(int)
- */
- static final int FLUSH_CACHES_FULL = 2;
-
- ///////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e9bdcae..d69d01d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -18,8 +18,6 @@ package android.view;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
import android.util.DisplayMetrics;
import android.view.Surface.OutOfResourcesException;
@@ -200,10 +198,8 @@ public abstract class HardwareRenderer {
/**
* Destroys the hardware rendering context.
- *
- * @param full If true, destroys all associated resources.
*/
- abstract void destroy(boolean full);
+ abstract void destroy();
/**
* Initializes the hardware renderer for the specified surface.
@@ -435,28 +431,7 @@ public abstract class HardwareRenderer {
* see {@link android.content.ComponentCallbacks}
*/
static void trimMemory(int level) {
- startTrimMemory(level);
- endTrimMemory();
- }
-
- /**
- * Starts the process of trimming memory. Usually this call will setup
- * hardware rendering context and reclaim memory.Extra cleanup might
- * be required by calling {@link #endTrimMemory()}.
- *
- * @param level Hint about the amount of memory that should be trimmed,
- * see {@link android.content.ComponentCallbacks}
- */
- static void startTrimMemory(int level) {
- ThreadedRenderer.startTrimMemory(level);
- }
-
- /**
- * Finishes the process of trimming memory. This method will usually
- * cleanup special resources used by the memory trimming process.
- */
- static void endTrimMemory() {
- ThreadedRenderer.endTrimMemory();
+ ThreadedRenderer.trimMemory(level);
}
/**
@@ -503,8 +478,15 @@ public abstract class HardwareRenderer {
abstract void fence();
/**
+ * Prevents any further drawing until draw() is called. This is a signal
+ * that the contents of the RenderNode tree are no longer safe to play back.
+ * In practice this usually means that there are Functor pointers in the
+ * display list that are no longer valid.
+ */
+ abstract void stopDrawing();
+
+ /**
* Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
*/
- public void notifyFramePending() {
- }
+ abstract void notifyFramePending();
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 45714ff..fcc51ec 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -90,7 +90,7 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
- void destroy(boolean full) {
+ void destroy() {
mInitialized = false;
updateEnabledState(null);
nDestroyCanvasAndSurface(mNativeProxy);
@@ -125,7 +125,7 @@ public class ThreadedRenderer extends HardwareRenderer {
@Override
void destroyHardwareResources(View view) {
destroyResources(view);
- nFlushCaches(mNativeProxy, GLES20Canvas.FLUSH_CACHES_LAYERS);
+ nDestroyHardwareResources(mNativeProxy);
}
private static void destroyResources(View view) {
@@ -289,6 +289,11 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
+ void stopDrawing() {
+ nStopDrawing(mNativeProxy);
+ }
+
+ @Override
public void notifyFramePending() {
nNotifyFramePending(mNativeProxy);
}
@@ -303,12 +308,8 @@ public class ThreadedRenderer extends HardwareRenderer {
}
}
- static void startTrimMemory(int level) {
- // TODO
- }
-
- static void endTrimMemory() {
- // TODO
+ static void trimMemory(int level) {
+ nTrimMemory(level);
}
private static class AtlasInitializer {
@@ -403,9 +404,11 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native void nCancelLayerUpdate(long nativeProxy, long layer);
private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
- private static native void nFlushCaches(long nativeProxy, int flushMode);
+ private static native void nDestroyHardwareResources(long nativeProxy);
+ private static native void nTrimMemory(int level);
private static native void nFence(long nativeProxy);
+ private static native void nStopDrawing(long nativeProxy);
private static native void nNotifyFramePending(long nativeProxy);
private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 829e089..6cfc019 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13598,7 +13598,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
protected void destroyHardwareResources() {
- resetDisplayList();
+ // Intentionally empty. RenderNode's lifecycle is now fully managed
+ // by the hardware renderer.
+ // However some subclasses (eg, WebView, TextureView) still need this signal
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4c9d3f9..3219330 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -632,21 +632,17 @@ public final class ViewRootImpl implements ViewParent,
void destroyHardwareResources() {
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
- mAttachInfo.mHardwareRenderer.destroy(false);
+ mAttachInfo.mHardwareRenderer.destroy();
}
}
- void destroyHardwareLayers() {
- // TODO Implement
- }
-
public void detachFunctor(long functor) {
// TODO: Make the resize buffer some other way to not need this block
mBlockResizeBuffer = true;
if (mAttachInfo.mHardwareRenderer != null) {
// Fence so that any pending invokeFunctor() messages will be processed
// before we return from detachFunctor.
- mAttachInfo.mHardwareRenderer.fence();
+ mAttachInfo.mHardwareRenderer.stopDrawing();
}
}
@@ -696,7 +692,7 @@ public final class ViewRootImpl implements ViewParent,
if (!HardwareRenderer.sRendererDisabled || (HardwareRenderer.sSystemRendererDisabled
&& forceHwAccelerated)) {
if (mAttachInfo.mHardwareRenderer != null) {
- mAttachInfo.mHardwareRenderer.destroy(true);
+ mAttachInfo.mHardwareRenderer.destroy();
}
final boolean translucent = attrs.format != PixelFormat.OPAQUE;
@@ -1613,7 +1609,7 @@ public final class ViewRootImpl implements ViewParent,
// Our surface is gone
if (mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled()) {
- mAttachInfo.mHardwareRenderer.destroy(true);
+ mAttachInfo.mHardwareRenderer.destroy();
}
} else if (surfaceGenerationId != mSurface.getGenerationId() &&
mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
@@ -5436,7 +5432,7 @@ public final class ViewRootImpl implements ViewParent,
if (mView != null) {
hardwareRenderer.destroyHardwareResources(mView);
}
- hardwareRenderer.destroy(true);
+ hardwareRenderer.destroy();
hardwareRenderer.setRequested(false);
attachInfo.mHardwareRenderer = null;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 0ebf2e1..74bc186 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -20,7 +20,6 @@ import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
-import android.opengl.ManagedEGLContext;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -114,7 +113,6 @@ public final class WindowManagerGlobal {
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();
- private boolean mNeedsEglTerminate;
private Runnable mSystemPropertyUpdater;
@@ -377,13 +375,22 @@ public final class WindowManagerGlobal {
return index;
}
- public void startTrimMemory(int level) {
+ public static boolean shouldDestroyEglContext(int trimLevel) {
+ // On low-end gfx devices we trim when memory is moderate;
+ // on high-end devices we do this when low.
+ if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+ return true;
+ }
+ if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+ && !ActivityManager.isHighEndGfx()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void trimMemory(int level) {
if (HardwareRenderer.isAvailable()) {
- // On low-end gfx devices we trim when memory is moderate;
- // on high-end devices we do this when low.
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
- || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
- && !ActivityManager.isHighEndGfx())) {
+ if (shouldDestroyEglContext(level)) {
// Destroy all hardware surfaces and resources associated to
// known windows
synchronized (mLock) {
@@ -392,29 +399,10 @@ public final class WindowManagerGlobal {
}
}
// Force a full memory flush
- mNeedsEglTerminate = true;
- HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
- return;
+ level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
}
- HardwareRenderer.startTrimMemory(level);
- }
- }
-
- public void endTrimMemory() {
- HardwareRenderer.endTrimMemory();
-
- if (mNeedsEglTerminate) {
- ManagedEGLContext.doTerminate();
- mNeedsEglTerminate = false;
- }
- }
-
- public void trimLocalMemory() {
- synchronized (mLock) {
- for (int i = mRoots.size() - 1; i >= 0; --i) {
- mRoots.get(i).destroyHardwareLayers();
- }
+ HardwareRenderer.trimMemory(level);
}
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index e63c475..aab48b3 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -298,10 +298,15 @@ static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobj
proxy->detachSurfaceTexture(layer);
}
-static void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jint flushMode) {
+static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->flushCaches(static_cast<Caches::FlushMode>(flushMode));
+ proxy->destroyHardwareResources();
+}
+
+static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
+ jint level) {
+ RenderProxy::trimMemory(level);
}
static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
@@ -310,6 +315,12 @@ static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
proxy->fence();
}
+static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->stopDrawing();
+}
+
static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -365,8 +376,10 @@ static JNINativeMethod gMethods[] = {
{ "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
{ "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
{ "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
- { "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches },
+ { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
+ { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
+ { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
{ "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
#endif
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e803ec3..89105ea 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -195,17 +195,28 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
void RenderNode::prepareTreeImpl(TreeInfo& info) {
info.damageAccumulator->pushTransform(this);
- if (info.mode == TreeInfo::MODE_FULL) {
+
+ switch (info.mode) {
+ case TreeInfo::MODE_FULL:
pushStagingPropertiesChanges(info);
mAnimatorManager.animate(info);
- } else if (info.mode == TreeInfo::MODE_MAYBE_DETACHING) {
+ break;
+ case TreeInfo::MODE_MAYBE_DETACHING:
pushStagingPropertiesChanges(info);
- } else if (info.mode == TreeInfo::MODE_RT_ONLY) {
+ break;
+ case TreeInfo::MODE_RT_ONLY:
mAnimatorManager.animate(info);
+ break;
+ case TreeInfo::MODE_DESTROY_RESOURCES:
+ // This will also release the hardware layer if we have one as
+ // isRenderable() will return false, thus causing pushLayerUpdate
+ // to recycle the hardware layer
+ setStagingDisplayList(NULL);
+ break;
}
prepareLayer(info);
- if (info.mode == TreeInfo::MODE_FULL) {
+ if (info.mode == TreeInfo::MODE_FULL || info.mode == TreeInfo::MODE_DESTROY_RESOURCES) {
pushStagingDisplayListChanges(info);
}
prepareSubTree(info, mDisplayListData);
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 083100e..9746ac53 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -65,7 +65,8 @@ public:
// but don't evaluate animators and such as if it isn't detached as a
// MODE_FULL will follow shortly.
MODE_MAYBE_DETACHING,
- // TODO: TRIM_MEMORY?
+ // Destroy all hardware resources, including DisplayListData, in the tree.
+ MODE_DESTROY_RESOURCES,
};
explicit TreeInfo(TraversalMode mode, RenderState& renderState)
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9c3cf44..524ee62 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -30,6 +30,9 @@
#include "../OpenGLRenderer.h"
#include "../Stencil.h"
+#define TRIM_MEMORY_COMPLETE 80
+#define TRIM_MEMORY_UI_HIDDEN 20
+
namespace android {
namespace uirenderer {
namespace renderthread {
@@ -156,6 +159,10 @@ void CanvasContext::prepareTree(TreeInfo& info) {
}
}
+void CanvasContext::stopDrawing() {
+ mRenderThread.removeFrameCallback(this);
+}
+
void CanvasContext::notifyFramePending() {
ATRACE_CALL();
mRenderThread.pushBackFrameCallback(this);
@@ -216,8 +223,6 @@ void CanvasContext::doFrame() {
profiler().startFrame();
TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
- info.prepareTextures = false;
-
prepareTree(info);
if (info.out.canDrawThisFrame) {
draw();
@@ -241,10 +246,25 @@ bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap)
return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
}
-void CanvasContext::flushCaches(Caches::FlushMode flushMode) {
+void CanvasContext::destroyHardwareResources() {
+ stopDrawing();
if (mEglManager.hasEglContext()) {
requireGlContext();
- Caches::getInstance().flush(flushMode);
+ TreeInfo info(TreeInfo::MODE_DESTROY_RESOURCES, mRenderThread.renderState());
+ mRootRenderNode->prepareTree(info);
+ Caches::getInstance().flush(Caches::kFlushMode_Layers);
+ }
+}
+
+void CanvasContext::trimMemory(RenderThread& thread, int level) {
+ // No context means nothing to free
+ if (!thread.eglManager().hasEglContext()) return;
+
+ if (level >= TRIM_MEMORY_COMPLETE) {
+ Caches::getInstance().flush(Caches::kFlushMode_Full);
+ thread.eglManager().destroy();
+ } else if (level >= TRIM_MEMORY_UI_HIDDEN) {
+ Caches::getInstance().flush(Caches::kFlushMode_Moderate);
}
}
@@ -264,11 +284,7 @@ Layer* CanvasContext::createTextureLayer() {
}
void CanvasContext::requireGlContext() {
- if (mEglSurface != EGL_NO_SURFACE) {
- makeCurrent();
- } else {
- mEglManager.usePBufferSurface();
- }
+ mEglManager.requireGlContext();
}
void CanvasContext::setTextureAtlas(RenderThread& thread,
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index dbfb3d2..1bab1b1 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -66,7 +66,8 @@ public:
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
- void flushCaches(Caches::FlushMode flushMode);
+ void destroyHardwareResources();
+ static void trimMemory(RenderThread& thread, int level);
static void invokeFunctor(RenderThread& thread, Functor* functor);
@@ -78,6 +79,7 @@ public:
ANDROID_API static void setTextureAtlas(RenderThread& thread,
const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
+ void stopDrawing();
void notifyFramePending();
DrawProfiler& profiler() { return mProfiler; }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e1ee620..6cd3d0b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -312,18 +312,30 @@ void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
postAndWait(task);
}
-CREATE_BRIDGE2(flushCaches, CanvasContext* context, Caches::FlushMode flushMode) {
- args->context->flushCaches(args->flushMode);
+CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
+ args->context->destroyHardwareResources();
return NULL;
}
-void RenderProxy::flushCaches(Caches::FlushMode flushMode) {
- SETUP_TASK(flushCaches);
+void RenderProxy::destroyHardwareResources() {
+ SETUP_TASK(destroyHardwareResources);
args->context = mContext;
- args->flushMode = flushMode;
post(task);
}
+CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) {
+ CanvasContext::trimMemory(*args->thread, args->level);
+ return NULL;
+}
+
+void RenderProxy::trimMemory(int level) {
+ RenderThread& thread = RenderThread::getInstance();
+ SETUP_TASK(timMemory);
+ args->thread = &thread;
+ args->level = level;
+ thread.queue(task);
+}
+
CREATE_BRIDGE0(fence) {
// Intentionally empty
return NULL;
@@ -334,6 +346,17 @@ void RenderProxy::fence() {
postAndWait(task);
}
+CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
+ args->context->stopDrawing();
+ return NULL;
+}
+
+void RenderProxy::stopDrawing() {
+ SETUP_TASK(stopDrawing);
+ args->context = mContext;
+ postAndWait(task);
+}
+
CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
args->context->notifyFramePending();
return NULL;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index c7358e6..0027403 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -85,9 +85,11 @@ public:
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
- ANDROID_API void flushCaches(Caches::FlushMode flushMode);
+ ANDROID_API void destroyHardwareResources();
+ ANDROID_API static void trimMemory(int level);
ANDROID_API void fence();
+ ANDROID_API void stopDrawing();
ANDROID_API void notifyFramePending();
ANDROID_API void dumpProfileInfo(int fd);
diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java
deleted file mode 100644
index 61fa565..0000000
--- a/opengl/java/android/opengl/ManagedEGLContext.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.opengl;
-
-import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
-
-import java.util.ArrayList;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-
-import android.os.Looper;
-import android.util.Log;
-
-import com.google.android.gles_jni.EGLImpl;
-
-/**
- * The per-process memory overhead of hardware accelerated graphics can
- * be quite large on some devices. For small memory devices, being able to
- * terminate all EGL contexts so that this graphics driver memory can be
- * reclaimed can significant improve the overall behavior of the device. This
- * class helps app developers participate in releasing their EGL context
- * when appropriate and possible.
- *
- * <p>To use, simple instantiate this class with the EGLContext you create.
- * When you have done this, if the device is getting low on memory and all
- * of the currently created EGL contexts in the process are being managed
- * through this class, then they will all be asked to terminate through the
- * call to {@link #onTerminate}.
- *
- * @hide
- */
-public abstract class ManagedEGLContext {
- static final String TAG = "ManagedEGLContext";
-
- static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
-
- final EGLContext mContext;
-
- /**
- * Instantiate to manage the given EGLContext.
- */
- public ManagedEGLContext(EGLContext context) {
- mContext = context;
- synchronized (sActive) {
- sActive.add(this);
- }
- }
-
- /**
- * Retrieve the EGLContext being managed by the class.
- */
- public EGLContext getContext() {
- return mContext;
- }
-
- /**
- * Force-terminate the ManagedEGLContext. This will cause
- * {@link #onTerminate(EGLContext)} to be called. You <em>must</em>
- * call this when destroying the EGLContext, so that the framework
- * knows to stop managing it.
- */
- public void terminate() {
- execTerminate();
- }
-
- void execTerminate() {
- onTerminate(mContext);
- }
-
- /**
- * Override this method to destroy the EGLContext when appropriate.
- * <em>Note that this method is always called on the main thread
- * of the process.</em> If your EGLContext was created on a different
- * thread, you will need to implement this method to hand off the work
- * of destroying the context to that thread.
- */
- public abstract void onTerminate(EGLContext context);
-
- /** @hide */
- public static boolean doTerminate() {
- ArrayList<ManagedEGLContext> active;
-
- if (Looper.getMainLooper() != Looper.myLooper()) {
- throw new IllegalStateException("Called on wrong thread");
- }
-
- synchronized (sActive) {
- // If there are no active managed contexts, we will not even
- // try to terminate.
- if (sActive.size() <= 0) {
- return false;
- }
-
- // Need to check how many EGL contexts are actually running,
- // to compare with how many we are managing.
- EGL10 egl = (EGL10) EGLContext.getEGL();
- EGLDisplay display = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
- if (display == EGL_NO_DISPLAY) {
- Log.w(TAG, "doTerminate failed: no display");
- return false;
- }
-
- if (EGLImpl.getInitCount(display) != sActive.size()) {
- Log.w(TAG, "doTerminate failed: EGL count is " + EGLImpl.getInitCount(display)
- + " but managed count is " + sActive.size());
- return false;
- }
-
- active = new ArrayList<ManagedEGLContext>(sActive);
- sActive.clear();
- }
-
- for (int i = 0; i < active.size(); i++) {
- active.get(i).execTerminate();
- }
-
- return true;
- }
-}