Merge "No-fail invokeFunctor"

This commit is contained in:
John Reck
2014-06-23 22:32:51 +00:00
committed by Android (Google) Code Review
35 changed files with 867 additions and 645 deletions

View File

@@ -386,17 +386,6 @@ public abstract class HardwareRenderer {
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

View File

@@ -80,13 +80,13 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
}
}
@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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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);

View File

@@ -661,11 +661,19 @@ public final class ViewRootImpl implements ViewParent,
}
}
/**
* 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;
}

View File

@@ -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 @@ namespace android {
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 struct {
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_destroyRenderer(JNIEnv* env, jobject clazz
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 void android_view_GLES20Canvas_setProperty(JNIEnv* env,
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_getMaxTextureHeight(JNIEnv* env, jobject c
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 void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
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_saveLayerClip(JNIEnv* env, jobject clazz,
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 jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl
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_quickReject(JNIEnv* env, jobject clazz
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_clipRectF(JNIEnv* env, jobject clazz,
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_clipRect(JNIEnv* env, jobject clazz,
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_clipPath(JNIEnv* env, jobject clazz,
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_clipRegion(JNIEnv* env, jobject clazz,
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 jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject cla
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 @@ static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
// 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 @@ static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
// 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 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject claz
// 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 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
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 @@ static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
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 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
// 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_drawPatch(JNIEnv* env, jobject clazz,
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_drawRect(JNIEnv* env, jobject clazz,
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_drawCircleProps(JNIEnv* env, jobject clazz
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_drawOval(JNIEnv* env, jobject clazz,
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_drawRegionAsRects(JNIEnv* env, jobject cla
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_drawPoints(JNIEnv* env, jobject clazz,
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_drawPath(JNIEnv* env, jobject clazz,
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_drawLines(JNIEnv* env, jobject clazz,
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 @@ static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
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 @@ public:
}
private:
const Layout& layout;
OpenGLRenderer* renderer;
DisplayListRenderer* renderer;
jfloat x;
jfloat y;
SkPaint* paint;
@@ -622,7 +614,7 @@ private:
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 @@ static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
}
#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 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
#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 @@ public:
}
private:
const Layout& layout;
OpenGLRenderer* renderer;
DisplayListRenderer* renderer;
float hOffset;
float vOffset;
SkPaint* paint;
@@ -696,7 +688,7 @@ private:
};
#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 @@ static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int co
#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 renderTextRun(OpenGLRenderer* renderer, const jchar* text,
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_drawTextArray(JNIEnv* env, jobject clazz,
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 @@ static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject c
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 @@ static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
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 @@ static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject claz
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 @@ static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
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 jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jo
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 jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
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);
}

View File

@@ -76,26 +76,6 @@ private:
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 @@ private:
};
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 @@ static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
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_destroyCanvasAndSurface(JNIEnv* env, j
}
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 @@ const char* const kClassPathName = "android/view/ThreadedRenderer";
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 @@ static JNINativeMethod gMethods[] = {
{ "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 },

View File

@@ -45,6 +45,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
RenderBufferCache.cpp \
RenderNode.cpp \
RenderProperties.cpp \
RenderState.cpp \
ResourceCache.cpp \
ShadowTessellator.cpp \
SkiaShader.cpp \
@@ -61,6 +62,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SRC_FILES += \
renderthread/CanvasContext.cpp \
renderthread/DrawFrameTask.cpp \
renderthread/EglManager.cpp \
renderthread/RenderProxy.cpp \
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp \

View File

@@ -500,7 +500,7 @@ void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* o
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);

View File

@@ -38,7 +38,6 @@ class SaveLayerOp;
class StateOp;
class DeferredDisplayState;
class OpenGLRenderer;
class Batch;
class DrawBatch;

View File

@@ -23,7 +23,6 @@
#include <utils/StrongPointer.h>
#include "Layer.h"
#include "OpenGLRenderer.h"
#include "Rect.h"
#include "RenderNode.h"

View File

@@ -171,7 +171,7 @@ public:
*
* returns true if bounds exist
*/
virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
virtual bool getLocalBounds(Rect& localBounds) {
return false;
}
@@ -253,7 +253,7 @@ public:
// 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 @@ public:
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 @@ public:
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);
}

View File

@@ -425,7 +425,7 @@ void DisplayListRenderer::addStateOp(StateOp* op) {
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);

View File

@@ -23,7 +23,6 @@
#include <cutils/compiler.h>
#include "DisplayListLogBuffer.h"
#include "OpenGLRenderer.h"
#include "RenderNode.h"
namespace android {
@@ -53,12 +52,12 @@ class StateOp;
/**
* 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 @@ public:
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 @@ public:
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
bool isCurrentTransformSimple() {
return currentTransform()->isSimple();
}
// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
@@ -152,11 +155,6 @@ public:
// 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();

View File

@@ -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 @@ uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
void Layer::requireRenderer() {
if (!renderer) {
renderer = new LayerRenderer(this);
renderer = new LayerRenderer(renderState, this);
renderer->initProperties();
}
}
@@ -123,18 +126,17 @@ bool Layer::resize(const uint32_t width, const uint32_t height) {
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;

View File

@@ -43,6 +43,7 @@ namespace uirenderer {
// Forward declarations
class Caches;
class RenderState;
class OpenGLRenderer;
class RenderNode;
class DeferredDisplayList;
@@ -53,7 +54,7 @@ class DeferStateStruct;
*/
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 @@ private:
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.

View File

@@ -91,7 +91,7 @@ void LayerCache::clear() {
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 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) {
} 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);

View File

@@ -24,6 +24,8 @@
namespace android {
namespace uirenderer {
class RenderState;
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
@@ -55,7 +57,7 @@ public:
* @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

View File

@@ -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 @@ namespace uirenderer {
// Rendering
///////////////////////////////////////////////////////////////////////////////
LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) {
LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer)
: OpenGLRenderer(renderState)
, mLayer(layer) {
}
LayerRenderer::~LayerRenderer() {
@@ -43,7 +46,7 @@ status_t LayerRenderer::prepareDirty(float left, float top, float right, float b
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 @@ void LayerRenderer::generateMesh() {
// 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 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
}
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* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
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 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
// 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 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
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 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
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::destroyLayerDeferred(Layer* layer) {
}
}
void LayerRenderer::flushLayer(Layer* layer) {
void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
if (!layer) return;
@@ -341,20 +343,23 @@ void LayerRenderer::flushLayer(Layer* layer) {
// 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 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
GLuint texture;
GLuint previousFbo;
GLuint previousViewport[4];
GLsizei previousViewportWidth;
GLsizei previousViewportHeight;
GLenum format;
GLenum type;
@@ -404,9 +410,9 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
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 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
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 @@ error:
}
#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;
}

View File

@@ -27,6 +27,8 @@
namespace android {
namespace uirenderer {
class RenderState;
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
@@ -44,7 +46,7 @@ namespace uirenderer {
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 @@ public:
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();

View File

@@ -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 @@ static inline T min(T a, T b) {
// 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 @@ status_t OpenGLRenderer::startFrame() {
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 @@ void OpenGLRenderer::finish() {
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 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
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::endMark() const {
}
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 @@ void OpenGLRenderer::updateLayers() {
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
mLayerUpdates.clear();
glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
mRenderState.bindFramebuffer(getTargetFbo());
}
endMark();
}
@@ -556,7 +511,7 @@ void OpenGLRenderer::flushLayers() {
}
mLayerUpdates.clear();
glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
mRenderState.bindFramebuffer(getTargetFbo());
endMark();
}
@@ -620,7 +575,7 @@ void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot&
bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
if (restoreViewport) {
glViewport(0, 0, getViewportWidth(), getViewportHeight());
mRenderState.setViewport(getViewportWidth(), getViewportHeight());
}
if (restoreClip) {
@@ -791,7 +746,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
}
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 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
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 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
dirtyClip();
// Change the ortho projection
glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
return true;
}
@@ -907,7 +862,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
layer->removeFbo(false);
// Unbind current FBO and restore previous one
glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo);
mRenderState.bindFramebuffer(restored.fbo);
debugOverdraw(true, false);
startTilingCurrentClip();

View File

@@ -57,6 +57,7 @@ namespace android {
namespace uirenderer {
class DeferredDisplayState;
class RenderState;
class RenderNode;
class TextSetupFunctor;
class VertexBuffer;
@@ -119,33 +120,31 @@ enum ModelViewMode {
*/
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 @@ public:
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 @@ protected:
return false;
}
inline RenderState& renderState() { return mRenderState; }
private:
/**
* Discards the content of the framebuffer if supported by the driver.
@@ -977,6 +978,7 @@ private:
// Various caches
Caches& mCaches;
Extensions& mExtensions;
RenderState& mRenderState;
// List of rectangles to clear after saveLayer() is invoked
Vector<Rect*> mLayers;
@@ -1012,7 +1014,6 @@ private:
bool mSkipOutlineClip;
friend class DisplayListRenderer;
friend class Layer;
friend class TextSetupFunctor;
friend class DrawBitmapOp;

View File

@@ -155,7 +155,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
}
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 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
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;

View File

@@ -55,7 +55,6 @@ class SkRegion;
namespace android {
namespace uirenderer {
class DeferredDisplayList;
class DisplayListOp;
class DisplayListRenderer;
class OpenGLRenderer;

112
libs/hwui/RenderState.cpp Normal file
View File

@@ -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 */

70
libs/hwui/RenderState.h Normal file
View File

@@ -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 */

View File

@@ -129,21 +129,6 @@ public:
*/
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
// ----------------------------------------------------------------------------

View File

@@ -29,6 +29,7 @@ namespace uirenderer {
class BaseRenderNodeAnimator;
class AnimationListener;
class OpenGLRenderer;
class RenderState;
class AnimationHook {
public:
@@ -67,14 +68,15 @@ public:
// 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 @@ public:
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;

View File

@@ -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 @@ void CanvasContext::setSurface(ANativeWindow* window) {
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::setSurface(ANativeWindow* window) {
}
void CanvasContext::swapBuffers() {
mGlobalContext->swapBuffers(mEglSurface);
mEglManager.swapBuffers(mEglSurface);
mHaveNewSurface = false;
}
@@ -397,7 +93,7 @@ void CanvasContext::requireSurface() {
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::setOpaque(bool opaque) {
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 @@ void CanvasContext::draw() {
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 @@ void CanvasContext::doFrame() {
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::doFrame() {
}
}
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 @@ void CanvasContext::runWithGlContext(RenderTask* task) {
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 */

View File

@@ -41,13 +41,13 @@ class Layer;
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 @@ public:
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 @@ private:
void requireGlContext();
GlobalContext* mGlobalContext;
RenderThread& mRenderThread;
EglManager& mEglManager;
sp<ANativeWindow> mNativeWindow;
EGLSurface mEglSurface;
bool mDirtyRegionsEnabled;

View File

@@ -98,7 +98,7 @@ void DrawFrameTask::run() {
bool canUnblockUiThread;
bool canDrawThisFrame;
{
TreeInfo info(TreeInfo::MODE_FULL);
TreeInfo info(TreeInfo::MODE_FULL, mRenderThread->renderState());
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -52,8 +52,8 @@ namespace renderthread {
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 @@ RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode)
SETUP_TASK(createContext);
args->translucent = translucent;
args->rootRenderNode = rootRenderNode;
args->thread = &mRenderThread;
mContext = (CanvasContext*) postAndWait(task);
mDrawFrameTask.setContext(&mRenderThread, mContext);
}
@@ -199,20 +200,29 @@ void RenderProxy::destroyCanvasAndSurface() {
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 @@ CREATE_BRIDGE1(destroyLayer, Layer* layer) {
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 @@ static void enqueueDestroyLayer(Layer* layer) {
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 @@ DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height)
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 @@ void RenderProxy::dumpProfileInfo(int fd) {
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);
}

View File

@@ -73,10 +73,11 @@ public:
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 @@ public:
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;

View File

@@ -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 @@ RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
, 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 @@ void RenderThread::initializeDisplayEventReceiver() {
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 @@ void RenderThread::requestVsync() {
}
bool RenderThread::threadLoop() {
initializeDisplayEventReceiver();
initThreadLocals();
int timeoutMillis = -1;
for (;;) {

View File

@@ -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 @@ protected:
~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 @@ public:
void pushBackFrameCallback(IFrameCallback* callback);
TimeLord& timeLord() { return mTimeLord; }
RenderState& renderState() { return *mRenderState; }
EglManager& eglManager() { return *mEglManager; }
protected:
virtual bool threadLoop();
@@ -86,10 +94,12 @@ protected:
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 @@ private:
DispatchFrameCallbacks* mFrameCallbackTask;
TimeLord mTimeLord;
RenderState* mRenderState;
EglManager* mEglManager;
};
} /* namespace renderthread */