Skip to content

Commit b6a8007

Browse files
ChrisCraikAndroid (Google) Code Review
authored andcommitted
Merge "Allow fine-grained control over functors execution"
2 parents 191310b + 8f3b8e3 commit b6a8007

File tree

8 files changed

+148
-30
lines changed

8 files changed

+148
-30
lines changed

core/java/android/os/Message.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package android.os;
1818

19-
import android.os.Bundle;
20-
import android.os.Parcel;
21-
import android.os.Parcelable;
2219
import android.util.TimeUtils;
2320

2421
/**
@@ -368,13 +365,13 @@ public void sendToTarget() {
368365
*
369366
* Asynchronous messages represent interrupts or events that do not require global ordering
370367
* with represent to synchronous messages. Asynchronous messages are not subject to
371-
* the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}.
368+
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
372369
*
373370
* @return True if the message is asynchronous.
374371
*
375372
* @see #setAsynchronous(boolean)
376-
* @see MessageQueue#acquireSyncBarrier()
377-
* @see MessageQueue#releaseSyncBarrier()
373+
* @see MessageQueue#enqueueSyncBarrier(long)
374+
* @see MessageQueue#removeSyncBarrier(int)
378375
*
379376
* @hide
380377
*/
@@ -387,13 +384,13 @@ public boolean isAsynchronous() {
387384
*
388385
* Asynchronous messages represent interrupts or events that do not require global ordering
389386
* with represent to synchronous messages. Asynchronous messages are not subject to
390-
* the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}.
387+
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
391388
*
392389
* @param async True if the message is asynchronous.
393390
*
394391
* @see #isAsynchronous()
395-
* @see MessageQueue#acquireSyncBarrier()
396-
* @see MessageQueue#releaseSyncBarrier()
392+
* @see MessageQueue#enqueueSyncBarrier(long)
393+
* @see MessageQueue#removeSyncBarrier(int)
397394
*
398395
* @hide
399396
*/
@@ -506,7 +503,7 @@ public void writeToParcel(Parcel dest, int flags) {
506503
Messenger.writeMessengerOrNullToParcel(replyTo, dest);
507504
}
508505

509-
private final void readFromParcel(Parcel source) {
506+
private void readFromParcel(Parcel source) {
510507
what = source.readInt();
511508
arg1 = source.readInt();
512509
arg2 = source.readInt();

core/java/android/view/GLES20Canvas.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ public int callDrawGLFunction(int drawGLFunction) {
259259

260260
private static native int nCallDrawGLFunction(int renderer, int drawGLFunction);
261261

262+
@Override
263+
public int invokeFunctors(Rect dirty) {
264+
return nInvokeFunctors(mRenderer, dirty);
265+
}
266+
267+
private static native int nInvokeFunctors(int renderer, Rect dirty);
268+
262269
///////////////////////////////////////////////////////////////////////////
263270
// Memory
264271
///////////////////////////////////////////////////////////////////////////

core/java/android/view/HardwareCanvas.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,16 @@ public int callDrawGLFunction(int drawGLFunction) {
9898
// Noop - this is done in the display list recorder subclass
9999
return DisplayList.STATUS_DONE;
100100
}
101+
102+
/**
103+
* Invoke all the functors who requested to be invoked during the previous frame.
104+
*
105+
* @param dirty The region to redraw when the functors return {@link DisplayList#STATUS_DRAW}
106+
*
107+
* @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or
108+
* {@link DisplayList#STATUS_INVOKE}
109+
*/
110+
public int invokeFunctors(Rect dirty) {
111+
return DisplayList.STATUS_DONE;
112+
}
101113
}

core/java/android/view/HardwareRenderer.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,9 @@ static abstract class GlRenderer extends HardwareRenderer {
502502
static final int SURFACE_STATE_ERROR = 0;
503503
static final int SURFACE_STATE_SUCCESS = 1;
504504
static final int SURFACE_STATE_UPDATED = 2;
505-
505+
506+
static final int FUNCTOR_PROCESS_DELAY = 2;
507+
506508
static EGL10 sEgl;
507509
static EGLDisplay sEglDisplay;
508510
static EGLConfig sEglConfig;
@@ -549,7 +551,9 @@ static abstract class GlRenderer extends HardwareRenderer {
549551
private boolean mDestroyed;
550552

551553
private final Rect mRedrawClip = new Rect();
554+
552555
private final int[] mSurfaceSize = new int[2];
556+
private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable();
553557

554558
GlRenderer(int glVersion, boolean translucent) {
555559
mGlVersion = glVersion;
@@ -957,6 +961,24 @@ void onPreDraw(Rect dirty) {
957961
void onPostDraw() {
958962
}
959963

964+
class FunctorsRunnable implements Runnable {
965+
View.AttachInfo attachInfo;
966+
967+
@Override
968+
public void run() {
969+
final HardwareRenderer renderer = attachInfo.mHardwareRenderer;
970+
if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) {
971+
return;
972+
}
973+
974+
final int surfaceState = checkCurrent();
975+
if (surfaceState != SURFACE_STATE_ERROR) {
976+
int status = mCanvas.invokeFunctors(mRedrawClip);
977+
handleFunctorStatus(attachInfo, status);
978+
}
979+
}
980+
}
981+
960982
@Override
961983
boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
962984
Rect dirty) {
@@ -1051,15 +1073,7 @@ boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callba
10511073
}
10521074
}
10531075

1054-
if (status != DisplayList.STATUS_DONE) {
1055-
if (mRedrawClip.isEmpty()) {
1056-
attachInfo.mViewRootImpl.invalidate();
1057-
} else {
1058-
attachInfo.mViewRootImpl.invalidateChildInParent(
1059-
null, mRedrawClip);
1060-
mRedrawClip.setEmpty();
1061-
}
1062-
}
1076+
handleFunctorStatus(attachInfo, status);
10631077
} else {
10641078
// Shouldn't reach here
10651079
view.draw(canvas);
@@ -1111,6 +1125,26 @@ boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callba
11111125
return false;
11121126
}
11131127

1128+
private void handleFunctorStatus(View.AttachInfo attachInfo, int status) {
1129+
// If the draw flag is set, functors will be invoked while executing
1130+
// the tree of display lists
1131+
if ((status & DisplayList.STATUS_DRAW) != 0) {
1132+
if (mRedrawClip.isEmpty()) {
1133+
attachInfo.mViewRootImpl.invalidate();
1134+
} else {
1135+
attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip);
1136+
mRedrawClip.setEmpty();
1137+
}
1138+
}
1139+
1140+
if ((status & DisplayList.STATUS_INVOKE) != 0) {
1141+
attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
1142+
mFunctorsRunnable.attachInfo = attachInfo;
1143+
// delay the functor callback by a few ms so it isn't polled constantly
1144+
attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
1145+
}
1146+
}
1147+
11141148
/**
11151149
* Ensures the current EGL context is the one we expect.
11161150
*

core/jni/android_view_GLES20Canvas.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject cl
163163
return renderer->callDrawGLFunction(functor, dirty);
164164
}
165165

166+
static jint android_view_GLES20Canvas_invokeFunctors(JNIEnv* env,
167+
jobject clazz, OpenGLRenderer* renderer, jobject dirty) {
168+
android::uirenderer::Rect bounds;
169+
status_t status = renderer->invokeFunctors(bounds);
170+
if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
171+
env->CallVoidMethod(dirty, gRectClassInfo.set,
172+
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
173+
}
174+
return status;
175+
}
176+
177+
// ----------------------------------------------------------------------------
178+
// Misc
179+
// ----------------------------------------------------------------------------
180+
166181
static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
167182
return Caches::getInstance().maxTextureSize;
168183
}
@@ -824,6 +839,8 @@ static JNINativeMethod gMethods[] = {
824839
{ "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize },
825840

826841
{ "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction },
842+
{ "nInvokeFunctors", "(ILandroid/graphics/Rect;)I",
843+
(void*) android_view_GLES20Canvas_invokeFunctors },
827844

828845
{ "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
829846
{ "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
@@ -899,9 +916,9 @@ static JNINativeMethod gMethods[] = {
899916
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
900917
{ "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListSize },
901918
{ "nSetDisplayListName", "(ILjava/lang/String;)V",
902-
(void*) android_view_GLES20Canvas_setDisplayListName },
919+
(void*) android_view_GLES20Canvas_setDisplayListName },
903920
{ "nDrawDisplayList", "(IIIILandroid/graphics/Rect;I)I",
904-
(void*) android_view_GLES20Canvas_drawDisplayList },
921+
(void*) android_view_GLES20Canvas_drawDisplayList },
905922

906923
{ "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
907924
{ "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer },

include/private/hwui/DrawGlInfo.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,32 @@ struct DrawGlInfo {
4343
float dirtyRight;
4444
float dirtyBottom;
4545

46+
/**
47+
* Values used as the "what" parameter of the functor.
48+
*/
49+
enum Mode {
50+
// Indicates that the functor is called to perform a draw
51+
kModeDraw,
52+
// Indicates the the functor is called only to perform
53+
// processing and that no draw should be attempted
54+
kModeProcess
55+
};
56+
4657
/**
4758
* Values used by OpenGL functors to tell the framework
4859
* what to do next.
4960
*/
5061
enum Status {
5162
// The functor is done
52-
kStatusDone,
63+
kStatusDone = 0x0,
5364
// The functor is requesting a redraw (the clip rect
5465
// used by the redraw is specified by DrawGlInfo.)
5566
// The rest of the UI might redraw too.
56-
kStatusDraw,
67+
kStatusDraw = 0x1,
5768
// The functor needs to be invoked again but will
5869
// not redraw. Only the functor is invoked again
5970
// (unless another functor requests a redraw.)
60-
kStatusInvoke
71+
kStatusInvoke = 0x2
6172
};
6273
}; // struct DrawGlInfo
6374

libs/hwui/OpenGLRenderer.cpp

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ void OpenGLRenderer::prepare(bool opaque) {
166166

167167
void OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
168168
mCaches.clearGarbage();
169+
mFunctors.clear();
169170

170171
mSnapshot = new Snapshot(mFirstSnapshot,
171172
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
@@ -236,7 +237,39 @@ void OpenGLRenderer::resume() {
236237
glBlendEquation(GL_FUNC_ADD);
237238
}
238239

239-
status_t OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
240+
status_t OpenGLRenderer::invokeFunctors(Rect& dirty) {
241+
status_t result = DrawGlInfo::kStatusDone;
242+
243+
Vector<Functor*> functors(mFunctors);
244+
mFunctors.clear();
245+
246+
DrawGlInfo info;
247+
info.clipLeft = 0;
248+
info.clipTop = 0;
249+
info.clipRight = 0;
250+
info.clipBottom = 0;
251+
info.isLayer = false;
252+
memset(info.transform, 0, sizeof(float) * 16);
253+
254+
size_t count = functors.size();
255+
for (size_t i = 0; i < count; i++) {
256+
Functor* f = functors.itemAt(i);
257+
result |= (*f)(DrawGlInfo::kModeProcess, &info);
258+
259+
if (result != DrawGlInfo::kStatusDone) {
260+
Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
261+
dirty.unionWith(localDirty);
262+
263+
if (result == DrawGlInfo::kStatusInvoke) {
264+
mFunctors.push(f);
265+
}
266+
}
267+
}
268+
269+
return result;
270+
}
271+
272+
status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
240273
interrupt();
241274
if (mDirtyClip) {
242275
setScissorFromClip();
@@ -261,11 +294,15 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
261294
info.isLayer = hasLayer();
262295
getSnapshot()->transform->copyTo(&info.transform[0]);
263296

264-
status_t result = (*functor)(0, &info);
297+
status_t result = (*functor)(DrawGlInfo::kModeDraw, &info);
265298

266-
if (result != 0) {
299+
if (result != DrawGlInfo::kStatusDone) {
267300
Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
268301
dirty.unionWith(localDirty);
302+
303+
if (result == DrawGlInfo::kStatusInvoke) {
304+
mFunctors.push(functor);
305+
}
269306
}
270307

271308
resume();

libs/hwui/OpenGLRenderer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class OpenGLRenderer {
7272
virtual void interrupt();
7373
virtual void resume();
7474

75-
virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
75+
ANDROID_API status_t invokeFunctors(Rect& dirty);
76+
virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
7677

7778
ANDROID_API int getSaveCount() const;
7879
virtual int save(int flags);
@@ -602,8 +603,10 @@ class OpenGLRenderer {
602603
// Various caches
603604
Caches& mCaches;
604605

605-
// List of rectagnles to clear after saveLayer() is invoked
606+
// List of rectangles to clear after saveLayer() is invoked
606607
Vector<Rect*> mLayers;
608+
// List of functors to invoke after a frame is drawn
609+
Vector<Functor*> mFunctors;
607610

608611
// Indentity matrix
609612
const mat4 mIdentity;

0 commit comments

Comments
 (0)