Merge "No-fail invokeFunctor"
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -38,7 +38,6 @@ class SaveLayerOp;
|
||||
class StateOp;
|
||||
|
||||
class DeferredDisplayState;
|
||||
class OpenGLRenderer;
|
||||
|
||||
class Batch;
|
||||
class DrawBatch;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include "Layer.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "Rect.h"
|
||||
#include "RenderNode.h"
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
112
libs/hwui/RenderState.cpp
Normal 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
70
libs/hwui/RenderState.h
Normal 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 */
|
||||
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
288
libs/hwui/renderthread/EglManager.cpp
Normal file
288
libs/hwui/renderthread/EglManager.cpp
Normal 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 */
|
||||
88
libs/hwui/renderthread/EglManager.h
Normal file
88
libs/hwui/renderthread/EglManager.h
Normal 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 */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 (;;) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user