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