DisplayListRenderer.cpp revision 8b2f5267f16c295f12faab810527cd6311997e34
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 "DisplayListRenderer.h" 20 21namespace android { 22namespace uirenderer { 23 24/////////////////////////////////////////////////////////////////////////////// 25// Defines 26/////////////////////////////////////////////////////////////////////////////// 27 28#define PATH_HEAP_SIZE 64 29 30/////////////////////////////////////////////////////////////////////////////// 31// Helpers 32/////////////////////////////////////////////////////////////////////////////// 33 34PathHeap::PathHeap(): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) { 35} 36 37PathHeap::PathHeap(SkFlattenableReadBuffer& buffer): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) { 38 int count = buffer.readS32(); 39 40 mPaths.setCount(count); 41 SkPath** ptr = mPaths.begin(); 42 SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath)); 43 44 for (int i = 0; i < count; i++) { 45 new (p) SkPath; 46 p->unflatten(buffer); 47 *ptr++ = p; 48 p++; 49 } 50} 51 52PathHeap::~PathHeap() { 53 SkPath** iter = mPaths.begin(); 54 SkPath** stop = mPaths.end(); 55 while (iter < stop) { 56 (*iter)->~SkPath(); 57 iter++; 58 } 59} 60 61int PathHeap::append(const SkPath& path) { 62 SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath)); 63 new (p) SkPath(path); 64 *mPaths.append() = p; 65 return mPaths.count(); 66} 67 68void PathHeap::flatten(SkFlattenableWriteBuffer& buffer) const { 69 int count = mPaths.count(); 70 71 buffer.write32(count); 72 SkPath** iter = mPaths.begin(); 73 SkPath** stop = mPaths.end(); 74 while (iter < stop) { 75 (*iter)->flatten(buffer); 76 iter++; 77 } 78} 79 80/////////////////////////////////////////////////////////////////////////////// 81// Display list 82/////////////////////////////////////////////////////////////////////////////// 83 84const char* DisplayList::OP_NAMES[] = { 85 "AcquireContext", 86 "ReleaseContext", 87 "Save", 88 "Restore", 89 "RestoreToCount", 90 "SaveLayer", 91 "SaveLayerAlpha", 92 "Translate", 93 "Rotate", 94 "Scale", 95 "Skew", 96 "SetMatrix", 97 "ConcatMatrix", 98 "ClipRect", 99 "DrawDisplayList", 100 "DrawLayer", 101 "DrawBitmap", 102 "DrawBitmapMatrix", 103 "DrawBitmapRect", 104 "DrawBitmapMesh", 105 "DrawPatch", 106 "DrawColor", 107 "DrawRect", 108 "DrawRoundRect", 109 "DrawCircle", 110 "DrawOval", 111 "DrawArc", 112 "DrawPath", 113 "DrawLines", 114 "DrawText", 115 "ResetShader", 116 "SetupShader", 117 "ResetColorFilter", 118 "SetupColorFilter", 119 "ResetShadow", 120 "SetupShadow" 121}; 122 123DisplayList::DisplayList(const DisplayListRenderer& recorder) { 124 initFromDisplayListRenderer(recorder); 125} 126 127DisplayList::~DisplayList() { 128 sk_free((void*) mReader.base()); 129 130 Caches& caches = Caches::getInstance(); 131 132 for (size_t i = 0; i < mBitmapResources.size(); i++) { 133 caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i)); 134 } 135 mBitmapResources.clear(); 136 137 for (size_t i = 0; i < mShaders.size(); i++) { 138 caches.resourceCache.decrementRefcount(mShaders.itemAt(i)); 139 } 140 mShaders.clear(); 141 142 for (size_t i = 0; i < mPaints.size(); i++) { 143 delete mPaints.itemAt(i); 144 } 145 mPaints.clear(); 146 147 for (size_t i = 0; i < mMatrices.size(); i++) { 148 delete mMatrices.itemAt(i); 149 } 150 mMatrices.clear(); 151 152 if (mPathHeap) { 153 for (int i = 0; i < mPathHeap->count(); i++) { 154 caches.pathCache.removeDeferred(&(*mPathHeap)[i]); 155 } 156 mPathHeap->safeUnref(); 157 } 158} 159 160void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder) { 161 const SkWriter32& writer = recorder.writeStream(); 162 init(); 163 164 if (writer.size() == 0) { 165 return; 166 } 167 168 size_t size = writer.size(); 169 void* buffer = sk_malloc_throw(size); 170 writer.flatten(buffer); 171 mReader.setMemory(buffer, size); 172 173 mRCPlayback.reset(&recorder.mRCRecorder); 174 mRCPlayback.setupBuffer(mReader); 175 176 mTFPlayback.reset(&recorder.mTFRecorder); 177 mTFPlayback.setupBuffer(mReader); 178 179 Caches& caches = Caches::getInstance(); 180 181 const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources(); 182 for (size_t i = 0; i < bitmapResources.size(); i++) { 183 SkBitmap* resource = bitmapResources.itemAt(i); 184 mBitmapResources.add(resource); 185 caches.resourceCache.incrementRefcount(resource); 186 } 187 188 const Vector<SkiaShader*> &shaders = recorder.getShaders(); 189 for (size_t i = 0; i < shaders.size(); i++) { 190 SkiaShader* shader = shaders.itemAt(i); 191 mShaders.add(shader); 192 caches.resourceCache.incrementRefcount(shader); 193 } 194 195 const Vector<SkPaint*> &paints = recorder.getPaints(); 196 for (size_t i = 0; i < paints.size(); i++) { 197 mPaints.add(paints.itemAt(i)); 198 } 199 200 const Vector<SkMatrix*> &matrices = recorder.getMatrices(); 201 for (size_t i = 0; i < matrices.size(); i++) { 202 mMatrices.add(matrices.itemAt(i)); 203 } 204 205 mPathHeap = recorder.mPathHeap; 206 if (mPathHeap) { 207 mPathHeap->safeRef(); 208 } 209} 210 211void DisplayList::init() { 212 mPathHeap = NULL; 213} 214 215void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) { 216 TextContainer text; 217 mReader.rewind(); 218 219#if DEBUG_DISPLAY_LIST 220 uint32_t count = (level + 1) * 2; 221 char indent[count + 1]; 222 for (uint32_t i = 0; i < count; i++) { 223 indent[i] = ' '; 224 } 225 indent[count] = '\0'; 226 DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this); 227#endif 228 229 int saveCount = renderer.getSaveCount() - 1; 230 while (!mReader.eof()) { 231 int op = mReader.readInt(); 232 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); 233 234 switch (op) { 235 case AcquireContext: { 236 renderer.acquireContext(); 237 } 238 break; 239 case ReleaseContext: { 240 renderer.releaseContext(); 241 } 242 break; 243 case Save: { 244 renderer.save(getInt()); 245 } 246 break; 247 case Restore: { 248 renderer.restore(); 249 } 250 break; 251 case RestoreToCount: { 252 renderer.restoreToCount(saveCount + getInt()); 253 } 254 break; 255 case SaveLayer: { 256 renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(), 257 getPaint(), getInt()); 258 } 259 break; 260 case SaveLayerAlpha: { 261 renderer.saveLayerAlpha(getFloat(), getFloat(), getFloat(), getFloat(), 262 getInt(), getInt()); 263 } 264 break; 265 case Translate: { 266 renderer.translate(getFloat(), getFloat()); 267 } 268 break; 269 case Rotate: { 270 renderer.rotate(getFloat()); 271 } 272 break; 273 case Scale: { 274 renderer.scale(getFloat(), getFloat()); 275 } 276 break; 277 case Skew: { 278 renderer.skew(getFloat(), getFloat()); 279 } 280 break; 281 case SetMatrix: { 282 renderer.setMatrix(getMatrix()); 283 } 284 break; 285 case ConcatMatrix: { 286 renderer.concatMatrix(getMatrix()); 287 } 288 break; 289 case ClipRect: { 290 renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(), 291 (SkRegion::Op) getInt()); 292 } 293 break; 294 case DrawDisplayList: { 295 renderer.drawDisplayList(getDisplayList(), level + 1); 296 } 297 break; 298 case DrawLayer: { 299 renderer.drawLayer((Layer*) getInt(), getFloat(), getFloat(), getPaint()); 300 } 301 break; 302 case DrawBitmap: { 303 renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint()); 304 } 305 break; 306 case DrawBitmapMatrix: { 307 renderer.drawBitmap(getBitmap(), getMatrix(), getPaint()); 308 } 309 break; 310 case DrawBitmapRect: { 311 renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(), 312 getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 313 } 314 break; 315 case DrawBitmapMesh: { 316 int verticesCount = 0; 317 uint32_t colorsCount = 0; 318 319 SkBitmap* bitmap = getBitmap(); 320 uint32_t meshWidth = getInt(); 321 uint32_t meshHeight = getInt(); 322 float* vertices = getFloats(verticesCount); 323 bool hasColors = getInt(); 324 int* colors = hasColors ? getInts(colorsCount) : NULL; 325 326 renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint()); 327 } 328 case DrawPatch: { 329 int32_t* xDivs = NULL; 330 int32_t* yDivs = NULL; 331 uint32_t* colors = NULL; 332 uint32_t xDivsCount = 0; 333 uint32_t yDivsCount = 0; 334 int8_t numColors = 0; 335 336 SkBitmap* bitmap = getBitmap(); 337 338 xDivs = getInts(xDivsCount); 339 yDivs = getInts(yDivsCount); 340 colors = getUInts(numColors); 341 342 renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount, 343 numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 344 } 345 break; 346 case DrawColor: { 347 renderer.drawColor(getInt(), (SkXfermode::Mode) getInt()); 348 } 349 break; 350 case DrawRect: { 351 renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 352 } 353 break; 354 case DrawRoundRect: { 355 renderer.drawRoundRect(getFloat(), getFloat(), getFloat(), getFloat(), 356 getFloat(), getFloat(), getPaint()); 357 } 358 break; 359 case DrawCircle: { 360 renderer.drawCircle(getFloat(), getFloat(), getFloat(), getPaint()); 361 } 362 break; 363 case DrawOval: { 364 renderer.drawOval(getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 365 } 366 break; 367 case DrawArc: { 368 renderer.drawArc(getFloat(), getFloat(), getFloat(), getFloat(), 369 getFloat(), getFloat(), getInt() == 1, getPaint()); 370 } 371 break; 372 case DrawPath: { 373 renderer.drawPath(getPath(), getPaint()); 374 } 375 break; 376 case DrawLines: { 377 int count = 0; 378 float* points = getFloats(count); 379 renderer.drawLines(points, count, getPaint()); 380 } 381 break; 382 case DrawText: { 383 getText(&text); 384 renderer.drawText(text.text(), text.length(), getInt(), 385 getFloat(), getFloat(), getPaint()); 386 } 387 break; 388 case ResetShader: { 389 renderer.resetShader(); 390 } 391 break; 392 case SetupShader: { 393 renderer.setupShader(getShader()); 394 } 395 break; 396 case ResetColorFilter: { 397 renderer.resetColorFilter(); 398 } 399 break; 400 case SetupColorFilter: { 401 renderer.setupColorFilter(getColorFilter()); 402 } 403 break; 404 case ResetShadow: { 405 renderer.resetShadow(); 406 } 407 break; 408 case SetupShadow: { 409 renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt()); 410 } 411 break; 412 } 413 } 414 415 DISPLAY_LIST_LOGD("%sDone", (char*) indent + 2); 416} 417 418/////////////////////////////////////////////////////////////////////////////// 419// Base structure 420/////////////////////////////////////////////////////////////////////////////// 421 422DisplayListRenderer::DisplayListRenderer(): 423 mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) { 424 mPathHeap = NULL; 425 mDisplayList = NULL; 426} 427 428DisplayListRenderer::~DisplayListRenderer() { 429 reset(); 430} 431 432void DisplayListRenderer::reset() { 433 if (mPathHeap) { 434 mPathHeap->unref(); 435 mPathHeap = NULL; 436 } 437 438 mWriter.reset(); 439 mHeap.reset(); 440 441 mRCRecorder.reset(); 442 mTFRecorder.reset(); 443 444 Caches& caches = Caches::getInstance(); 445 for (size_t i = 0; i < mBitmapResources.size(); i++) { 446 SkBitmap* resource = mBitmapResources.itemAt(i); 447 caches.resourceCache.decrementRefcount(resource); 448 } 449 mBitmapResources.clear(); 450 451 for (size_t i = 0; i < mShaders.size(); i++) { 452 caches.resourceCache.decrementRefcount(mShaders.itemAt(i)); 453 } 454 mShaders.clear(); 455 mShaderMap.clear(); 456 457 mPaints.clear(); 458 mPaintMap.clear(); 459 mMatrices.clear(); 460} 461 462/////////////////////////////////////////////////////////////////////////////// 463// Operations 464/////////////////////////////////////////////////////////////////////////////// 465 466DisplayList* DisplayListRenderer::getDisplayList() { 467 if (mDisplayList == NULL) { 468 mDisplayList = new DisplayList(*this); 469 } else { 470 mDisplayList->initFromDisplayListRenderer(*this); 471 } 472 return mDisplayList; 473} 474 475void DisplayListRenderer::setViewport(int width, int height) { 476 mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 477 478 mWidth = width; 479 mHeight = height; 480} 481 482void DisplayListRenderer::prepare(bool opaque) { 483 mSnapshot = new Snapshot(mFirstSnapshot, 484 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 485 mSaveCount = 1; 486 mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); 487 mRestoreSaveCount = -1; 488} 489 490void DisplayListRenderer::finish() { 491 insertRestoreToCount(); 492 OpenGLRenderer::finish(); 493} 494 495void DisplayListRenderer::acquireContext() { 496 addOp(DisplayList::AcquireContext); 497 OpenGLRenderer::acquireContext(); 498} 499 500void DisplayListRenderer::releaseContext() { 501 addOp(DisplayList::ReleaseContext); 502 OpenGLRenderer::releaseContext(); 503} 504 505int DisplayListRenderer::save(int flags) { 506 addOp(DisplayList::Save); 507 addInt(flags); 508 return OpenGLRenderer::save(flags); 509} 510 511void DisplayListRenderer::restore() { 512 addOp(DisplayList::Restore); 513 OpenGLRenderer::restore(); 514} 515 516void DisplayListRenderer::restoreToCount(int saveCount) { 517 mRestoreSaveCount = saveCount; 518 OpenGLRenderer::restoreToCount(saveCount); 519} 520 521int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom, 522 SkPaint* p, int flags) { 523 addOp(DisplayList::SaveLayer); 524 addBounds(left, top, right, bottom); 525 addPaint(p); 526 addInt(flags); 527 return OpenGLRenderer::save(flags); 528} 529 530int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom, 531 int alpha, int flags) { 532 addOp(DisplayList::SaveLayerAlpha); 533 addBounds(left, top, right, bottom); 534 addInt(alpha); 535 addInt(flags); 536 return OpenGLRenderer::save(flags); 537} 538 539void DisplayListRenderer::translate(float dx, float dy) { 540 addOp(DisplayList::Translate); 541 addPoint(dx, dy); 542 OpenGLRenderer::translate(dx, dy); 543} 544 545void DisplayListRenderer::rotate(float degrees) { 546 addOp(DisplayList::Rotate); 547 addFloat(degrees); 548 OpenGLRenderer::rotate(degrees); 549} 550 551void DisplayListRenderer::scale(float sx, float sy) { 552 addOp(DisplayList::Scale); 553 addPoint(sx, sy); 554 OpenGLRenderer::scale(sx, sy); 555} 556 557void DisplayListRenderer::skew(float sx, float sy) { 558 addOp(DisplayList::Skew); 559 addPoint(sx, sy); 560 OpenGLRenderer::skew(sx, sy); 561} 562 563void DisplayListRenderer::setMatrix(SkMatrix* matrix) { 564 addOp(DisplayList::SetMatrix); 565 addMatrix(matrix); 566 OpenGLRenderer::setMatrix(matrix); 567} 568 569void DisplayListRenderer::concatMatrix(SkMatrix* matrix) { 570 addOp(DisplayList::ConcatMatrix); 571 addMatrix(matrix); 572 OpenGLRenderer::concatMatrix(matrix); 573} 574 575bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom, 576 SkRegion::Op op) { 577 addOp(DisplayList::ClipRect); 578 addBounds(left, top, right, bottom); 579 addInt(op); 580 return OpenGLRenderer::clipRect(left, top, right, bottom, op); 581} 582 583void DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) { 584 addOp(DisplayList::DrawDisplayList); 585 addDisplayList(displayList); 586} 587 588void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { 589 addOp(DisplayList::DrawLayer); 590 addInt((int) layer); 591 addPoint(x, y); 592 addPaint(paint); 593} 594 595void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, 596 SkPaint* paint) { 597 addOp(DisplayList::DrawBitmap); 598 addBitmap(bitmap); 599 addPoint(left, top); 600 addPaint(paint); 601} 602 603void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, 604 SkPaint* paint) { 605 addOp(DisplayList::DrawBitmapMatrix); 606 addBitmap(bitmap); 607 addMatrix(matrix); 608 addPaint(paint); 609} 610 611void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, 612 float srcRight, float srcBottom, float dstLeft, float dstTop, 613 float dstRight, float dstBottom, SkPaint* paint) { 614 addOp(DisplayList::DrawBitmapRect); 615 addBitmap(bitmap); 616 addBounds(srcLeft, srcTop, srcRight, srcBottom); 617 addBounds(dstLeft, dstTop, dstRight, dstBottom); 618 addPaint(paint); 619} 620 621void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, 622 float* vertices, int* colors, SkPaint* paint) { 623 addOp(DisplayList::DrawBitmapMesh); 624 addBitmap(bitmap); 625 addInt(meshWidth); 626 addInt(meshHeight); 627 addFloats(vertices, (meshWidth + 1) * (meshHeight + 1) * 2); 628 if (colors) { 629 addInt(1); 630 addInts(colors, (meshWidth + 1) * (meshHeight + 1)); 631 } else { 632 addInt(0); 633 } 634 addPaint(paint); 635} 636 637void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, 638 const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, 639 float left, float top, float right, float bottom, SkPaint* paint) { 640 addOp(DisplayList::DrawPatch); 641 addBitmap(bitmap); 642 addInts(xDivs, width); 643 addInts(yDivs, height); 644 addUInts(colors, numColors); 645 addBounds(left, top, right, bottom); 646 addPaint(paint); 647} 648 649void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { 650 addOp(DisplayList::DrawColor); 651 addInt(color); 652 addInt(mode); 653} 654 655void DisplayListRenderer::drawRect(float left, float top, float right, float bottom, 656 SkPaint* paint) { 657 addOp(DisplayList::DrawRect); 658 addBounds(left, top, right, bottom); 659 addPaint(paint); 660} 661 662void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom, 663 float rx, float ry, SkPaint* paint) { 664 addOp(DisplayList::DrawRoundRect); 665 addBounds(left, top, right, bottom); 666 addPoint(rx, ry); 667 addPaint(paint); 668} 669 670void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { 671 addOp(DisplayList::DrawCircle); 672 addPoint(x, y); 673 addFloat(radius); 674 addPaint(paint); 675} 676 677void DisplayListRenderer::drawOval(float left, float top, float right, float bottom, 678 SkPaint* paint) { 679 addOp(DisplayList::DrawOval); 680 addBounds(left, top, right, bottom); 681 addPaint(paint); 682} 683 684void DisplayListRenderer::drawArc(float left, float top, float right, float bottom, 685 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { 686 addOp(DisplayList::DrawOval); 687 addBounds(left, top, right, bottom); 688 addPoint(startAngle, sweepAngle); 689 addInt(useCenter ? 1 : 0); 690 addPaint(paint); 691} 692 693void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) { 694 addOp(DisplayList::DrawPath); 695 addPath(path); 696 addPaint(paint); 697} 698 699void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) { 700 addOp(DisplayList::DrawLines); 701 addFloats(points, count); 702 addPaint(paint); 703} 704 705void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, 706 float x, float y, SkPaint* paint) { 707 addOp(DisplayList::DrawText); 708 addText(text, bytesCount); 709 addInt(count); 710 addPoint(x, y); 711 addPaint(paint); 712} 713 714void DisplayListRenderer::resetShader() { 715 addOp(DisplayList::ResetShader); 716} 717 718void DisplayListRenderer::setupShader(SkiaShader* shader) { 719 addOp(DisplayList::SetupShader); 720 addShader(shader); 721} 722 723void DisplayListRenderer::resetColorFilter() { 724 addOp(DisplayList::ResetColorFilter); 725} 726 727void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) { 728 addOp(DisplayList::SetupColorFilter); 729 addColorFilter(filter); 730} 731 732void DisplayListRenderer::resetShadow() { 733 addOp(DisplayList::ResetShadow); 734} 735 736void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) { 737 addOp(DisplayList::SetupShadow); 738 addFloat(radius); 739 addPoint(dx, dy); 740 addInt(color); 741} 742 743}; // namespace uirenderer 744}; // namespace android 745