• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "OpenGLRenderer"
18 
19 #include <SkCamera.h>
20 #include <SkCanvas.h>
21 
22 #include <private/hwui/DrawGlInfo.h>
23 
24 #include "ResourceCache.h"
25 #include "DeferredDisplayList.h"
26 #include "DeferredLayerUpdater.h"
27 #include "DisplayListLogBuffer.h"
28 #include "DisplayListOp.h"
29 #include "DisplayListRenderer.h"
30 #include "RenderNode.h"
31 
32 namespace android {
33 namespace uirenderer {
34 
DisplayListRenderer()35 DisplayListRenderer::DisplayListRenderer()
36     : mResourceCache(ResourceCache::getInstance())
37     , mDisplayListData(NULL)
38     , mTranslateX(0.0f)
39     , mTranslateY(0.0f)
40     , mDeferredBarrierType(kBarrier_None)
41     , mHighContrastText(false)
42     , mRestoreSaveCount(-1) {
43 }
44 
~DisplayListRenderer()45 DisplayListRenderer::~DisplayListRenderer() {
46     LOG_ALWAYS_FATAL_IF(mDisplayListData,
47             "Destroyed a DisplayListRenderer during a record!");
48 }
49 
50 ///////////////////////////////////////////////////////////////////////////////
51 // Operations
52 ///////////////////////////////////////////////////////////////////////////////
53 
finishRecording()54 DisplayListData* DisplayListRenderer::finishRecording() {
55     mPaintMap.clear();
56     mRegionMap.clear();
57     mPathMap.clear();
58     DisplayListData* data = mDisplayListData;
59     mDisplayListData = 0;
60     return data;
61 }
62 
prepareDirty(float left,float top,float right,float bottom,bool opaque)63 status_t DisplayListRenderer::prepareDirty(float left, float top,
64         float right, float bottom, bool opaque) {
65 
66     LOG_ALWAYS_FATAL_IF(mDisplayListData,
67             "prepareDirty called a second time during a recording!");
68     mDisplayListData = new DisplayListData();
69 
70     initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
71 
72     mDeferredBarrierType = kBarrier_InOrder;
73     mDirtyClip = opaque;
74     mRestoreSaveCount = -1;
75 
76     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
77 }
78 
finish()79 void DisplayListRenderer::finish() {
80     flushRestoreToCount();
81     flushTranslate();
82 }
83 
interrupt()84 void DisplayListRenderer::interrupt() {
85 }
86 
resume()87 void DisplayListRenderer::resume() {
88 }
89 
callDrawGLFunction(Functor * functor,Rect & dirty)90 status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
91     // Ignore dirty during recording, it matters only when we replay
92     addDrawOp(new (alloc()) DrawFunctorOp(functor));
93     mDisplayListData->functors.add(functor);
94     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
95 }
96 
save(int flags)97 int DisplayListRenderer::save(int flags) {
98     addStateOp(new (alloc()) SaveOp(flags));
99     return StatefulBaseRenderer::save(flags);
100 }
101 
restore()102 void DisplayListRenderer::restore() {
103     if (mRestoreSaveCount < 0) {
104         restoreToCount(getSaveCount() - 1);
105         return;
106     }
107 
108     mRestoreSaveCount--;
109     flushTranslate();
110     StatefulBaseRenderer::restore();
111 }
112 
restoreToCount(int saveCount)113 void DisplayListRenderer::restoreToCount(int saveCount) {
114     mRestoreSaveCount = saveCount;
115     flushTranslate();
116     StatefulBaseRenderer::restoreToCount(saveCount);
117 }
118 
saveLayer(float left,float top,float right,float bottom,const SkPaint * paint,int flags)119 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
120         const SkPaint* paint, int flags) {
121     // force matrix/clip isolation for layer
122     flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
123 
124     paint = refPaint(paint);
125     addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
126     return StatefulBaseRenderer::save(flags);
127 }
128 
translate(float dx,float dy,float dz)129 void DisplayListRenderer::translate(float dx, float dy, float dz) {
130     // ignore dz, not used at defer time
131     mHasDeferredTranslate = true;
132     mTranslateX += dx;
133     mTranslateY += dy;
134     flushRestoreToCount();
135     StatefulBaseRenderer::translate(dx, dy, dz);
136 }
137 
rotate(float degrees)138 void DisplayListRenderer::rotate(float degrees) {
139     addStateOp(new (alloc()) RotateOp(degrees));
140     StatefulBaseRenderer::rotate(degrees);
141 }
142 
scale(float sx,float sy)143 void DisplayListRenderer::scale(float sx, float sy) {
144     addStateOp(new (alloc()) ScaleOp(sx, sy));
145     StatefulBaseRenderer::scale(sx, sy);
146 }
147 
skew(float sx,float sy)148 void DisplayListRenderer::skew(float sx, float sy) {
149     addStateOp(new (alloc()) SkewOp(sx, sy));
150     StatefulBaseRenderer::skew(sx, sy);
151 }
152 
setMatrix(const SkMatrix & matrix)153 void DisplayListRenderer::setMatrix(const SkMatrix& matrix) {
154     addStateOp(new (alloc()) SetMatrixOp(matrix));
155     StatefulBaseRenderer::setMatrix(matrix);
156 }
157 
concatMatrix(const SkMatrix & matrix)158 void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) {
159     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
160     StatefulBaseRenderer::concatMatrix(matrix);
161 }
162 
clipRect(float left,float top,float right,float bottom,SkRegion::Op op)163 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
164         SkRegion::Op op) {
165     addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
166     return StatefulBaseRenderer::clipRect(left, top, right, bottom, op);
167 }
168 
clipPath(const SkPath * path,SkRegion::Op op)169 bool DisplayListRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
170     path = refPath(path);
171     addStateOp(new (alloc()) ClipPathOp(path, op));
172     return StatefulBaseRenderer::clipPath(path, op);
173 }
174 
clipRegion(const SkRegion * region,SkRegion::Op op)175 bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
176     region = refRegion(region);
177     addStateOp(new (alloc()) ClipRegionOp(region, op));
178     return StatefulBaseRenderer::clipRegion(region, op);
179 }
180 
drawRenderNode(RenderNode * renderNode,Rect & dirty,int32_t flags)181 status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
182     LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
183 
184     // dirty is an out parameter and should not be recorded,
185     // it matters only when replaying the display list
186     DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
187     addRenderNodeOp(op);
188 
189     return DrawGlInfo::kStatusDone;
190 }
191 
drawLayer(DeferredLayerUpdater * layerHandle,float x,float y)192 status_t DisplayListRenderer::drawLayer(DeferredLayerUpdater* layerHandle, float x, float y) {
193     // We ref the DeferredLayerUpdater due to its thread-safe ref-counting
194     // semantics.
195     mDisplayListData->ref(layerHandle);
196     addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer(), x, y));
197     return DrawGlInfo::kStatusDone;
198 }
199 
drawBitmap(const SkBitmap * bitmap,const SkPaint * paint)200 status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
201     bitmap = refBitmap(bitmap);
202     paint = refPaint(paint);
203 
204     addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
205     return DrawGlInfo::kStatusDone;
206 }
207 
drawBitmap(const SkBitmap * bitmap,float srcLeft,float srcTop,float srcRight,float srcBottom,float dstLeft,float dstTop,float dstRight,float dstBottom,const SkPaint * paint)208 status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
209         float srcRight, float srcBottom, float dstLeft, float dstTop,
210         float dstRight, float dstBottom, const SkPaint* paint) {
211     if (srcLeft == 0 && srcTop == 0
212             && srcRight == bitmap->width() && srcBottom == bitmap->height()
213             && (srcBottom - srcTop == dstBottom - dstTop)
214             && (srcRight - srcLeft == dstRight - dstLeft)) {
215         // transform simple rect to rect drawing case into position bitmap ops, since they merge
216         save(SkCanvas::kMatrix_SaveFlag);
217         translate(dstLeft, dstTop);
218         drawBitmap(bitmap, paint);
219         restore();
220     } else {
221         bitmap = refBitmap(bitmap);
222         paint = refPaint(paint);
223 
224         addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
225                 srcLeft, srcTop, srcRight, srcBottom,
226                 dstLeft, dstTop, dstRight, dstBottom, paint));
227     }
228     return DrawGlInfo::kStatusDone;
229 }
230 
drawBitmapData(const SkBitmap * bitmap,const SkPaint * paint)231 status_t DisplayListRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) {
232     bitmap = refBitmapData(bitmap);
233     paint = refPaint(paint);
234 
235     addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, paint));
236     return DrawGlInfo::kStatusDone;
237 }
238 
drawBitmapMesh(const SkBitmap * bitmap,int meshWidth,int meshHeight,const float * vertices,const int * colors,const SkPaint * paint)239 status_t DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
240         const float* vertices, const int* colors, const SkPaint* paint) {
241     int vertexCount = (meshWidth + 1) * (meshHeight + 1);
242     bitmap = refBitmap(bitmap);
243     vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
244     paint = refPaint(paint);
245     colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
246 
247     addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
248                     vertices, colors, paint));
249     return DrawGlInfo::kStatusDone;
250 }
251 
drawPatch(const SkBitmap * bitmap,const Res_png_9patch * patch,float left,float top,float right,float bottom,const SkPaint * paint)252 status_t DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
253         float left, float top, float right, float bottom, const SkPaint* paint) {
254     bitmap = refBitmap(bitmap);
255     patch = refPatch(patch);
256     paint = refPaint(paint);
257 
258     addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
259     return DrawGlInfo::kStatusDone;
260 }
261 
drawColor(int color,SkXfermode::Mode mode)262 status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
263     addDrawOp(new (alloc()) DrawColorOp(color, mode));
264     return DrawGlInfo::kStatusDone;
265 }
266 
drawRect(float left,float top,float right,float bottom,const SkPaint * paint)267 status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
268         const SkPaint* paint) {
269     paint = refPaint(paint);
270     addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
271     return DrawGlInfo::kStatusDone;
272 }
273 
drawRoundRect(float left,float top,float right,float bottom,float rx,float ry,const SkPaint * paint)274 status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
275         float rx, float ry, const SkPaint* paint) {
276     paint = refPaint(paint);
277     addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
278     return DrawGlInfo::kStatusDone;
279 }
280 
drawRoundRect(CanvasPropertyPrimitive * left,CanvasPropertyPrimitive * top,CanvasPropertyPrimitive * right,CanvasPropertyPrimitive * bottom,CanvasPropertyPrimitive * rx,CanvasPropertyPrimitive * ry,CanvasPropertyPaint * paint)281 status_t DisplayListRenderer::drawRoundRect(
282         CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
283         CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
284         CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
285         CanvasPropertyPaint* paint) {
286     mDisplayListData->ref(left);
287     mDisplayListData->ref(top);
288     mDisplayListData->ref(right);
289     mDisplayListData->ref(bottom);
290     mDisplayListData->ref(rx);
291     mDisplayListData->ref(ry);
292     mDisplayListData->ref(paint);
293     addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value,
294             &right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
295     return DrawGlInfo::kStatusDone;
296 }
297 
drawCircle(float x,float y,float radius,const SkPaint * paint)298 status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint* paint) {
299     paint = refPaint(paint);
300     addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
301     return DrawGlInfo::kStatusDone;
302 }
303 
drawCircle(CanvasPropertyPrimitive * x,CanvasPropertyPrimitive * y,CanvasPropertyPrimitive * radius,CanvasPropertyPaint * paint)304 status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
305         CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
306     mDisplayListData->ref(x);
307     mDisplayListData->ref(y);
308     mDisplayListData->ref(radius);
309     mDisplayListData->ref(paint);
310     addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
311             &radius->value, &paint->value));
312     return DrawGlInfo::kStatusDone;
313 }
314 
drawOval(float left,float top,float right,float bottom,const SkPaint * paint)315 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
316         const SkPaint* paint) {
317     paint = refPaint(paint);
318     addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
319     return DrawGlInfo::kStatusDone;
320 }
321 
drawArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle,bool useCenter,const SkPaint * paint)322 status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
323         float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
324     if (fabs(sweepAngle) >= 360.0f) {
325         return drawOval(left, top, right, bottom, paint);
326     }
327 
328     paint = refPaint(paint);
329     addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
330                     startAngle, sweepAngle, useCenter, paint));
331     return DrawGlInfo::kStatusDone;
332 }
333 
drawPath(const SkPath * path,const SkPaint * paint)334 status_t DisplayListRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
335     path = refPath(path);
336     paint = refPaint(paint);
337 
338     addDrawOp(new (alloc()) DrawPathOp(path, paint));
339     return DrawGlInfo::kStatusDone;
340 }
341 
drawLines(const float * points,int count,const SkPaint * paint)342 status_t DisplayListRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
343     points = refBuffer<float>(points, count);
344     paint = refPaint(paint);
345 
346     addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
347     return DrawGlInfo::kStatusDone;
348 }
349 
drawPoints(const float * points,int count,const SkPaint * paint)350 status_t DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
351     points = refBuffer<float>(points, count);
352     paint = refPaint(paint);
353 
354     addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
355     return DrawGlInfo::kStatusDone;
356 }
357 
drawTextOnPath(const char * text,int bytesCount,int count,const SkPath * path,float hOffset,float vOffset,const SkPaint * paint)358 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
359         const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
360     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
361 
362     text = refText(text, bytesCount);
363     path = refPath(path);
364     paint = refPaint(paint);
365 
366     DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
367             hOffset, vOffset, paint);
368     addDrawOp(op);
369     return DrawGlInfo::kStatusDone;
370 }
371 
drawPosText(const char * text,int bytesCount,int count,const float * positions,const SkPaint * paint)372 status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
373         const float* positions, const SkPaint* paint) {
374     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
375 
376     text = refText(text, bytesCount);
377     positions = refBuffer<float>(positions, count * 2);
378     paint = refPaint(paint);
379 
380     DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
381     addDrawOp(op);
382     return DrawGlInfo::kStatusDone;
383 }
384 
simplifyPaint(int color,SkPaint * paint)385 static void simplifyPaint(int color, SkPaint* paint) {
386     paint->setColor(color);
387     paint->setShader(NULL);
388     paint->setColorFilter(NULL);
389     paint->setLooper(NULL);
390     paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
391     paint->setStrokeJoin(SkPaint::kRound_Join);
392     paint->setLooper(NULL);
393 }
394 
drawText(const char * text,int bytesCount,int count,float x,float y,const float * positions,const SkPaint * paint,float totalAdvance,const Rect & bounds,DrawOpMode drawOpMode)395 status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
396         float x, float y, const float* positions, const SkPaint* paint,
397         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
398 
399     if (!text || count <= 0 || paintWillNotDrawText(*paint)) return DrawGlInfo::kStatusDone;
400 
401     text = refText(text, bytesCount);
402     positions = refBuffer<float>(positions, count * 2);
403 
404     if (CC_UNLIKELY(mHighContrastText)) {
405         // high contrast draw path
406         int color = paint->getColor();
407         int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
408         bool darken = channelSum < (128 * 3);
409 
410         // outline
411         SkPaint* outlinePaint = copyPaint(paint);
412         simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, outlinePaint);
413         outlinePaint->setStyle(SkPaint::kStrokeAndFill_Style);
414         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
415                 x, y, positions, outlinePaint, totalAdvance, bounds)); // bounds?
416 
417         // inner
418         SkPaint* innerPaint = copyPaint(paint);
419         simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, innerPaint);
420         innerPaint->setStyle(SkPaint::kFill_Style);
421         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
422                 x, y, positions, innerPaint, totalAdvance, bounds));
423     } else {
424         // standard draw path
425         paint = refPaint(paint);
426 
427         DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
428                 x, y, positions, paint, totalAdvance, bounds);
429         addDrawOp(op);
430     }
431     return DrawGlInfo::kStatusDone;
432 }
433 
drawRects(const float * rects,int count,const SkPaint * paint)434 status_t DisplayListRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
435     if (count <= 0) return DrawGlInfo::kStatusDone;
436 
437     rects = refBuffer<float>(rects, count);
438     paint = refPaint(paint);
439     addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
440     return DrawGlInfo::kStatusDone;
441 }
442 
resetPaintFilter()443 void DisplayListRenderer::resetPaintFilter() {
444     addStateOp(new (alloc()) ResetPaintFilterOp());
445 }
446 
setupPaintFilter(int clearBits,int setBits)447 void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
448     addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
449 }
450 
insertReorderBarrier(bool enableReorder)451 void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
452     flushRestoreToCount();
453     flushTranslate();
454     mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
455 }
456 
flushRestoreToCount()457 void DisplayListRenderer::flushRestoreToCount() {
458     if (mRestoreSaveCount >= 0) {
459         addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
460         mRestoreSaveCount = -1;
461     }
462 }
463 
flushTranslate()464 void DisplayListRenderer::flushTranslate() {
465     if (mHasDeferredTranslate) {
466         if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
467             addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
468             mTranslateX = mTranslateY = 0.0f;
469         }
470         mHasDeferredTranslate = false;
471     }
472 }
473 
addOpAndUpdateChunk(DisplayListOp * op)474 size_t DisplayListRenderer::addOpAndUpdateChunk(DisplayListOp* op) {
475     int insertIndex = mDisplayListData->displayListOps.add(op);
476     if (mDeferredBarrierType != kBarrier_None) {
477         // op is first in new chunk
478         mDisplayListData->chunks.push();
479         DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop();
480         newChunk.beginOpIndex = insertIndex;
481         newChunk.endOpIndex = insertIndex + 1;
482         newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
483 
484         int nextChildIndex = mDisplayListData->children().size();
485         newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
486         mDeferredBarrierType = kBarrier_None;
487     } else {
488         // standard case - append to existing chunk
489         mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1;
490     }
491     return insertIndex;
492 }
493 
flushAndAddOp(DisplayListOp * op)494 size_t DisplayListRenderer::flushAndAddOp(DisplayListOp* op) {
495     flushRestoreToCount();
496     flushTranslate();
497     return addOpAndUpdateChunk(op);
498 }
499 
addStateOp(StateOp * op)500 size_t DisplayListRenderer::addStateOp(StateOp* op) {
501     return flushAndAddOp(op);
502 }
503 
addDrawOp(DrawOp * op)504 size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
505     Rect localBounds;
506     if (op->getLocalBounds(localBounds)) {
507         bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
508                 localBounds.right, localBounds.bottom);
509         op->setQuickRejected(rejected);
510     }
511 
512     mDisplayListData->hasDrawOps = true;
513     return flushAndAddOp(op);
514 }
515 
addRenderNodeOp(DrawRenderNodeOp * op)516 size_t DisplayListRenderer::addRenderNodeOp(DrawRenderNodeOp* op) {
517     int opIndex = addDrawOp(op);
518     int childIndex = mDisplayListData->addChild(op);
519 
520     // update the chunk's child indices
521     DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();
522     chunk.endChildIndex = childIndex + 1;
523 
524     if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
525         // use staging property, since recording on UI thread
526         mDisplayListData->projectionReceiveIndex = opIndex;
527     }
528     return opIndex;
529 }
530 
531 }; // namespace uirenderer
532 }; // namespace android
533