Merge "Remove View.executeHardwareAction"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ba31243..b68ce36 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -68,6 +68,7 @@
*/
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
+ private static final boolean LEGACY_DBG = true; // STOPSHIP
/**
* A change in network connectivity has occurred. A default connection has either
@@ -823,6 +824,14 @@
NetworkRequest request = null;
synchronized (sLegacyRequests) {
+ if (LEGACY_DBG) {
+ Log.d(TAG, "Looking for legacyRequest for netCap with hash: " + netCap + " (" +
+ netCap.hashCode() + ")");
+ Log.d(TAG, "sLegacyRequests has:");
+ for (NetworkCapabilities nc : sLegacyRequests.keySet()) {
+ Log.d(TAG, " " + nc + " (" + nc.hashCode() + ")");
+ }
+ }
LegacyRequest l = sLegacyRequests.get(netCap);
if (l != null) {
Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest);
@@ -837,7 +846,7 @@
request = requestNetworkForFeatureLocked(netCap);
}
if (request != null) {
- Log.d(TAG, "starting startUsingNeworkFeature for request " + request);
+ Log.d(TAG, "starting startUsingNetworkFeature for request " + request);
return PhoneConstants.APN_REQUEST_STARTED;
} else {
Log.d(TAG, " request Failed");
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 0fe764f..325917e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
/**
* The Media provider contains meta data for all available media on both internal
@@ -671,6 +672,7 @@
if (sThumbBuf == null) {
sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
}
+ Arrays.fill(sThumbBuf, (byte)0);
if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
if (bitmap == null) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c0e42a3..cfb4af2 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -387,17 +387,6 @@
abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
/**
- * Schedules the functor for execution in either kModeProcess or
- * kModeProcessNoContext, depending on whether or not there is an EGLContext.
- *
- * @param functor The native functor to invoke
- * @param waitForCompletion If true, this will not return until the functor
- * has invoked. If false, the functor may be invoked
- * asynchronously.
- */
- abstract void invokeFunctor(long functor, boolean waitForCompletion);
-
- /**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
* potentially lost the hardware renderer. The hardware renderer should be
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index a2ff0fb..5c67da9 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -80,13 +80,13 @@
private boolean mProfilingEnabled;
ThreadedRenderer(Context context, boolean translucent) {
- AtlasInitializer.sInstance.init(context);
-
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
mRootNode.setClipToBounds(false);
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
+ AtlasInitializer.sInstance.init(context, mNativeProxy);
+
// Setup timing
mChoreographer = Choreographer.getInstance();
nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
@@ -259,9 +259,8 @@
}
}
- @Override
- void invokeFunctor(long functor, boolean waitForCompletion) {
- nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
+ static void invokeFunctor(long functor, boolean waitForCompletion) {
+ nInvokeFunctor(functor, waitForCompletion);
}
@Override
@@ -342,7 +341,7 @@
private AtlasInitializer() {}
- synchronized void init(Context context) {
+ synchronized void init(Context context, long renderProxy) {
if (mInitialized) return;
IBinder binder = ServiceManager.getService("assetatlas");
if (binder == null) return;
@@ -356,7 +355,7 @@
if (map != null) {
// TODO Remove after fixing b/15425820
validateMap(context, map);
- nSetAtlas(buffer, map);
+ nSetAtlas(renderProxy, buffer, map);
mInitialized = true;
}
// If IAssetAtlas is not the same class as the IBinder
@@ -399,7 +398,7 @@
static native void setupShadersDiskCache(String cacheFile);
- private static native void nSetAtlas(GraphicBuffer buffer, long[] map);
+ private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
private static native long nCreateRootRenderNode();
private static native long nCreateProxy(boolean translucent, long rootRenderNode);
@@ -419,7 +418,7 @@
private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
private static native void nDestroyCanvasAndSurface(long nativeProxy);
- private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
+ private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
private static native long nCreateTextureLayer(long nativeProxy);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 785ba1a..829e089 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3894,7 +3894,7 @@
if (fadingEdge != FADING_EDGE_NONE) {
viewFlagValues |= fadingEdge;
viewFlagMasks |= FADING_EDGE_MASK;
- initializeFadingEdge(a);
+ initializeFadingEdgeInternal(a);
}
break;
case R.styleable.View_scrollbarStyle:
@@ -4108,7 +4108,7 @@
}
if (initializeScrollbars) {
- initializeScrollbars(a);
+ initializeScrollbarsInternal(a);
}
a.recycle();
@@ -4236,6 +4236,32 @@
* @param a the styled attributes set to initialize the fading edges from
*/
protected void initializeFadingEdge(TypedArray a) {
+ // This method probably shouldn't have been included in the SDK to begin with.
+ // It relies on 'a' having been initialized using an attribute filter array that is
+ // not publicly available to the SDK. The old method has been renamed
+ // to initializeFadingEdgeInternal and hidden for framework use only;
+ // this one initializes using defaults to make it safe to call for apps.
+
+ TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
+
+ initializeFadingEdgeInternal(arr);
+
+ arr.recycle();
+ }
+
+ /**
+ * <p>
+ * Initializes the fading edges from a given set of styled attributes. This
+ * method should be called by subclasses that need fading edges and when an
+ * instance of these subclasses is created programmatically rather than
+ * being inflated from XML. This method is automatically called when the XML
+ * is inflated.
+ * </p>
+ *
+ * @param a the styled attributes set to initialize the fading edges from
+ * @hide This is the real method; the public one is shimmed to be safe to call from apps.
+ */
+ protected void initializeFadingEdgeInternal(TypedArray a) {
initScrollCache();
mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
@@ -4350,6 +4376,31 @@
* @param a the styled attributes set to initialize the scrollbars from
*/
protected void initializeScrollbars(TypedArray a) {
+ // It's not safe to use this method from apps. The parameter 'a' must have been obtained
+ // using the View filter array which is not available to the SDK. As such, internal
+ // framework usage now uses initializeScrollbarsInternal and we grab a default
+ // TypedArray with the right filter instead here.
+ TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
+
+ initializeScrollbarsInternal(arr);
+
+ // We ignored the method parameter. Recycle the one we actually did use.
+ arr.recycle();
+ }
+
+ /**
+ * <p>
+ * Initializes the scrollbars from a given set of styled attributes. This
+ * method should be called by subclasses that need scrollbars and when an
+ * instance of these subclasses is created programmatically rather than
+ * being inflated from XML. This method is automatically called when the XML
+ * is inflated.
+ * </p>
+ *
+ * @param a the styled attributes set to initialize the scrollbars from
+ * @hide
+ */
+ protected void initializeScrollbarsInternal(TypedArray a) {
initScrollCache();
final ScrollabilityCache scrollabilityCache = mScrollCache;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f574042..329efcc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -661,11 +661,19 @@
}
}
+ /**
+ * Schedules the functor for execution in either kModeProcess or
+ * kModeProcessNoContext, depending on whether or not there is an EGLContext.
+ *
+ * @param functor The native functor to invoke
+ * @param waitForCompletion If true, this will not return until the functor
+ * has invoked. If false, the functor may be invoked
+ * asynchronously.
+ */
public boolean invokeFunctor(long functor, boolean waitForCompletion) {
- if (mAttachInfo.mHardwareRenderer == null) {
- return false;
- }
- mAttachInfo.mHardwareRenderer.invokeFunctor(functor, waitForCompletion);
+ ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
+ // TODO: Remove the return value. This is here for compatibility
+ // with current webview, which expects a boolean
return true;
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index a92bf59..bf5c84e 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -167,5 +167,5 @@
* Invalidate all visible windows. Then report back on the callback once all windows have
* redrawn.
*/
- public abstract void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout);
+ public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index d426edc..024600d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1154,6 +1154,12 @@
public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
/**
+ * Show the recents task list app.
+ * @hide
+ */
+ public void showRecentApps();
+
+ /**
* @return The current height of the input method window.
*/
public int getInputMethodWindowVisibleHeightLw();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 372228c..f2692da 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -785,7 +785,7 @@
setVerticalScrollBarEnabled(true);
TypedArray a = context.obtainStyledAttributes(R.styleable.View);
- initializeScrollbars(a);
+ initializeScrollbarsInternal(a);
a.recycle();
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 329e371..ca8fb30 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -20,15 +20,10 @@
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
-#include "android_view_GraphicBuffer.h"
-
#include <android_runtime/AndroidRuntime.h>
-#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <androidfw/ResourceTypes.h>
-#include <gui/GLConsumer.h>
-
#include <private/hwui/DrawGlInfo.h>
#include <cutils/properties.h>
@@ -43,9 +38,6 @@
#include <SkXfermode.h>
#include <DisplayListRenderer.h>
-#include <LayerRenderer.h>
-#include <OpenGLRenderer.h>
-#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
#include <CanvasProperty.h>
@@ -64,7 +56,7 @@
using namespace uirenderer;
/**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
+ * Note: DisplayListRenderer JNI layer is generated and compiled only on supported
* devices. This means all the logic must be compiled only when the
* preprocessor variable USE_OPENGL_RENDERER is defined.
*/
@@ -96,8 +88,8 @@
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- RENDERER_LOGD("Destroy OpenGLRenderer");
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ RENDERER_LOGD("Destroy DisplayListRenderer");
delete renderer;
}
@@ -107,26 +99,26 @@
static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint width, jint height) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setViewport(width, height);
}
static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean opaque) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->prepare(opaque);
}
static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
jboolean opaque) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->prepareDirty(left, top, right, bottom, opaque);
}
static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->finish();
}
@@ -154,7 +146,7 @@
static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong functorPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
android::uirenderer::Rect dirty;
return renderer->callDrawGLFunction(functor, dirty);
@@ -178,25 +170,25 @@
static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
jint flags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->save(flags);
}
static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->getSaveCount();
}
static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->restore();
}
static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint saveCount) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->restoreToCount(saveCount);
}
@@ -207,14 +199,14 @@
static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
}
static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong paintPtr, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
@@ -224,13 +216,13 @@
static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint alpha, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
}
static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint alpha, jint saveFlags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
alpha, saveFlags);
@@ -242,7 +234,7 @@
static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->quickRejectConservative(left, top, right, bottom);
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -250,7 +242,7 @@
static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->clipRect(left, top, right, bottom,
static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -259,7 +251,7 @@
static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const bool result = renderer->clipRect(float(left), float(top), float(right),
float(bottom),
static_cast<SkRegion::Op>(op));
@@ -268,7 +260,7 @@
static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong pathPtr, jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -276,7 +268,7 @@
static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong regionPtr, jint op) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
@@ -284,7 +276,7 @@
static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
jlong rendererPtr, jobject rect) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
env->CallVoidMethod(rect, gRectClassInfo.set,
@@ -299,45 +291,45 @@
static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat dx, jfloat dy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->translate(dx, dy);
}
static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat degrees) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->rotate(degrees);
}
static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat sx, jfloat sy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->scale(sx, sy);
}
static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat sx, jfloat sy) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->skew(sx, sy);
}
static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
}
static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderer->getMatrix(matrix);
}
static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong matrixPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderer->concatMatrix(*matrix);
}
@@ -353,7 +345,7 @@
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmap(bitmap, left, top, paint);
}
@@ -366,7 +358,7 @@
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint);
@@ -379,7 +371,7 @@
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmap(bitmap, *matrix, paint);
@@ -402,7 +394,7 @@
return;
}
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmapData(bitmap, left, top, paint);
@@ -423,7 +415,7 @@
jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
@@ -438,7 +430,7 @@
// This object allows the renderer to allocate a global JNI ref to the buffer object.
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
@@ -446,14 +438,14 @@
static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint color, jint mode) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->drawColor(color, static_cast<SkXfermode::Mode>(mode));
}
static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawRect(left, top, right, bottom, paint);
}
@@ -461,21 +453,21 @@
static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jfloat rx, jfloat ry, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
}
static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawCircle(x, y, radius, paint);
}
static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -486,7 +478,7 @@
static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawOval(left, top, right, bottom, paint);
}
@@ -494,14 +486,14 @@
static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
}
static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
if (paint->getStyle() != SkPaint::kFill_Style ||
@@ -531,7 +523,7 @@
static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jfloat* storage = env->GetFloatArrayElements(points, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPoints(storage + offset, count, paint);
@@ -540,7 +532,7 @@
static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawPath(path, paint);
@@ -548,7 +540,7 @@
static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jfloat* storage = env->GetFloatArrayElements(points, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
renderer->drawLines(storage + offset, count, paint);
@@ -561,13 +553,13 @@
static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint clearBits, jint setBits) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setupPaintFilter(clearBits, setBits);
}
static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->resetPaintFilter();
}
@@ -594,7 +586,7 @@
class RenderTextFunctor {
public:
- RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
+ RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
uirenderer::Rect& bounds)
: layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
@@ -612,7 +604,7 @@
}
private:
const Layout& layout;
- OpenGLRenderer* renderer;
+ DisplayListRenderer* renderer;
jfloat x;
jfloat y;
SkPaint* paint;
@@ -622,7 +614,7 @@
uirenderer::Rect& bounds;
};
-static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
+static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
jfloat x, jfloat y, SkPaint* paint) {
size_t nGlyphs = layout->nGlyphs();
float* pos = new float[nGlyphs * 2];
@@ -640,7 +632,7 @@
}
#endif
-static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
+static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
Layout layout;
@@ -672,7 +664,7 @@
#ifdef USE_MINIKIN
class RenderTextOnPathFunctor {
public:
- RenderTextOnPathFunctor(const Layout& layout, OpenGLRenderer* renderer, float hOffset,
+ RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
float vOffset, SkPaint* paint, SkPath* path)
: layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
paint(paint), path(path) {
@@ -688,7 +680,7 @@
}
private:
const Layout& layout;
- OpenGLRenderer* renderer;
+ DisplayListRenderer* renderer;
float hOffset;
float vOffset;
SkPaint* paint;
@@ -696,7 +688,7 @@
};
#endif
-static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
+static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
@@ -724,7 +716,7 @@
#endif
}
-static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
+static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
jint start, jint count, jint contextCount, jfloat x, jfloat y,
int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
@@ -757,7 +749,7 @@
static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
jlong rendererPtr, jcharArray text, jint index, jint count,
jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -769,7 +761,7 @@
static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
jlong rendererPtr, jstring text, jint start, jint end,
jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -782,7 +774,7 @@
jlong rendererPtr, jcharArray text, jint index, jint count,
jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
@@ -797,7 +789,7 @@
jlong rendererPtr, jstring text, jint start, jint end,
jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
@@ -812,7 +804,7 @@
jlong rendererPtr, jcharArray text, jint index, jint count,
jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
jchar* textArray = env->GetCharArrayElements(text, NULL);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -827,7 +819,7 @@
jlong rendererPtr, jstring text, jint start, jint end,
jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
jlong paintPtr, jlong typefacePtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
const jchar* textArray = env->GetStringChars(text, NULL);
jint count = end - start;
jint contextCount = contextEnd - contextStart;
@@ -857,7 +849,7 @@
static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
jobject clazz, jlong rendererPtr, jlong renderNodePtr,
jobject dirty, jint flags) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
android::uirenderer::Rect bounds;
status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
@@ -874,7 +866,7 @@
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Layer* layer = reinterpret_cast<Layer*>(layerPtr);
renderer->drawLayer(layer, x, y);
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 2b94b65..3e62d0b 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -76,26 +76,6 @@
jobject mRunnable;
};
-class SetAtlasTask : public RenderTask {
-public:
- SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
- : mBuffer(buffer)
- , mMap(map)
- , mMapSize(size) {
- }
-
- virtual void run() {
- CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
- mMap = 0;
- delete this;
- }
-
-private:
- sp<GraphicBuffer> mBuffer;
- int64_t* mMap;
- size_t mMapSize;
-};
-
class OnFinishedEvent {
public:
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -193,7 +173,7 @@
};
static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
- jobject graphicBuffer, jlongArray atlasMapArray) {
+ jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
jsize len = env->GetArrayLength(atlasMapArray);
if (len <= 0) {
@@ -203,8 +183,8 @@
int64_t* map = new int64_t[len];
env->GetLongArrayRegion(atlasMapArray, 0, len, map);
- SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
- RenderThread::getInstance().queue(task);
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->setTextureAtlas(buffer, map, len);
}
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
@@ -291,10 +271,9 @@
}
static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ jlong functorPtr, jboolean waitForCompletion) {
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- proxy->invokeFunctor(functor, waitForCompletion);
+ RenderProxy::invokeFunctor(functor, waitForCompletion);
}
static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
@@ -387,7 +366,7 @@
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
- { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
+ { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
{ "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
{ "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
@@ -400,7 +379,7 @@
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
- { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
+ { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 02e85fe..95d8a97 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -45,6 +45,7 @@
RenderBufferCache.cpp \
RenderNode.cpp \
RenderProperties.cpp \
+ RenderState.cpp \
ResourceCache.cpp \
ShadowTessellator.cpp \
SkiaShader.cpp \
@@ -61,6 +62,7 @@
LOCAL_SRC_FILES += \
renderthread/CanvasContext.cpp \
renderthread/DrawFrameTask.cpp \
+ renderthread/EglManager.cpp \
renderthread/RenderProxy.cpp \
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp \
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 937bf8d..a998594 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -500,7 +500,7 @@
void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
/* 1: op calculates local bounds */
DeferredDisplayState* const state = createState();
- if (op->getLocalBounds(renderer.getDrawModifiers(), state->mBounds)) {
+ if (op->getLocalBounds(state->mBounds)) {
if (state->mBounds.isEmpty()) {
// valid empty bounds, don't bother deferring
tryRecycleState(state);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 48489c2..8a015b21 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -38,7 +38,6 @@
class StateOp;
class DeferredDisplayState;
-class OpenGLRenderer;
class Batch;
class DrawBatch;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 5082271..c76bd5e 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -23,7 +23,6 @@
#include <utils/StrongPointer.h>
#include "Layer.h"
-#include "OpenGLRenderer.h"
#include "Rect.h"
#include "RenderNode.h"
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 811af39..5ed04a0 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -171,7 +171,7 @@
*
* returns true if bounds exist
*/
- virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+ virtual bool getLocalBounds(Rect& localBounds) {
return false;
}
@@ -253,7 +253,7 @@
// default empty constructor for bounds, to be overridden in child constructor body
DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
- bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+ bool getLocalBounds(Rect& localBounds) {
localBounds.set(mLocalBounds);
OpenGLRenderer::TextShadow textShadow;
if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
@@ -1029,7 +1029,7 @@
DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
: DrawBoundedOp(left, top, right, bottom, paint) {};
- bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+ bool getLocalBounds(Rect& localBounds) {
localBounds.set(mLocalBounds);
if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
localBounds.outset(strokeWidthOutset());
@@ -1399,7 +1399,7 @@
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Rect bounds;
- getLocalBounds(renderer.getDrawModifiers(), bounds);
+ getLocalBounds(bounds);
return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
mPositions, getPaint(renderer), mTotalAdvance, bounds);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index b6d3f4b..7789358 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -425,7 +425,7 @@
void DisplayListRenderer::addDrawOp(DrawOp* op) {
Rect localBounds;
- if (op->getLocalBounds(mDrawModifiers, localBounds)) {
+ if (op->getLocalBounds(localBounds)) {
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
localBounds.right, localBounds.bottom);
op->setQuickRejected(rejected);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 1de656e..8ca9af1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -23,7 +23,6 @@
#include <cutils/compiler.h>
#include "DisplayListLogBuffer.h"
-#include "OpenGLRenderer.h"
#include "RenderNode.h"
namespace android {
@@ -53,12 +52,12 @@
/**
* Records drawing commands in a display list for later playback into an OpenGLRenderer.
*/
-class DisplayListRenderer: public OpenGLRenderer {
+class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer {
public:
- ANDROID_API DisplayListRenderer();
+ DisplayListRenderer();
virtual ~DisplayListRenderer();
- ANDROID_API DisplayListData* finishRecording();
+ DisplayListData* finishRecording();
virtual bool isRecording() const { return true; }
@@ -81,7 +80,7 @@
const SkPaint* paint, int flags);
// Matrix
- virtual void translate(float dx, float dy, float dz);
+ virtual void translate(float dx, float dy, float dz = 0.0f);
virtual void rotate(float degrees);
virtual void scale(float sx, float sy);
virtual void skew(float sx, float sy);
@@ -98,6 +97,10 @@
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
+ bool isCurrentTransformSimple() {
+ return currentTransform()->isSimple();
+ }
+
// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
@@ -152,11 +155,6 @@
// TODO: rename for consistency
virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
-protected:
- // NOTE: must override these to avoid calling into super class, which calls GL. These may be
- // removed once DisplayListRenderer no longer inherits from OpenGLRenderer
- virtual void onViewportInitialized() {};
- virtual void onSnapshotRestored() {};
private:
void insertRestoreToCount();
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index b6414e5..73a4da5 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -20,6 +20,7 @@
#include "Caches.h"
#include "DeferredDisplayList.h"
+#include "RenderState.h"
#include "Layer.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
@@ -28,8 +29,10 @@
namespace android {
namespace uirenderer {
-Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight):
- caches(Caches::getInstance()), texture(caches) {
+Layer::Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
+ : caches(Caches::getInstance())
+ , renderState(renderState)
+ , texture(caches) {
mesh = NULL;
meshElementCount = 0;
cacheable = true;
@@ -72,7 +75,7 @@
void Layer::requireRenderer() {
if (!renderer) {
- renderer = new LayerRenderer(this);
+ renderer = new LayerRenderer(renderState, this);
renderer->initProperties();
}
}
@@ -123,18 +126,17 @@
void Layer::removeFbo(bool flush) {
if (stencil) {
- GLuint previousFbo;
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
- if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint previousFbo = renderState.getFramebuffer();
+ renderState.bindFramebuffer(fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
- if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ renderState.bindFramebuffer(previousFbo);
caches.renderBufferCache.put(stencil);
stencil = NULL;
}
if (fbo) {
- if (flush) LayerRenderer::flushLayer(this);
+ if (flush) LayerRenderer::flushLayer(renderState, this);
// If put fails the cache will delete the FBO
caches.fboCache.put(fbo);
fbo = 0;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 741f4c3..0bf05d0 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -43,6 +43,7 @@
// Forward declarations
class Caches;
+class RenderState;
class OpenGLRenderer;
class RenderNode;
class DeferredDisplayList;
@@ -53,7 +54,7 @@
*/
class Layer {
public:
- Layer(const uint32_t layerWidth, const uint32_t layerHeight);
+ Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
~Layer();
static uint32_t computeIdealWidth(uint32_t layerWidth);
@@ -306,6 +307,8 @@
Caches& caches;
+ RenderState& renderState;
+
/**
* Name of the FBO used to render the layer. If the name is 0
* this layer is not backed by an FBO, but a simple texture.
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 6be0146..13869aa 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -91,7 +91,7 @@
mCache.clear();
}
-Layer* LayerCache::get(const uint32_t width, const uint32_t height) {
+Layer* LayerCache::get(RenderState& renderState, const uint32_t width, const uint32_t height) {
Layer* layer = NULL;
LayerEntry entry(width, height);
@@ -108,7 +108,7 @@
} else {
LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
- layer = new Layer(entry.mWidth, entry.mHeight);
+ layer = new Layer(renderState, entry.mWidth, entry.mHeight);
layer->setBlend(true);
layer->setEmpty(true);
layer->setFbo(0);
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 221bfe0..1b0fc2c 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -24,6 +24,8 @@
namespace android {
namespace uirenderer {
+class RenderState;
+
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
@@ -55,7 +57,7 @@
* @param width The desired width of the layer
* @param height The desired height of the layer
*/
- Layer* get(const uint32_t width, const uint32_t height);
+ Layer* get(RenderState& renderState, const uint32_t width, const uint32_t height);
/**
* Adds the layer to the cache. The layer will not be added if there is
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index a5fd375..873baf5 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -20,6 +20,7 @@
#include <private/hwui/DrawGlInfo.h>
+#include "RenderState.h"
#include "LayerCache.h"
#include "LayerRenderer.h"
#include "Matrix.h"
@@ -33,7 +34,9 @@
// Rendering
///////////////////////////////////////////////////////////////////////////////
-LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) {
+LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer)
+ : OpenGLRenderer(renderState)
+ , mLayer(layer) {
}
LayerRenderer::~LayerRenderer() {
@@ -43,7 +46,7 @@
bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
- glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
+ renderState().bindFramebuffer(mLayer->getFbo());
const float width = mLayer->layer.getWidth();
const float height = mLayer->layer.getHeight();
@@ -180,7 +183,7 @@
// Layers management
///////////////////////////////////////////////////////////////////////////////
-Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
+Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) {
LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
Caches& caches = Caches::getInstance();
@@ -191,7 +194,7 @@
}
caches.activeTexture(0);
- Layer* layer = caches.layerCache.get(width, height);
+ Layer* layer = caches.layerCache.get(renderState, width, height);
if (!layer) {
ALOGW("Could not obtain a layer");
return NULL;
@@ -221,10 +224,9 @@
layer->setDirty(true);
layer->region.clear();
- GLuint previousFbo;
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+ GLuint previousFbo = renderState.getFramebuffer();
- glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+ renderState.bindFramebuffer(layer->getFbo());
layer->bindTexture();
// Initialize the texture if needed
@@ -235,7 +237,7 @@
// This should only happen if we run out of memory
if (glGetError() != GL_NO_ERROR) {
ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
- glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ renderState.bindFramebuffer(previousFbo);
caches.resourceCache.decrementRefcount(layer);
return NULL;
}
@@ -244,7 +246,7 @@
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->getTexture(), 0);
- glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ renderState.bindFramebuffer(previousFbo);
return layer;
}
@@ -265,10 +267,10 @@
return true;
}
-Layer* LayerRenderer::createTextureLayer() {
+Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
LAYER_RENDERER_LOGD("Creating new texture layer");
- Layer* layer = new Layer(0, 0);
+ Layer* layer = new Layer(renderState, 0, 0);
layer->setCacheable(false);
layer->setTextureLayer(true);
layer->setEmpty(true);
@@ -332,7 +334,7 @@
}
}
-void LayerRenderer::flushLayer(Layer* layer) {
+void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
if (!layer) return;
@@ -341,20 +343,23 @@
// If possible, discard any enqueud operations on deferred
// rendering architectures
if (Extensions::getInstance().hasDiscardFramebuffer()) {
- GLuint previousFbo;
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
- if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint previousFbo = renderState.getFramebuffer();
+ if (fbo != previousFbo) {
+ renderState.bindFramebuffer(fbo);
+ }
const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
- if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ if (fbo != previousFbo) {
+ renderState.bindFramebuffer(previousFbo);
+ }
}
}
#endif
}
-bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
+bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
Caches& caches = Caches::getInstance();
if (layer && bitmap->width() <= caches.maxTextureSize &&
bitmap->height() <= caches.maxTextureSize) {
@@ -369,7 +374,8 @@
GLuint texture;
GLuint previousFbo;
- GLuint previousViewport[4];
+ GLsizei previousViewportWidth;
+ GLsizei previousViewportHeight;
GLenum format;
GLenum type;
@@ -404,9 +410,9 @@
layer->setAlpha(255, SkXfermode::kSrc_Mode);
layer->setFbo(fbo);
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
- glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ previousFbo = renderState.getFramebuffer();
+ renderState.getViewport(&previousViewportWidth, &previousViewportHeight);
+ renderState.bindFramebuffer(fbo);
glGenTextures(1, &texture);
if ((error = glGetError()) != GL_NO_ERROR) goto error;
@@ -431,7 +437,7 @@
if ((error = glGetError()) != GL_NO_ERROR) goto error;
{
- LayerRenderer renderer(layer);
+ LayerRenderer renderer(renderState, layer);
renderer.setViewport(bitmap->width(), bitmap->height());
renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
bitmap->width(), bitmap->height(), !layer->isBlend());
@@ -471,13 +477,12 @@
}
#endif
- glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ renderState.bindFramebuffer(previousFbo);
layer->setAlpha(alpha, mode);
layer->setFbo(previousLayerFbo);
caches.deleteTexture(texture);
caches.fboCache.put(fbo);
- glViewport(previousViewport[0], previousViewport[1],
- previousViewport[2], previousViewport[3]);
+ renderState.setViewport(previousViewportWidth, previousViewportHeight);
return status;
}
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index e79e7b8..9202e49 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -27,6 +27,8 @@
namespace android {
namespace uirenderer {
+class RenderState;
+
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
@@ -44,7 +46,7 @@
class LayerRenderer: public OpenGLRenderer {
public:
- ANDROID_API LayerRenderer(Layer* layer);
+ LayerRenderer(RenderState& renderState, Layer* layer);
virtual ~LayerRenderer();
virtual void onViewportInitialized(int width, int height) { /* do nothing */ }
@@ -52,16 +54,16 @@
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
- ANDROID_API static Layer* createTextureLayer();
- ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height);
- ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
- ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ static Layer* createTextureLayer(RenderState& renderState);
+ static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height);
+ static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+ static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
- ANDROID_API static void destroyLayer(Layer* layer);
+ static void destroyLayer(Layer* layer);
ANDROID_API static void destroyLayerDeferred(Layer* layer);
- ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
+ static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
- static void flushLayer(Layer* layer);
+ static void flushLayer(RenderState& renderState, Layer* layer);
protected:
virtual void ensureStencilBuffer();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index afb65a6..ede89d7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -35,6 +35,7 @@
#include "DeferredDisplayList.h"
#include "DisplayListRenderer.h"
#include "Fence.h"
+#include "RenderState.h"
#include "PathTessellator.h"
#include "Properties.h"
#include "ShadowTessellator.h"
@@ -129,8 +130,10 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-OpenGLRenderer::OpenGLRenderer():
- mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
+OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
+ : mCaches(Caches::getInstance())
+ , mExtensions(Extensions::getInstance())
+ , mRenderState(renderState) {
// *set* draw modifiers to be 0
memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
mDrawModifiers.mOverrideLayerAlpha = 1.0f;
@@ -187,7 +190,7 @@
discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
- glViewport(0, 0, getWidth(), getHeight());
+ mRenderState.setViewport(getWidth(), getHeight());
// Functors break the tiling extension in pretty spectacular ways
// This ensures we don't use tiling when a functor is going to be
@@ -311,46 +314,9 @@
mFrameStarted = false;
}
-void OpenGLRenderer::interrupt() {
- if (mCaches.currentProgram) {
- if (mCaches.currentProgram->isInUse()) {
- mCaches.currentProgram->remove();
- mCaches.currentProgram = NULL;
- }
- }
- mCaches.resetActiveTexture();
- mCaches.unbindMeshBuffer();
- mCaches.unbindIndicesBuffer();
- mCaches.resetVertexPointers();
- mCaches.disableTexCoordsVertexArray();
- debugOverdraw(false, false);
-}
-
-void OpenGLRenderer::resume() {
- const Snapshot* snapshot = currentSnapshot();
- glViewport(0, 0, getViewportWidth(), getViewportHeight());
- glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
- debugOverdraw(true, false);
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
- mCaches.enableScissor();
- mCaches.resetScissor();
- dirtyClip();
-
- mCaches.activeTexture(0);
- mCaches.resetBoundTextures();
-
- mCaches.blend = true;
- glEnable(GL_BLEND);
- glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
- glBlendEquation(GL_FUNC_ADD);
-}
-
void OpenGLRenderer::resumeAfterLayer() {
- glViewport(0, 0, getViewportWidth(), getViewportHeight());
- glBindFramebuffer(GL_FRAMEBUFFER, currentSnapshot()->fbo);
+ mRenderState.setViewport(getViewportWidth(), getViewportHeight());
+ mRenderState.bindFramebuffer(currentSnapshot()->fbo);
debugOverdraw(true, false);
mCaches.resetScissor();
@@ -379,20 +345,19 @@
info.height = getViewportHeight();
currentTransform()->copyTo(&info.transform[0]);
- bool dirtyClip = mDirtyClip;
+ bool prevDirtyClip = mDirtyClip;
// setup GL state for functor
if (mDirtyClip) {
setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
}
- if (mCaches.enableScissor() || dirtyClip) {
+ if (mCaches.enableScissor() || prevDirtyClip) {
setScissorFromClip();
}
- interrupt();
- // call functor immediately after GL state setup
- (*functor)(DrawGlInfo::kModeDraw, &info);
+ mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
+ // Scissor may have been modified, reset dirty clip
+ dirtyClip();
- resume();
return DrawGlInfo::kStatusDrew;
}
@@ -413,17 +378,7 @@
}
void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
- if (mCaches.debugOverdraw && getTargetFbo() == 0) {
- if (clear) {
- mCaches.disableScissor();
- mCaches.stencil.clear();
- }
- if (enable) {
- mCaches.stencil.enableDebugWrite();
- } else {
- mCaches.stencil.disable();
- }
- }
+ mRenderState.debugOverdraw(enable, clear);
}
void OpenGLRenderer::renderOverdraw() {
@@ -528,7 +483,7 @@
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
mLayerUpdates.clear();
- glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+ mRenderState.bindFramebuffer(getTargetFbo());
}
endMark();
}
@@ -556,7 +511,7 @@
}
mLayerUpdates.clear();
- glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+ mRenderState.bindFramebuffer(getTargetFbo());
endMark();
}
@@ -620,7 +575,7 @@
bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
if (restoreViewport) {
- glViewport(0, 0, getViewportWidth(), getViewportHeight());
+ mRenderState.setViewport(getViewportWidth(), getViewportHeight());
}
if (restoreClip) {
@@ -791,7 +746,7 @@
}
mCaches.activeTexture(0);
- Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight());
+ Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
if (!layer) {
return false;
}
@@ -853,7 +808,7 @@
endTiling();
debugOverdraw(false, false);
// Bind texture to FBO
- glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+ mRenderState.bindFramebuffer(layer->getFbo());
layer->bindTexture();
// Initialize the texture if needed
@@ -876,7 +831,7 @@
dirtyClip();
// Change the ortho projection
- glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
+ mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
return true;
}
@@ -907,7 +862,7 @@
layer->removeFbo(false);
// Unbind current FBO and restore previous one
- glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo);
+ mRenderState.bindFramebuffer(restored.fbo);
debugOverdraw(true, false);
startTilingCurrentClip();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 066b267..4ff5780 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -57,6 +57,7 @@
namespace uirenderer {
class DeferredDisplayState;
+class RenderState;
class RenderNode;
class TextSetupFunctor;
class VertexBuffer;
@@ -119,33 +120,31 @@
*/
class OpenGLRenderer : public StatefulBaseRenderer {
public:
- ANDROID_API OpenGLRenderer();
+ OpenGLRenderer(RenderState& renderState);
virtual ~OpenGLRenderer();
- ANDROID_API void initProperties();
+ void initProperties();
virtual void onViewportInitialized();
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
- virtual void interrupt();
- virtual void resume();
- ANDROID_API void setCountOverdrawEnabled(bool enabled) {
+ void setCountOverdrawEnabled(bool enabled) {
mCountOverdraw = enabled;
}
- ANDROID_API float getOverdraw() {
+ float getOverdraw() {
return mCountOverdraw ? mOverdraw : 0.0f;
}
virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
- ANDROID_API void pushLayerUpdate(Layer* layer);
- ANDROID_API void cancelLayerUpdate(Layer* layer);
- ANDROID_API void clearLayerUpdates();
- ANDROID_API void flushLayerUpdates();
+ void pushLayerUpdate(Layer* layer);
+ void cancelLayerUpdate(Layer* layer);
+ void clearLayerUpdates();
+ void flushLayerUpdates();
- ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom,
+ virtual int saveLayer(float left, float top, float right, float bottom,
const SkPaint* paint, int flags) {
return saveLayer(left, top, right, bottom, paint, flags, NULL);
}
@@ -231,7 +230,7 @@
const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
- ANDROID_API bool isCurrentTransformSimple() {
+ bool isCurrentTransformSimple() {
return currentTransform()->isSimple();
}
@@ -474,6 +473,8 @@
return false;
}
+ inline RenderState& renderState() { return mRenderState; }
+
private:
/**
* Discards the content of the framebuffer if supported by the driver.
@@ -977,6 +978,7 @@
// Various caches
Caches& mCaches;
Extensions& mExtensions;
+ RenderState& mRenderState;
// List of rectangles to clear after saveLayer() is invoked
Vector<Rect*> mLayers;
@@ -1012,7 +1014,6 @@
bool mSkipOutlineClip;
- friend class DisplayListRenderer;
friend class Layer;
friend class TextSetupFunctor;
friend class DrawBitmapOp;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e8f2dd2..131384a 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -155,7 +155,7 @@
}
if (!mLayer) {
- mLayer = LayerRenderer::createRenderLayer(getWidth(), getHeight());
+ mLayer = LayerRenderer::createRenderLayer(info.renderState, getWidth(), getHeight());
applyLayerPropertiesToLayer(info);
damageSelf(info);
} else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) {
@@ -267,7 +267,7 @@
mNeedsDisplayListDataSync = false;
// Do a push pass on the old tree to handle freeing DisplayListData
// that are no longer used
- TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING);
+ TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info.renderState);
oldTreeInfo.damageAccumulator = info.damageAccumulator;
prepareSubTree(oldTreeInfo, mDisplayListData);
delete mDisplayListData;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 2fa6078..3980dad 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -55,7 +55,6 @@
namespace android {
namespace uirenderer {
-class DeferredDisplayList;
class DisplayListOp;
class DisplayListRenderer;
class OpenGLRenderer;
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
new file mode 100644
index 0000000..97f379d
--- /dev/null
+++ b/libs/hwui/RenderState.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+#include "RenderState.h"
+
+namespace android {
+namespace uirenderer {
+
+RenderState::RenderState()
+ : mCaches(NULL)
+ , mViewportWidth(0)
+ , mViewportHeight(0)
+ , mFramebuffer(0) {
+}
+
+RenderState::~RenderState() {
+}
+
+void RenderState::onGLContextCreated() {
+ // This is delayed because the first access of Caches makes GL calls
+ mCaches = &Caches::getInstance();
+ mCaches->init();
+}
+
+void RenderState::setViewport(GLsizei width, GLsizei height) {
+ mViewportWidth = width;
+ mViewportHeight = height;
+ glViewport(0, 0, mViewportWidth, mViewportHeight);
+}
+
+
+void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
+ *outWidth = mViewportWidth;
+ *outHeight = mViewportHeight;
+}
+
+void RenderState::bindFramebuffer(GLuint fbo) {
+ if (mFramebuffer != fbo) {
+ mFramebuffer = fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ }
+}
+
+void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
+ interruptForFunctorInvoke();
+ (*functor)(mode, info);
+ resumeFromFunctorInvoke();
+}
+
+void RenderState::interruptForFunctorInvoke() {
+ if (mCaches->currentProgram) {
+ if (mCaches->currentProgram->isInUse()) {
+ mCaches->currentProgram->remove();
+ mCaches->currentProgram = NULL;
+ }
+ }
+ mCaches->resetActiveTexture();
+ mCaches->unbindMeshBuffer();
+ mCaches->unbindIndicesBuffer();
+ mCaches->resetVertexPointers();
+ mCaches->disableTexCoordsVertexArray();
+ debugOverdraw(false, false);
+}
+
+void RenderState::resumeFromFunctorInvoke() {
+ glViewport(0, 0, mViewportWidth, mViewportHeight);
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ debugOverdraw(false, false);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
+ mCaches->enableScissor();
+ mCaches->resetScissor();
+
+ mCaches->activeTexture(0);
+ mCaches->resetBoundTextures();
+
+ mCaches->blend = true;
+ glEnable(GL_BLEND);
+ glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode);
+ glBlendEquation(GL_FUNC_ADD);
+}
+
+void RenderState::debugOverdraw(bool enable, bool clear) {
+ if (mCaches->debugOverdraw && mFramebuffer == 0) {
+ if (clear) {
+ mCaches->disableScissor();
+ mCaches->stencil.clear();
+ }
+ if (enable) {
+ mCaches->stencil.enableDebugWrite();
+ } else {
+ mCaches->stencil.disable();
+ }
+ }
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
new file mode 100644
index 0000000..f7116e2
--- /dev/null
+++ b/libs/hwui/RenderState.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+#ifndef RENDERSTATE_H
+#define RENDERSTATE_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
+#include "Caches.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+namespace renderthread {
+class RenderThread;
+}
+
+// TODO: Replace Cache's GL state tracking with this. For now it's more a thin
+// wrapper of Caches for users to migrate to.
+class RenderState {
+ PREVENT_COPY_AND_ASSIGN(RenderState);
+public:
+ void onGLContextCreated();
+
+ void setViewport(GLsizei width, GLsizei height);
+ void getViewport(GLsizei* outWidth, GLsizei* outHeight);
+
+ void bindFramebuffer(GLuint fbo);
+ GLint getFramebuffer() { return mFramebuffer; }
+
+ void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info);
+
+ void debugOverdraw(bool enable, bool clear);
+
+private:
+ friend class renderthread::RenderThread;
+
+ void interruptForFunctorInvoke();
+ void resumeFromFunctorInvoke();
+
+ RenderState();
+ ~RenderState();
+
+ Caches* mCaches;
+
+ GLsizei mViewportWidth;
+ GLsizei mViewportHeight;
+ GLuint mFramebuffer;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* RENDERSTATE_H */
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index d68b932..2ec99c9 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -129,21 +129,6 @@
*/
virtual void finish() = 0;
- /**
- * This method must be invoked before handing control over to a draw functor.
- * See callDrawGLFunction() for instance.
- *
- * This command must not be recorded inside display lists.
- */
- virtual void interrupt() = 0;
-
- /**
- * This method must be invoked after getting control back from a draw functor.
- *
- * This command must not be recorded inside display lists.
- */
- virtual void resume() = 0;
-
// ----------------------------------------------------------------------------
// Canvas state operations
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index f67e434..249e525 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -29,6 +29,7 @@
class BaseRenderNodeAnimator;
class AnimationListener;
class OpenGLRenderer;
+class RenderState;
class AnimationHook {
public:
@@ -67,14 +68,15 @@
// TODO: TRIM_MEMORY?
};
- explicit TreeInfo(TraversalMode mode)
+ explicit TreeInfo(TraversalMode mode, RenderState& renderState)
: mode(mode)
, frameTimeMs(0)
, animationHook(NULL)
, prepareTextures(mode == MODE_FULL)
, damageAccumulator(NullDamageAccumulator::instance())
- , renderer(0)
- , errorHandler(0)
+ , renderState(renderState)
+ , renderer(NULL)
+ , errorHandler(NULL)
{}
const TraversalMode mode;
@@ -85,6 +87,7 @@
bool prepareTextures;
// Must not be null
IDamageAccumulator* damageAccumulator;
+ RenderState& renderState;
// The renderer that will be drawing the next frame. Use this to push any
// layer updates or similar. May be NULL.
OpenGLRenderer* renderer;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index eab9810..fe4edf8 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -18,332 +18,31 @@
#include "CanvasContext.h"
-#include <cutils/properties.h>
#include <private/hwui/DrawGlInfo.h>
#include <strings.h>
+#include "EglManager.h"
#include "RenderThread.h"
#include "../Caches.h"
#include "../DeferredLayerUpdater.h"
+#include "../RenderState.h"
#include "../LayerRenderer.h"
#include "../OpenGLRenderer.h"
#include "../Stencil.h"
-#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
-#define GLES_VERSION 2
-
-// Android-specific addition that is used to show when frames began in systrace
-EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
-
namespace android {
namespace uirenderer {
namespace renderthread {
-#define ERROR_CASE(x) case x: return #x;
-static const char* egl_error_str(EGLint error) {
- switch (error) {
- ERROR_CASE(EGL_SUCCESS)
- ERROR_CASE(EGL_NOT_INITIALIZED)
- ERROR_CASE(EGL_BAD_ACCESS)
- ERROR_CASE(EGL_BAD_ALLOC)
- ERROR_CASE(EGL_BAD_ATTRIBUTE)
- ERROR_CASE(EGL_BAD_CONFIG)
- ERROR_CASE(EGL_BAD_CONTEXT)
- ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
- ERROR_CASE(EGL_BAD_DISPLAY)
- ERROR_CASE(EGL_BAD_MATCH)
- ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
- ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
- ERROR_CASE(EGL_BAD_PARAMETER)
- ERROR_CASE(EGL_BAD_SURFACE)
- ERROR_CASE(EGL_CONTEXT_LOST)
- default:
- return "Unknown error";
- }
-}
-static const char* egl_error_str() {
- return egl_error_str(eglGetError());
-}
-
-static bool load_dirty_regions_property() {
- char buf[PROPERTY_VALUE_MAX];
- int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
- return !strncasecmp("true", buf, len);
-}
-
-// This class contains the shared global EGL objects, such as EGLDisplay
-// and EGLConfig, which are re-used by CanvasContext
-class GlobalContext {
-public:
- static GlobalContext* get();
-
- // Returns true on success, false on failure
- void initialize();
-
- bool hasContext();
-
- void usePBufferSurface();
- EGLSurface createSurface(EGLNativeWindowType window);
- void destroySurface(EGLSurface surface);
-
- void destroy();
-
- bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
- // 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);
- void swapBuffers(EGLSurface surface);
-
- bool enableDirtyRegions(EGLSurface surface);
-
- void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
-
-private:
- GlobalContext();
- // GlobalContext is never destroyed, method is purposely not implemented
- ~GlobalContext();
-
- void loadConfig();
- void createContext();
- void initAtlas();
-
- static GlobalContext* sContext;
-
- EGLDisplay mEglDisplay;
- EGLConfig mEglConfig;
- EGLContext mEglContext;
- EGLSurface mPBufferSurface;
-
- const bool mRequestDirtyRegions;
- bool mCanSetDirtyRegions;
-
- EGLSurface mCurrentSurface;
-
- sp<GraphicBuffer> mAtlasBuffer;
- int64_t* mAtlasMap;
- size_t mAtlasMapSize;
-};
-
-GlobalContext* GlobalContext::sContext = 0;
-
-GlobalContext* GlobalContext::get() {
- if (!sContext) {
- sContext = new GlobalContext();
- }
- return sContext;
-}
-
-GlobalContext::GlobalContext()
- : mEglDisplay(EGL_NO_DISPLAY)
- , mEglConfig(0)
- , mEglContext(EGL_NO_CONTEXT)
- , mPBufferSurface(EGL_NO_SURFACE)
- , mRequestDirtyRegions(load_dirty_regions_property())
- , mCurrentSurface(EGL_NO_SURFACE)
- , mAtlasMap(NULL)
- , mAtlasMapSize(0) {
- mCanSetDirtyRegions = mRequestDirtyRegions;
- ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
-}
-
-void GlobalContext::initialize() {
- if (hasContext()) return;
-
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
-
- EGLint major, minor;
- LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
- "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
-
- ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
-
- loadConfig();
- createContext();
- usePBufferSurface();
- Caches::getInstance().init();
- initAtlas();
-}
-
-bool GlobalContext::hasContext() {
- return mEglDisplay != EGL_NO_DISPLAY;
-}
-
-void GlobalContext::loadConfig() {
- EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
- EGLint attribs[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 0,
- EGL_CONFIG_CAVEAT, EGL_NONE,
- EGL_STENCIL_SIZE, Stencil::getStencilSize(),
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
-
- EGLint num_configs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
- || num_configs != 1) {
- // Failed to get a valid config
- if (mCanSetDirtyRegions) {
- ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
- // Try again without dirty regions enabled
- mCanSetDirtyRegions = false;
- loadConfig();
- } else {
- LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
- }
- }
-}
-
-void GlobalContext::createContext() {
- EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
- mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
- LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
- "Failed to create context, error = %s", egl_error_str());
-}
-
-void GlobalContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
- int64_t* map, size_t mapSize) {
-
- // Already initialized
- if (mAtlasBuffer.get()) {
- ALOGW("Multiple calls to setTextureAtlas!");
- delete map;
- return;
- }
-
- mAtlasBuffer = buffer;
- mAtlasMap = map;
- mAtlasMapSize = mapSize;
-
- if (hasContext()) {
- usePBufferSurface();
- initAtlas();
- }
-}
-
-void GlobalContext::initAtlas() {
- if (mAtlasBuffer.get()) {
- Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
- }
-}
-
-void GlobalContext::usePBufferSurface() {
- LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "usePBufferSurface() called on uninitialized GlobalContext!");
-
- if (mPBufferSurface == EGL_NO_SURFACE) {
- EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
- mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
- }
- makeCurrent(mPBufferSurface);
-}
-
-EGLSurface GlobalContext::createSurface(EGLNativeWindowType window) {
- initialize();
- return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
-}
-
-void GlobalContext::destroySurface(EGLSurface surface) {
- if (isCurrent(surface)) {
- makeCurrent(EGL_NO_SURFACE);
- }
- if (!eglDestroySurface(mEglDisplay, surface)) {
- ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
- }
-}
-
-void GlobalContext::destroy() {
- if (mEglDisplay == EGL_NO_DISPLAY) return;
-
- usePBufferSurface();
- if (Caches::hasInstance()) {
- Caches::getInstance().terminate();
- }
-
- eglDestroyContext(mEglDisplay, mEglContext);
- eglDestroySurface(mEglDisplay, mPBufferSurface);
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(mEglDisplay);
- eglReleaseThread();
-
- mEglDisplay = EGL_NO_DISPLAY;
- mEglContext = EGL_NO_CONTEXT;
- mPBufferSurface = EGL_NO_SURFACE;
- mCurrentSurface = EGL_NO_SURFACE;
-}
-
-bool GlobalContext::makeCurrent(EGLSurface surface) {
- if (isCurrent(surface)) return false;
-
- if (surface == EGL_NO_SURFACE) {
- // If we are setting EGL_NO_SURFACE we don't care about any of the potential
- // return errors, which would only happen if mEglDisplay had already been
- // destroyed in which case the current context is already NO_CONTEXT
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
- LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
- (void*)surface, egl_error_str());
- }
- mCurrentSurface = surface;
- return true;
-}
-
-void GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
- LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Tried to beginFrame on EGL_NO_SURFACE!");
- makeCurrent(surface);
- if (width) {
- eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
- }
- if (height) {
- eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
- }
- eglBeginFrame(mEglDisplay, surface);
-}
-
-void GlobalContext::swapBuffers(EGLSurface surface) {
- eglSwapBuffers(mEglDisplay, surface);
- EGLint err = eglGetError();
- LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
- "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
-}
-
-bool GlobalContext::enableDirtyRegions(EGLSurface surface) {
- if (!mRequestDirtyRegions) return false;
-
- if (mCanSetDirtyRegions) {
- if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
- ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
- (void*) surface, egl_error_str());
- return false;
- }
- return true;
- }
- // Perhaps it is already enabled?
- EGLint value;
- if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
- ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
- (void*) surface, egl_error_str());
- return false;
- }
- return value == EGL_BUFFER_PRESERVED;
-}
-
-CanvasContext::CanvasContext(bool translucent, RenderNode* rootRenderNode)
- : mRenderThread(RenderThread::getInstance())
+CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode)
+ : mRenderThread(thread)
+ , mEglManager(thread.eglManager())
, mEglSurface(EGL_NO_SURFACE)
, mDirtyRegionsEnabled(false)
, mOpaque(!translucent)
- , mCanvas(0)
+ , mCanvas(NULL)
, mHaveNewSurface(false)
, mRootRenderNode(rootRenderNode) {
- mGlobalContext = GlobalContext::get();
}
CanvasContext::~CanvasContext() {
@@ -363,19 +62,16 @@
mNativeWindow = window;
if (mEglSurface != EGL_NO_SURFACE) {
- mGlobalContext->destroySurface(mEglSurface);
+ mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
}
if (window) {
- mEglSurface = mGlobalContext->createSurface(window);
- LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "Failed to create EGLSurface for window %p, eglErr = %s",
- (void*) window, egl_error_str());
+ mEglSurface = mEglManager.createSurface(window);
}
if (mEglSurface != EGL_NO_SURFACE) {
- mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
+ mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface);
mHaveNewSurface = true;
makeCurrent();
} else {
@@ -384,7 +80,7 @@
}
void CanvasContext::swapBuffers() {
- mGlobalContext->swapBuffers(mEglSurface);
+ mEglManager.swapBuffers(mEglSurface);
mHaveNewSurface = false;
}
@@ -397,7 +93,7 @@
bool CanvasContext::initialize(ANativeWindow* window) {
if (mCanvas) return false;
setSurface(window);
- mCanvas = new OpenGLRenderer();
+ mCanvas = new OpenGLRenderer(mRenderThread.renderState());
mCanvas->initProperties();
return true;
}
@@ -424,7 +120,7 @@
void CanvasContext::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
// In the meantime this matches the behavior of GLRenderer, so it is not a regression
- mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
+ mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface);
}
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) {
@@ -477,7 +173,7 @@
mDamageAccumulator.finish(&dirty);
EGLint width, height;
- mGlobalContext->beginFrame(mEglSurface, &width, &height);
+ mEglManager.beginFrame(mEglSurface, &width, &height);
if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
mCanvas->setViewport(width, height);
dirty.setEmpty();
@@ -521,7 +217,7 @@
profiler().startFrame();
- TreeInfo info(TreeInfo::MODE_RT_ONLY);
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
info.prepareTextures = false;
prepareTree(info);
@@ -530,32 +226,26 @@
}
}
-void CanvasContext::invokeFunctor(Functor* functor) {
+void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) {
ATRACE_CALL();
DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
- if (mGlobalContext->hasContext()) {
- requireGlContext();
+ if (thread.eglManager().hasEglContext()) {
+ thread.eglManager().requireGlContext();
mode = DrawGlInfo::kModeProcess;
}
- if (mCanvas) {
- mCanvas->interrupt();
- }
- (*functor)(mode, NULL);
- if (mCanvas) {
- mCanvas->resume();
- }
+ thread.renderState().invokeFunctor(functor, mode, NULL);
}
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
- TreeInfo info(TreeInfo::MODE_FULL);
+ TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
layer->apply(info);
- return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
+ return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
}
void CanvasContext::flushCaches(Caches::FlushMode flushMode) {
- if (mGlobalContext->hasContext()) {
+ if (mEglManager.hasEglContext()) {
requireGlContext();
Caches::getInstance().flush(flushMode);
}
@@ -568,25 +258,25 @@
Layer* CanvasContext::createRenderLayer(int width, int height) {
requireSurface();
- return LayerRenderer::createRenderLayer(width, height);
+ return LayerRenderer::createRenderLayer(mRenderThread.renderState(), width, height);
}
Layer* CanvasContext::createTextureLayer() {
requireSurface();
- return LayerRenderer::createTextureLayer();
+ return LayerRenderer::createTextureLayer(mRenderThread.renderState());
}
void CanvasContext::requireGlContext() {
if (mEglSurface != EGL_NO_SURFACE) {
makeCurrent();
} else {
- mGlobalContext->usePBufferSurface();
+ mEglManager.usePBufferSurface();
}
}
-void CanvasContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
- int64_t* map, size_t mapSize) {
- GlobalContext::get()->setTextureAtlas(buffer, map, mapSize);
+void CanvasContext::setTextureAtlas(RenderThread& thread,
+ const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize) {
+ thread.eglManager().setTextureAtlas(buffer, map, mapSize);
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d926b38..d2ce1a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -41,13 +41,13 @@
namespace renderthread {
-class GlobalContext;
+class EglManager;
// This per-renderer class manages the bridge between the global EGL context
// and the render surface.
class CanvasContext : public IFrameCallback {
public:
- CanvasContext(bool translucent, RenderNode* rootRenderNode);
+ CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode);
virtual ~CanvasContext();
bool initialize(ANativeWindow* window);
@@ -68,15 +68,15 @@
void flushCaches(Caches::FlushMode flushMode);
- void invokeFunctor(Functor* functor);
+ static void invokeFunctor(RenderThread& thread, Functor* functor);
void runWithGlContext(RenderTask* task);
Layer* createRenderLayer(int width, int height);
Layer* createTextureLayer();
- ANDROID_API static void setTextureAtlas(const sp<GraphicBuffer>& buffer,
- int64_t* map, size_t mapSize);
+ ANDROID_API static void setTextureAtlas(RenderThread& thread,
+ const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
void notifyFramePending();
@@ -91,8 +91,8 @@
void requireGlContext();
- GlobalContext* mGlobalContext;
RenderThread& mRenderThread;
+ EglManager& mEglManager;
sp<ANativeWindow> mNativeWindow;
EGLSurface mEglSurface;
bool mDirtyRegionsEnabled;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 48abbf2..fddffd5 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -98,7 +98,7 @@
bool canUnblockUiThread;
bool canDrawThisFrame;
{
- TreeInfo info(TreeInfo::MODE_FULL);
+ TreeInfo info(TreeInfo::MODE_FULL, mRenderThread->renderState());
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
}
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
new file mode 100644
index 0000000..05ca34d
--- /dev/null
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define LOG_TAG "EglContext"
+
+#include "EglManager.h"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "../RenderState.h"
+#include "RenderThread.h"
+
+#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
+#define GLES_VERSION 2
+
+// Android-specific addition that is used to show when frames began in systrace
+EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+#define ERROR_CASE(x) case x: return #x;
+static const char* egl_error_str(EGLint error) {
+ switch (error) {
+ ERROR_CASE(EGL_SUCCESS)
+ ERROR_CASE(EGL_NOT_INITIALIZED)
+ ERROR_CASE(EGL_BAD_ACCESS)
+ ERROR_CASE(EGL_BAD_ALLOC)
+ ERROR_CASE(EGL_BAD_ATTRIBUTE)
+ ERROR_CASE(EGL_BAD_CONFIG)
+ ERROR_CASE(EGL_BAD_CONTEXT)
+ ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
+ ERROR_CASE(EGL_BAD_DISPLAY)
+ ERROR_CASE(EGL_BAD_MATCH)
+ ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
+ ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
+ ERROR_CASE(EGL_BAD_PARAMETER)
+ ERROR_CASE(EGL_BAD_SURFACE)
+ ERROR_CASE(EGL_CONTEXT_LOST)
+ default:
+ return "Unknown error";
+ }
+}
+static const char* egl_error_str() {
+ return egl_error_str(eglGetError());
+}
+
+static bool load_dirty_regions_property() {
+ char buf[PROPERTY_VALUE_MAX];
+ int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
+ return !strncasecmp("true", buf, len);
+}
+
+EglManager::EglManager(RenderThread& thread)
+ : mRenderThread(thread)
+ , mEglDisplay(EGL_NO_DISPLAY)
+ , mEglConfig(0)
+ , mEglContext(EGL_NO_CONTEXT)
+ , mPBufferSurface(EGL_NO_SURFACE)
+ , mRequestDirtyRegions(load_dirty_regions_property())
+ , mCurrentSurface(EGL_NO_SURFACE)
+ , mAtlasMap(NULL)
+ , mAtlasMapSize(0) {
+ mCanSetDirtyRegions = mRequestDirtyRegions;
+ ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
+}
+
+void EglManager::initialize() {
+ if (hasEglContext()) return;
+
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
+ "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
+
+ EGLint major, minor;
+ LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
+ "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
+
+ ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
+
+ loadConfig();
+ createContext();
+ usePBufferSurface();
+ mRenderThread.renderState().onGLContextCreated();
+ initAtlas();
+}
+
+bool EglManager::hasEglContext() {
+ return mEglDisplay != EGL_NO_DISPLAY;
+}
+
+void EglManager::requireGlContext() {
+ LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context");
+
+ // We don't care *WHAT* surface is active, just that one is active to give
+ // us access to the GL context
+ if (mCurrentSurface == EGL_NO_SURFACE) {
+ usePBufferSurface();
+ }
+}
+
+void EglManager::loadConfig() {
+ EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ EGLint attribs[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_STENCIL_SIZE, Stencil::getStencilSize(),
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
+ EGL_NONE
+ };
+
+ EGLint num_configs = 1;
+ if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
+ || num_configs != 1) {
+ // Failed to get a valid config
+ if (mCanSetDirtyRegions) {
+ ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
+ // Try again without dirty regions enabled
+ mCanSetDirtyRegions = false;
+ loadConfig();
+ } else {
+ LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
+ }
+ }
+}
+
+void EglManager::createContext() {
+ EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
+ mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
+ LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
+ "Failed to create context, error = %s", egl_error_str());
+}
+
+void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer,
+ int64_t* map, size_t mapSize) {
+
+ // Already initialized
+ if (mAtlasBuffer.get()) {
+ ALOGW("Multiple calls to setTextureAtlas!");
+ delete map;
+ return;
+ }
+
+ mAtlasBuffer = buffer;
+ mAtlasMap = map;
+ mAtlasMapSize = mapSize;
+
+ if (hasEglContext()) {
+ usePBufferSurface();
+ initAtlas();
+ }
+}
+
+void EglManager::initAtlas() {
+ if (mAtlasBuffer.get()) {
+ Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
+ }
+}
+
+void EglManager::usePBufferSurface() {
+ LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
+ "usePBufferSurface() called on uninitialized GlobalContext!");
+
+ if (mPBufferSurface == EGL_NO_SURFACE) {
+ EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+ mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
+ }
+ makeCurrent(mPBufferSurface);
+}
+
+EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
+ initialize();
+ EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
+ LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
+ "Failed to create EGLSurface for window %p, eglErr = %s",
+ (void*) window, egl_error_str());
+ return surface;
+}
+
+void EglManager::destroySurface(EGLSurface surface) {
+ if (isCurrent(surface)) {
+ makeCurrent(EGL_NO_SURFACE);
+ }
+ if (!eglDestroySurface(mEglDisplay, surface)) {
+ ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
+ }
+}
+
+void EglManager::destroy() {
+ if (mEglDisplay == EGL_NO_DISPLAY) return;
+
+ usePBufferSurface();
+ if (Caches::hasInstance()) {
+ Caches::getInstance().terminate();
+ }
+
+ eglDestroyContext(mEglDisplay, mEglContext);
+ eglDestroySurface(mEglDisplay, mPBufferSurface);
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(mEglDisplay);
+ eglReleaseThread();
+
+ mEglDisplay = EGL_NO_DISPLAY;
+ mEglContext = EGL_NO_CONTEXT;
+ mPBufferSurface = EGL_NO_SURFACE;
+ mCurrentSurface = EGL_NO_SURFACE;
+}
+
+bool EglManager::makeCurrent(EGLSurface surface) {
+ if (isCurrent(surface)) return false;
+
+ if (surface == EGL_NO_SURFACE) {
+ // If we are setting EGL_NO_SURFACE we don't care about any of the potential
+ // return errors, which would only happen if mEglDisplay had already been
+ // destroyed in which case the current context is already NO_CONTEXT
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
+ LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
+ (void*)surface, egl_error_str());
+ }
+ mCurrentSurface = surface;
+ return true;
+}
+
+void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
+ LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
+ "Tried to beginFrame on EGL_NO_SURFACE!");
+ makeCurrent(surface);
+ if (width) {
+ eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
+ }
+ if (height) {
+ eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
+ }
+ eglBeginFrame(mEglDisplay, surface);
+}
+
+void EglManager::swapBuffers(EGLSurface surface) {
+ eglSwapBuffers(mEglDisplay, surface);
+ EGLint err = eglGetError();
+ LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
+ "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
+}
+
+bool EglManager::enableDirtyRegions(EGLSurface surface) {
+ if (!mRequestDirtyRegions) return false;
+
+ if (mCanSetDirtyRegions) {
+ if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
+ ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
+ (void*) surface, egl_error_str());
+ return false;
+ }
+ return true;
+ }
+ // Perhaps it is already enabled?
+ EGLint value;
+ if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
+ ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
+ (void*) surface, egl_error_str());
+ return false;
+ }
+ return value == EGL_BUFFER_PRESERVED;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
new file mode 100644
index 0000000..a844cfc
--- /dev/null
+++ b/libs/hwui/renderthread/EglManager.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+#ifndef EGLMANAGER_H
+#define EGLMANAGER_H
+
+#include <cutils/compiler.h>
+#include <EGL/egl.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class RenderThread;
+
+// This class contains the shared global EGL objects, such as EGLDisplay
+// and EGLConfig, which are re-used by CanvasContext
+class EglManager {
+public:
+ // Returns true on success, false on failure
+ void initialize();
+
+ bool hasEglContext();
+ void requireGlContext();
+
+ void usePBufferSurface();
+ EGLSurface createSurface(EGLNativeWindowType window);
+ void destroySurface(EGLSurface surface);
+
+ void destroy();
+
+ bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
+ // 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);
+ void swapBuffers(EGLSurface surface);
+
+ bool enableDirtyRegions(EGLSurface surface);
+
+ void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
+
+private:
+ friend class RenderThread;
+
+ EglManager(RenderThread& thread);
+ // EglContext is never destroyed, method is purposely not implemented
+ ~EglManager();
+
+ void loadConfig();
+ void createContext();
+ void initAtlas();
+
+ RenderThread& mRenderThread;
+
+ EGLDisplay mEglDisplay;
+ EGLConfig mEglConfig;
+ EGLContext mEglContext;
+ EGLSurface mPBufferSurface;
+
+ const bool mRequestDirtyRegions;
+ bool mCanSetDirtyRegions;
+
+ EGLSurface mCurrentSurface;
+
+ sp<GraphicBuffer> mAtlasBuffer;
+ int64_t* mAtlasMap;
+ size_t mAtlasMapSize;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* EGLMANAGER_H */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4988f19..f90a26a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,8 +52,8 @@
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
-CREATE_BRIDGE2(createContext, bool translucent, RenderNode* rootRenderNode) {
- return new CanvasContext(args->translucent, args->rootRenderNode);
+CREATE_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) {
+ return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode);
}
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode)
@@ -62,6 +62,7 @@
SETUP_TASK(createContext);
args->translucent = translucent;
args->rootRenderNode = rootRenderNode;
+ args->thread = &mRenderThread;
mContext = (CanvasContext*) postAndWait(task);
mDrawFrameTask.setContext(&mRenderThread, mContext);
}
@@ -199,20 +200,29 @@
postAndWait(task);
}
-CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
- args->context->invokeFunctor(args->functor);
+CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
+ CanvasContext::invokeFunctor(*args->thread, args->functor);
return NULL;
}
void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
ATRACE_CALL();
+ RenderThread& thread = RenderThread::getInstance();
SETUP_TASK(invokeFunctor);
- args->context = mContext;
+ args->thread = &thread;
args->functor = functor;
if (waitForCompletion) {
- postAndWait(task);
+ // waitForCompletion = true is expected to be fairly rare and only
+ // happen in destruction. Thus it should be fine to temporarily
+ // create a Mutex
+ Mutex mutex;
+ Condition condition;
+ SignalingRenderTask syncTask(task, &mutex, &condition);
+ AutoMutex _lock(mutex);
+ thread.queue(&syncTask);
+ condition.wait(mutex);
} else {
- post(task);
+ thread.queue(task);
}
}
@@ -233,7 +243,7 @@
return NULL;
}
-static void enqueueDestroyLayer(Layer* layer) {
+void RenderProxy::enqueueDestroyLayer(Layer* layer) {
SETUP_TASK(destroyLayer);
args->layer = layer;
RenderThread::getInstance().queue(task);
@@ -242,7 +252,7 @@
CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
Layer* layer = args->context->createRenderLayer(args->width, args->height);
if (!layer) return 0;
- return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
+ return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
}
DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
@@ -258,7 +268,7 @@
CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
Layer* layer = args->context->createTextureLayer();
if (!layer) return 0;
- return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
+ return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
}
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
@@ -336,6 +346,22 @@
postAndWait(task);
}
+CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
+ CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
+ args->buffer->decStrong(0);
+ return NULL;
+}
+
+void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
+ SETUP_TASK(setTextureAtlas);
+ args->thread = &mRenderThread;
+ args->buffer = buffer.get();
+ args->buffer->incStrong(0);
+ args->map = map;
+ args->size = size;
+ post(task);
+}
+
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index a95f8f0..df0aff0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -73,10 +73,11 @@
float density);
ANDROID_API void destroyCanvasAndSurface();
- ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
+ ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task);
+ static void enqueueDestroyLayer(Layer* layer);
ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -90,6 +91,8 @@
ANDROID_API void dumpProfileInfo(int fd);
+ ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4a4e254..03e98d5 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -21,7 +21,9 @@
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
+#include "../RenderState.h"
#include "CanvasContext.h"
+#include "EglManager.h"
#include "RenderProxy.h"
namespace android {
@@ -138,13 +140,16 @@
, mDisplayEventReceiver(0)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
- , mFrameCallbackTask(0) {
+ , mFrameCallbackTask(0)
+ , mRenderState(NULL)
+ , mEglManager(NULL) {
mFrameCallbackTask = new DispatchFrameCallbacks(this);
mLooper = new Looper(false);
run("RenderThread");
}
RenderThread::~RenderThread() {
+ LOG_ALWAYS_FATAL("Can't destroy the render thread");
}
void RenderThread::initializeDisplayEventReceiver() {
@@ -159,6 +164,12 @@
Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
}
+void RenderThread::initThreadLocals() {
+ initializeDisplayEventReceiver();
+ mEglManager = new EglManager(*this);
+ mRenderState = new RenderState();
+}
+
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
@@ -233,7 +244,7 @@
}
bool RenderThread::threadLoop() {
- initializeDisplayEventReceiver();
+ initThreadLocals();
int timeoutMillis = -1;
for (;;) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 4412584..0b91e9d 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -31,12 +31,18 @@
#include "TimeLord.h"
namespace android {
+
class DisplayEventReceiver;
namespace uirenderer {
+
+class RenderState;
+
namespace renderthread {
class DispatchFrameCallbacks;
+class EglManager;
+class RenderProxy;
class TaskQueue {
public:
@@ -62,7 +68,7 @@
~IFrameCallback() {}
};
-class ANDROID_API RenderThread : public Thread, public Singleton<RenderThread> {
+class ANDROID_API RenderThread : public Thread, protected Singleton<RenderThread> {
public:
// RenderThread takes complete ownership of tasks that are queued
// and will delete them after they are run
@@ -79,6 +85,8 @@
void pushBackFrameCallback(IFrameCallback* callback);
TimeLord& timeLord() { return mTimeLord; }
+ RenderState& renderState() { return *mRenderState; }
+ EglManager& eglManager() { return *mEglManager; }
protected:
virtual bool threadLoop();
@@ -86,10 +94,12 @@
private:
friend class Singleton<RenderThread>;
friend class DispatchFrameCallbacks;
+ friend class RenderProxy;
RenderThread();
virtual ~RenderThread();
+ void initThreadLocals();
void initializeDisplayEventReceiver();
static int displayEventReceiverCallback(int fd, int events, void* data);
void drainDisplayEventQueue(bool skipCallbacks = false);
@@ -119,6 +129,8 @@
DispatchFrameCallbacks* mFrameCallbackTask;
TimeLord mTimeLord;
+ RenderState* mRenderState;
+ EglManager* mEglManager;
};
} /* namespace renderthread */
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 23c3652..664308c 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -248,7 +248,8 @@
long magic = mBuffer.getLong();
int length = mBuffer.getInt();
- if (size >= 1 + 8 + 4 + length && data.length >= length) {
+ if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
+ data.length >= length) {
mBuffer.get(data, 0, length);
return data;
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 637061d04..2d8d681 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,7 +42,6 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.media.AudioManager;
-import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -51,7 +50,6 @@
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
-import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -105,7 +103,6 @@
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.telephony.ITelephony;
import com.android.internal.widget.PointerLocationView;
import com.android.server.LocalServices;
@@ -270,10 +267,10 @@
// The following are only accessed on the mHandler thread.
boolean mKeyguardDrawComplete;
boolean mWindowManagerDrawComplete;
- ArrayList<ScreenOnListener> mScreenOnListeners = new ArrayList<ScreenOnListener>();
- final IRemoteCallback mWindowManagerDrawCallback = new IRemoteCallback.Stub() {
+ ScreenOnListener mScreenOnListener;
+ final Runnable mWindowManagerDrawCallback = new Runnable() {
@Override
- public void sendResult(Bundle data) {
+ public void run() {
if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
}
@@ -521,6 +518,7 @@
private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
private static final int MSG_WAKING_UP = 8;
+ private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
private class PolicyHandler extends Handler {
@Override
@@ -538,6 +536,9 @@
case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
break;
+ case MSG_DISPATCH_SHOW_RECENTS:
+ showRecentApps(false);
+ break;
case MSG_KEYGUARD_DRAWN_COMPLETE:
if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
mKeyguardDrawComplete = true;
@@ -2589,6 +2590,12 @@
}
}
+ @Override
+ public void showRecentApps() {
+ mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
+ mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS);
+ }
+
private void showRecentApps(boolean triggeredFromAltTab) {
mPreloadedRecentApps = false; // preloading no longer needs to be canceled
try {
@@ -4543,7 +4550,7 @@
// Called on the mHandler thread.
private void handleWakingUp(final ScreenOnListener screenOnListener) {
if (screenOnListener != null) {
- mScreenOnListeners.add(screenOnListener);
+ mScreenOnListener = screenOnListener;
}
synchronized (mLock) {
@@ -4575,8 +4582,11 @@
return;
}
+ ScreenOnListener screenOnListener;
synchronized (mLock) {
mScreenOnFully = true;
+ screenOnListener = mScreenOnListener;
+ mScreenOnListener = null;
}
try {
@@ -4584,8 +4594,8 @@
} catch (RemoteException unhandled) {
}
- for (int i = mScreenOnListeners.size() - 1; i >=0; --i) {
- mScreenOnListeners.remove(i).onScreenOn();
+ if (screenOnListener != null) {
+ screenOnListener.onScreenOn();
}
setKeyguardDrawn();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 57b56b4..570ac3d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7230,7 +7230,7 @@
// Compose the recent task info
ActivityManager.RecentTaskInfo rti
= new ActivityManager.RecentTaskInfo();
- rti.id = tr.mActivities.isEmpty() ? -1 : tr.taskId;
+ rti.id = tr.getTopActivity() == null ? -1 : tr.taskId;
rti.persistentId = tr.taskId;
rti.baseIntent = new Intent(tr.getBaseIntent());
rti.origActivity = tr.origActivity;
@@ -7297,6 +7297,12 @@
continue;
}
}
+ if (tr.intent != null &&
+ (tr.intent.getFlags() & Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS)
+ != 0 && tr.getTopActivity() == null) {
+ // Don't include auto remove tasks that are finished or finishing.
+ continue;
+ }
ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
if (!detailed) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index fe2a473..aa777e1 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -30,6 +30,10 @@
import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+
import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP;
import static com.android.server.am.ActivityStackSupervisor.DEBUG_CONTAINERS;
@@ -1095,7 +1099,8 @@
for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
- final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
+ final TaskRecord task = tasks.get(taskNdx);
+ final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
final ActivityRecord r = activities.get(activityNdx);
@@ -1106,7 +1111,7 @@
// - Full Screen Activity OR
// - On top of Home and our stack is NOT home
if (!r.finishing && r.visible && (r.fullscreen ||
- (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) {
+ (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
return false;
}
}
@@ -1234,7 +1239,7 @@
// At this point, nothing else needs to be shown
if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
behindFullscreen = true;
- } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) {
+ } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
behindFullscreen = true;
}
@@ -1388,6 +1393,7 @@
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
+ final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
@@ -1395,7 +1401,10 @@
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
- return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
+ final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
+ HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
+ return isOnHomeDisplay() &&
+ mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}
next.delayedResume = false;
@@ -1414,24 +1423,29 @@
}
final TaskRecord nextTask = next.task;
- final TaskRecord prevTask = prev != null ? prev.task : null;
if (prevTask != null && prevTask.stack == this &&
- prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
+ prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
- // This task is going away but it was supposed to return to the home task.
+ // This task is going away but it was supposed to return to the home stack.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
- mTaskHistory.get(taskNdx).mOnTopOfHome = true;
+ mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else {
if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
"resumeTopActivityLocked: Launching home next");
// Only resume home if on home display
- return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
+ final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
+ HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
+ return isOnHomeDisplay() &&
+ mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}
}
+ if (prev != null && prev.isRecentsActivity()) {
+ nextTask.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
+ }
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
@@ -1800,10 +1814,11 @@
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHome = lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) {
- task.mOnTopOfHome = fromHome;
+ task.setTaskToReturnTo(fromHome ?
+ lastStack.topTask().taskType : APPLICATION_ACTIVITY_TYPE);
}
} else {
- task.mOnTopOfHome = false;
+ task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
mTaskHistory.remove(task);
@@ -2350,8 +2365,8 @@
ActivityRecord next = topRunningActivityLocked(null);
if (next != r) {
final TaskRecord task = r.task;
- if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
- mStackSupervisor.moveHomeToTop();
+ if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
}
}
ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
@@ -2843,8 +2858,9 @@
if (task != null && task.removeActivity(r)) {
if (DEBUG_STACK) Slog.i(TAG,
"removeActivityFromHistoryLocked: last activity removed from " + this);
- if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
- mStackSupervisor.moveHomeToTop();
+ if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
+ task.isOverHomeStack()) {
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
}
removeTask(task);
}
@@ -3160,12 +3176,13 @@
}
}
- void moveHomeTaskToTop() {
+ void moveHomeStackTaskToTop(int homeStackTaskType) {
final int top = mTaskHistory.size() - 1;
for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
- if (task.isHomeTask()) {
- if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task);
+ if (task.taskType == homeStackTaskType) {
+ if (DEBUG_TASKS || DEBUG_STACK)
+ Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task);
mTaskHistory.remove(taskNdx);
mTaskHistory.add(top, task);
updateTaskMovement(task, true);
@@ -3277,12 +3294,12 @@
int numTasks = mTaskHistory.size();
for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
- if (task.mOnTopOfHome) {
+ if (task.isOverHomeStack()) {
break;
}
if (taskNdx == 1) {
// Set the last task before tr to go to home.
- task.mOnTopOfHome = true;
+ task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
@@ -3303,9 +3320,10 @@
}
final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
- if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) {
- tr.mOnTopOfHome = false;
- return mStackSupervisor.resumeHomeActivity(null);
+ if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) {
+ final int taskToReturnTo = tr.getTaskToReturnTo();
+ tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+ return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
}
mStackSupervisor.resumeTopActivitiesLocked();
@@ -3746,8 +3764,11 @@
final int taskNdx = mTaskHistory.indexOf(task);
final int topTaskNdx = mTaskHistory.size() - 1;
- if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
- mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
+ if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
+ final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
+ if (!nextTask.isOverHomeStack()) {
+ nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+ }
}
mTaskHistory.remove(task);
updateTaskMovement(task, true);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4be208b..73266bc 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -31,6 +31,9 @@
import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.am.ActivityManagerService.TAG;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import android.app.Activity;
import android.app.ActivityManager;
@@ -382,17 +385,27 @@
}
}
- void moveHomeToTop() {
+ void moveHomeStackTaskToTop(int homeStackTaskType) {
+ if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
+ mWindowManager.showRecentApps();
+ return;
+ }
moveHomeStack(true);
- mHomeStack.moveHomeTaskToTop();
+ mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
}
- boolean resumeHomeActivity(ActivityRecord prev) {
- moveHomeToTop();
- if (prev != null) {
- prev.task.mOnTopOfHome = false;
+ boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) {
+ if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
+ mWindowManager.showRecentApps();
+ return false;
}
+ moveHomeStackTaskToTop(homeStackTaskType);
+ if (prev != null) {
+ prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+ }
+
ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
+ // if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) {
if (r != null && r.isHomeActivity()) {
mService.setFocusedActivityLocked(r);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
@@ -747,7 +760,7 @@
}
void startHomeActivity(Intent intent, ActivityInfo aInfo) {
- moveHomeToTop();
+ moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0,
null, false, null, null);
}
@@ -1697,7 +1710,7 @@
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity.
- intentActivity.task.mOnTopOfHome = true;
+ intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
options = null;
}
@@ -1893,7 +1906,7 @@
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity, so before starting
// their own activity we will bring home to the front.
- r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay();
+ r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
} else if (sourceRecord != null) {
@@ -2244,7 +2257,7 @@
if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
// Caller wants the home activity moved with it. To accomplish this,
// we'll just indicate that this task returns to the home task.
- task.mOnTopOfHome = true;
+ task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
task.stack.moveTaskToFrontLocked(task, null, options);
if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
@@ -2356,7 +2369,7 @@
}
mWindowManager.addTask(taskId, stackId, false);
}
- resumeHomeActivity(null);
+ resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
}
void moveTaskToStack(int taskId, int stackId, boolean toTop) {
@@ -2618,7 +2631,7 @@
}
} else {
// Stack was moved to another display while user was swapped out.
- resumeHomeActivity(null);
+ resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
}
return homeInFront;
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index e9afc36..a301c4b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -17,6 +17,9 @@
package com.android.server.am;
import static com.android.server.am.ActivityManagerService.TAG;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
import android.app.Activity;
@@ -53,7 +56,6 @@
private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
private static final String ATTR_USERID = "user_id";
private static final String ATTR_TASKTYPE = "task_type";
- private static final String ATTR_ONTOPOFHOME = "on_top_of_home";
private static final String ATTR_LASTDESCRIPTION = "last_description";
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -107,9 +109,10 @@
/** True if persistable, has changed, and has not yet been persisted */
boolean needsPersisting = false;
- /** Launch the home activity when leaving this task. Will be false for tasks that are not on
- * Display.DEFAULT_DISPLAY. */
- boolean mOnTopOfHome = false;
+ /** Indication of what to run next when task exits. Use ActivityRecord types.
+ * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
+ * task stack. */
+ private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
/** If original intent did not allow relinquishing task identity, save that information */
boolean mNeverRelinquishIdentity = true;
@@ -132,9 +135,9 @@
TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
String _affinity, ComponentName _realActivity, ComponentName _origActivity,
- boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome,
- int _userId, String _lastDescription, ArrayList<ActivityRecord> activities,
- long lastTimeMoved, boolean neverRelinquishIdentity) {
+ boolean _rootWasReset, boolean _askedCompatMode, int _taskType, int _userId,
+ String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved,
+ boolean neverRelinquishIdentity) {
mService = service;
taskId = _taskId;
intent = _intent;
@@ -147,7 +150,7 @@
rootWasReset = _rootWasReset;
askedCompatMode = _askedCompatMode;
taskType = _taskType;
- mOnTopOfHome = _onTopOfHome;
+ mTaskToReturnTo = HOME_ACTIVITY_TYPE;
userId = _userId;
lastDescription = _lastDescription;
mActivities = activities;
@@ -224,6 +227,14 @@
}
}
+ void setTaskToReturnTo(int taskToReturnTo) {
+ mTaskToReturnTo = taskToReturnTo;
+ }
+
+ int getTaskToReturnTo() {
+ return mTaskToReturnTo;
+ }
+
void disposeThumbnail() {
super.disposeThumbnail();
for (int i=mActivities.size()-1; i>=0; i--) {
@@ -514,11 +525,15 @@
}
boolean isHomeTask() {
- return taskType == ActivityRecord.HOME_ACTIVITY_TYPE;
+ return taskType == HOME_ACTIVITY_TYPE;
}
boolean isApplicationTask() {
- return taskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+ return taskType == APPLICATION_ACTIVITY_TYPE;
+ }
+
+ boolean isOverHomeStack() {
+ return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
}
public TaskAccessInfo getTaskAccessInfoLocked() {
@@ -688,7 +703,6 @@
out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
out.attribute(null, ATTR_USERID, String.valueOf(userId));
out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
- out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome));
out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
if (lastDescription != null) {
@@ -737,7 +751,6 @@
boolean rootHasReset = false;
boolean askedCompatMode = false;
int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
- boolean onTopOfHome = true;
int userId = 0;
String lastDescription = null;
long lastTimeOnTop = 0;
@@ -766,8 +779,6 @@
userId = Integer.valueOf(attrValue);
} else if (ATTR_TASKTYPE.equals(attrName)) {
taskType = Integer.valueOf(attrValue);
- } else if (ATTR_ONTOPOFHOME.equals(attrName)) {
- onTopOfHome = Boolean.valueOf(attrValue);
} else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
lastDescription = attrValue;
} else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -807,8 +818,8 @@
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
affinityIntent, affinity, realActivity, origActivity, rootHasReset,
- askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities,
- lastTimeOnTop, neverRelinquishIdentity);
+ askedCompatMode, taskType, userId, lastDescription, activities, lastTimeOnTop,
+ neverRelinquishIdentity);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
@@ -827,7 +838,7 @@
pw.print(" userId="); pw.print(userId);
pw.print(" taskType="); pw.print(taskType);
pw.print(" numFullscreen="); pw.print(numFullscreen);
- pw.print(" mOnTopOfHome="); pw.println(mOnTopOfHome);
+ pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
}
if (affinity != null) {
pw.print(prefix); pw.print("affinity="); pw.println(affinity);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d04d668..1d857231 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -411,7 +411,7 @@
/**
* And the callback to make when they've all been drawn.
*/
- IRemoteCallback mWaitingForDrawnCallback;
+ Runnable mWaitingForDrawnCallback;
/**
* Windows that have called relayout() while we were running animations,
@@ -7561,7 +7561,7 @@
}
case WAITING_FOR_DRAWN_TIMEOUT: {
- IRemoteCallback callback = null;
+ Runnable callback = null;
synchronized (mWindowMap) {
Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
mWaitingForDrawn.clear();
@@ -7569,10 +7569,7 @@
mWaitingForDrawnCallback = null;
}
if (callback != null) {
- try {
- callback.sendResult(null);
- } catch (RemoteException e) {
- }
+ callback.run();
}
break;
}
@@ -7626,16 +7623,13 @@
}
break;
case ALL_WINDOWS_DRAWN: {
- IRemoteCallback callback;
+ Runnable callback;
synchronized (mWindowMap) {
callback = mWaitingForDrawnCallback;
mWaitingForDrawnCallback = null;
}
if (callback != null) {
- try {
- callback.sendResult(null);
- } catch (RemoteException e) {
- }
+ callback.run();
}
}
case NEW_ANIMATOR_SCALE: {
@@ -9555,8 +9549,9 @@
}
}
- if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
- && !mInnerFields.mUpdateRotation) {
+ if (mWaitingForDrawnCallback != null ||
+ (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
+ !mInnerFields.mUpdateRotation)) {
checkDrawnWindowsLocked();
}
@@ -10321,6 +10316,10 @@
mPolicy.lockNow(options);
}
+ public void showRecentApps() {
+ mPolicy.showRecentApps();
+ }
+
@Override
public boolean isSafeModeEnabled() {
return mSafeMode;
@@ -11141,24 +11140,31 @@
}
}
- public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) {
+ public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
synchronized (mWindowMap) {
mWaitingForDrawnCallback = callback;
final WindowList windows = getDefaultWindowListLocked();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
- if (win.mHasSurface) {
- win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+ if (win.mHasSurface && win.isWinVisibleLw()) {
+ if (!win.mIsWallpaper) {
+ // Don't force wallpaper to redraw.
+ win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+ }
// Force add to mResizingWindows.
win.mLastContentInsets.set(-1, -1, -1, -1);
mWaitingForDrawn.add(win);
}
}
requestTraversalLocked();
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
- mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
}
- checkDrawnWindowsLocked();
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ if (mWaitingForDrawn.isEmpty()) {
+ callback.run();
+ } else {
+ mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+ checkDrawnWindowsLocked();
+ }
}
}
}