DisplayListRenderer.cpp revision 5977baa1fa24125c148a72699b53e62abaf08960
17cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 27cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Copyright (C) 2010 The Android Open Source Project 37cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 47cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 57cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * you may not use this file except in compliance with the License. 67cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * You may obtain a copy of the License at 77cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 87cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 97cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Unless required by applicable law or agreed to in writing, software 117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * See the License for the specific language governing permissions and 147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * limitations under the License. 157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define LOG_TAG "OpenGLRenderer" 187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include "DisplayListRenderer.h" 207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace android { 227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace uirenderer { 237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/////////////////////////////////////////////////////////////////////////////// 257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root// Defines 267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/////////////////////////////////////////////////////////////////////////////// 277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define PATH_HEAP_SIZE 64 297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/////////////////////////////////////////////////////////////////////////////// 317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root// Helpers 327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/////////////////////////////////////////////////////////////////////////////// 337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootPathHeap::PathHeap(): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) { 357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootPathHeap::PathHeap(SkFlattenableReadBuffer& buffer): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) { 387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int count = buffer.readS32(); 397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mPaths.setCount(count); 417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath** ptr = mPaths.begin(); 427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath)); 437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root for (int i = 0; i < count; i++) { 457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root new (p) SkPath; 467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root p->unflatten(buffer); 477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root *ptr++ = p; 487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root p++; 497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootPathHeap::~PathHeap() { 537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath** iter = mPaths.begin(); 547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath** stop = mPaths.end(); 557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root while (iter < stop) { 567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root (*iter)->~SkPath(); 577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root iter++; 587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootint PathHeap::append(const SkPath& path) { 627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath)); 637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root new (p) SkPath(path); 647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root *mPaths.append() = p; 657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return mPaths.count(); 667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootvoid PathHeap::flatten(SkFlattenableWriteBuffer& buffer) const { 697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int count = mPaths.count(); 707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root buffer.write32(count); 727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath** iter = mPaths.begin(); 737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root SkPath** stop = mPaths.end(); 747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root while (iter < stop) { 757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root (*iter)->flatten(buffer); 76 iter++; 77 } 78} 79 80/////////////////////////////////////////////////////////////////////////////// 81// Display list 82/////////////////////////////////////////////////////////////////////////////// 83 84DisplayList::DisplayList(const DisplayListRenderer& recorder) { 85 initFromDisplayListRenderer(recorder); 86} 87 88DisplayList::~DisplayList() { 89 sk_free((void*) mReader.base()); 90 91 Caches& caches = Caches::getInstance(); 92 93 for (size_t i = 0; i < mBitmapResources.size(); i++) { 94 caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i)); 95 } 96 mBitmapResources.clear(); 97 98 for (size_t i = 0; i < mShaderResources.size(); i++) { 99 caches.resourceCache.decrementRefcount(mShaderResources.itemAt(i)); 100 } 101 mShaderResources.clear(); 102 103 for (size_t i = 0; i < mPaints.size(); i++) { 104 delete mPaints.itemAt(i); 105 } 106 mPaints.clear(); 107 108 for (size_t i = 0; i < mMatrices.size(); i++) { 109 delete mMatrices.itemAt(i); 110 } 111 mMatrices.clear(); 112 113 if (mPathHeap) { 114 for (int i = 0; i < mPathHeap->count(); i++) { 115 caches.pathCache.removeDeferred(&(*mPathHeap)[i]); 116 } 117 mPathHeap->safeUnref(); 118 } 119} 120 121void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder) { 122 const SkWriter32& writer = recorder.writeStream(); 123 init(); 124 125 if (writer.size() == 0) { 126 return; 127 } 128 129 size_t size = writer.size(); 130 void* buffer = sk_malloc_throw(size); 131 writer.flatten(buffer); 132 mReader.setMemory(buffer, size); 133 134 mRCPlayback.reset(&recorder.mRCRecorder); 135 mRCPlayback.setupBuffer(mReader); 136 137 mTFPlayback.reset(&recorder.mTFRecorder); 138 mTFPlayback.setupBuffer(mReader); 139 140 Caches& caches = Caches::getInstance(); 141 142 const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources(); 143 for (size_t i = 0; i < bitmapResources.size(); i++) { 144 SkBitmap* resource = bitmapResources.itemAt(i); 145 mBitmapResources.add(resource); 146 caches.resourceCache.incrementRefcount(resource); 147 } 148 149 const Vector<SkiaShader*> &shaderResources = recorder.getShaderResources(); 150 for (size_t i = 0; i < shaderResources.size(); i++) { 151 SkiaShader* resource = shaderResources.itemAt(i); 152 mShaderResources.add(resource); 153 caches.resourceCache.incrementRefcount(resource); 154 } 155 156 const Vector<SkPaint*> &paints = recorder.getPaints(); 157 for (size_t i = 0; i < paints.size(); i++) { 158 mPaints.add(paints.itemAt(i)); 159 } 160 161 const Vector<SkMatrix*> &matrices = recorder.getMatrices(); 162 for (size_t i = 0; i < matrices.size(); i++) { 163 mMatrices.add(matrices.itemAt(i)); 164 } 165 166 mPathHeap = recorder.mPathHeap; 167 if (mPathHeap) { 168 mPathHeap->safeRef(); 169 } 170} 171 172void DisplayList::init() { 173 mPathHeap = NULL; 174} 175 176void DisplayList::replay(OpenGLRenderer& renderer) { 177 TextContainer text; 178 mReader.rewind(); 179 180 int saveCount = renderer.getSaveCount() - 1; 181 182 while (!mReader.eof()) { 183 int op = mReader.readInt(); 184 switch (op) { 185 case AcquireContext: { 186 renderer.acquireContext(); 187 } 188 break; 189 case ReleaseContext: { 190 renderer.releaseContext(); 191 } 192 break; 193 case Save: { 194 renderer.save(getInt()); 195 } 196 break; 197 case Restore: { 198 renderer.restore(); 199 } 200 break; 201 case RestoreToCount: { 202 renderer.restoreToCount(saveCount + getInt()); 203 } 204 break; 205 case SaveLayer: { 206 renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(), 207 getPaint(), getInt()); 208 } 209 break; 210 case SaveLayerAlpha: { 211 renderer.saveLayerAlpha(getFloat(), getFloat(), getFloat(), getFloat(), 212 getInt(), getInt()); 213 } 214 break; 215 case Translate: { 216 renderer.translate(getFloat(), getFloat()); 217 } 218 break; 219 case Rotate: { 220 renderer.rotate(getFloat()); 221 } 222 break; 223 case Scale: { 224 renderer.scale(getFloat(), getFloat()); 225 } 226 break; 227 case SetMatrix: { 228 renderer.setMatrix(getMatrix()); 229 } 230 break; 231 case ConcatMatrix: { 232 renderer.concatMatrix(getMatrix()); 233 } 234 break; 235 case ClipRect: { 236 renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(), 237 (SkRegion::Op) getInt()); 238 } 239 break; 240 case DrawDisplayList: { 241 renderer.drawDisplayList(getDisplayList()); 242 } 243 break; 244 case DrawBitmap: { 245 renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint()); 246 } 247 break; 248 case DrawBitmapMatrix: { 249 renderer.drawBitmap(getBitmap(), getMatrix(), getPaint()); 250 } 251 break; 252 case DrawBitmapRect: { 253 renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(), 254 getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 255 } 256 break; 257 case DrawPatch: { 258 int32_t* xDivs = NULL; 259 int32_t* yDivs = NULL; 260 uint32_t* colors = NULL; 261 uint32_t xDivsCount = 0; 262 uint32_t yDivsCount = 0; 263 int8_t numColors = 0; 264 265 SkBitmap* bitmap = getBitmap(); 266 267 xDivs = getInts(xDivsCount); 268 yDivs = getInts(yDivsCount); 269 colors = getUInts(numColors); 270 271 renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount, 272 numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 273 } 274 break; 275 case DrawColor: { 276 renderer.drawColor(getInt(), (SkXfermode::Mode) getInt()); 277 } 278 break; 279 case DrawRect: { 280 renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); 281 } 282 break; 283 case DrawPath: { 284 renderer.drawPath(getPath(), getPaint()); 285 } 286 break; 287 case DrawLines: { 288 int count = 0; 289 float* points = getFloats(count); 290 renderer.drawLines(points, count, getPaint()); 291 } 292 break; 293 case DrawText: { 294 getText(&text); 295 renderer.drawText(text.text(), text.length(), getInt(), 296 getFloat(), getFloat(), getPaint()); 297 } 298 break; 299 case ResetShader: { 300 renderer.resetShader(); 301 } 302 break; 303 case SetupShader: { 304 renderer.setupShader(getShader()); 305 } 306 break; 307 case ResetColorFilter: { 308 renderer.resetColorFilter(); 309 } 310 break; 311 case SetupColorFilter: { 312 renderer.setupColorFilter(getColorFilter()); 313 } 314 break; 315 case ResetShadow: { 316 renderer.resetShadow(); 317 } 318 break; 319 case SetupShadow: { 320 renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt()); 321 } 322 break; 323 } 324 } 325} 326 327/////////////////////////////////////////////////////////////////////////////// 328// Base structure 329/////////////////////////////////////////////////////////////////////////////// 330 331DisplayListRenderer::DisplayListRenderer(): 332 mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) { 333 mPathHeap = NULL; 334 mDisplayList = NULL; 335} 336 337DisplayListRenderer::~DisplayListRenderer() { 338 reset(); 339} 340 341void DisplayListRenderer::reset() { 342 if (mPathHeap) { 343 mPathHeap->unref(); 344 mPathHeap = NULL; 345 } 346 347 mWriter.reset(); 348 mHeap.reset(); 349 350 mRCRecorder.reset(); 351 mTFRecorder.reset(); 352 353 Caches& caches = Caches::getInstance(); 354 for (size_t i = 0; i < mBitmapResources.size(); i++) { 355 SkBitmap* resource = mBitmapResources.itemAt(i); 356 caches.resourceCache.decrementRefcount(resource); 357 } 358 mBitmapResources.clear(); 359 360 for (size_t i = 0; i < mShaderResources.size(); i++) { 361 SkiaShader* resource = mShaderResources.itemAt(i); 362 caches.resourceCache.decrementRefcount(resource); 363 } 364 mShaderResources.clear(); 365 366 mPaints.clear(); 367 mPaintMap.clear(); 368 mMatrices.clear(); 369} 370 371/////////////////////////////////////////////////////////////////////////////// 372// Operations 373/////////////////////////////////////////////////////////////////////////////// 374 375DisplayList* DisplayListRenderer::getDisplayList() { 376 if (mDisplayList == NULL) { 377 mDisplayList = new DisplayList(*this); 378 } else { 379 mDisplayList->initFromDisplayListRenderer(*this); 380 } 381 return mDisplayList; 382} 383 384void DisplayListRenderer::setViewport(int width, int height) { 385 mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 386 387 mWidth = width; 388 mHeight = height; 389} 390 391void DisplayListRenderer::prepare(bool opaque) { 392 mSnapshot = new Snapshot(mFirstSnapshot, 393 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 394 mSaveCount = 1; 395 mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); 396} 397 398void DisplayListRenderer::acquireContext() { 399 addOp(DisplayList::AcquireContext); 400 OpenGLRenderer::acquireContext(); 401} 402 403void DisplayListRenderer::releaseContext() { 404 addOp(DisplayList::ReleaseContext); 405 OpenGLRenderer::releaseContext(); 406} 407 408int DisplayListRenderer::save(int flags) { 409 addOp(DisplayList::Save); 410 addInt(flags); 411 return OpenGLRenderer::save(flags); 412} 413 414void DisplayListRenderer::restore() { 415 addOp(DisplayList::Restore); 416 OpenGLRenderer::restore(); 417} 418 419void DisplayListRenderer::restoreToCount(int saveCount) { 420 addOp(DisplayList::RestoreToCount); 421 addInt(saveCount); 422 OpenGLRenderer::restoreToCount(saveCount); 423} 424 425int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom, 426 SkPaint* p, int flags) { 427 addOp(DisplayList::SaveLayer); 428 addBounds(left, top, right, bottom); 429 addPaint(p); 430 addInt(flags); 431 return OpenGLRenderer::save(flags); 432} 433 434int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom, 435 int alpha, int flags) { 436 addOp(DisplayList::SaveLayerAlpha); 437 addBounds(left, top, right, bottom); 438 addInt(alpha); 439 addInt(flags); 440 return OpenGLRenderer::save(flags); 441} 442 443void DisplayListRenderer::translate(float dx, float dy) { 444 addOp(DisplayList::Translate); 445 addPoint(dx, dy); 446 OpenGLRenderer::translate(dx, dy); 447} 448 449void DisplayListRenderer::rotate(float degrees) { 450 addOp(DisplayList::Rotate); 451 addFloat(degrees); 452 OpenGLRenderer::rotate(degrees); 453} 454 455void DisplayListRenderer::scale(float sx, float sy) { 456 addOp(DisplayList::Scale); 457 addPoint(sx, sy); 458 OpenGLRenderer::scale(sx, sy); 459} 460 461void DisplayListRenderer::setMatrix(SkMatrix* matrix) { 462 addOp(DisplayList::SetMatrix); 463 addMatrix(matrix); 464 OpenGLRenderer::setMatrix(matrix); 465} 466 467void DisplayListRenderer::concatMatrix(SkMatrix* matrix) { 468 addOp(DisplayList::ConcatMatrix); 469 addMatrix(matrix); 470 OpenGLRenderer::concatMatrix(matrix); 471} 472 473bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom, 474 SkRegion::Op op) { 475 addOp(DisplayList::ClipRect); 476 addBounds(left, top, right, bottom); 477 addInt(op); 478 return OpenGLRenderer::clipRect(left, top, right, bottom, op); 479} 480 481void DisplayListRenderer::drawDisplayList(DisplayList* displayList) { 482 addOp(DisplayList::DrawDisplayList); 483 addDisplayList(displayList); 484} 485 486void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, 487 SkPaint* paint) { 488 addOp(DisplayList::DrawBitmap); 489 addBitmap(bitmap); 490 addPoint(left, top); 491 addPaint(paint); 492} 493 494void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, 495 SkPaint* paint) { 496 addOp(DisplayList::DrawBitmapMatrix); 497 addBitmap(bitmap); 498 addMatrix(matrix); 499 addPaint(paint); 500} 501 502void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, 503 float srcRight, float srcBottom, float dstLeft, float dstTop, 504 float dstRight, float dstBottom, SkPaint* paint) { 505 addOp(DisplayList::DrawBitmapRect); 506 addBitmap(bitmap); 507 addBounds(srcLeft, srcTop, srcRight, srcBottom); 508 addBounds(dstLeft, dstTop, dstRight, dstBottom); 509 addPaint(paint); 510} 511 512void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, 513 const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, 514 float left, float top, float right, float bottom, SkPaint* paint) { 515 addOp(DisplayList::DrawPatch); 516 addBitmap(bitmap); 517 addInts(xDivs, width); 518 addInts(yDivs, height); 519 addUInts(colors, numColors); 520 addBounds(left, top, right, bottom); 521 addPaint(paint); 522} 523 524void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { 525 addOp(DisplayList::DrawColor); 526 addInt(color); 527 addInt(mode); 528} 529 530void DisplayListRenderer::drawRect(float left, float top, float right, float bottom, 531 SkPaint* paint) { 532 addOp(DisplayList::DrawRect); 533 addBounds(left, top, right, bottom); 534 addPaint(paint); 535} 536 537void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) { 538 addOp(DisplayList::DrawPath); 539 addPath(path); 540 addPaint(paint); 541} 542 543void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) { 544 addOp(DisplayList::DrawLines); 545 addFloats(points, count); 546 addPaint(paint); 547} 548 549void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, 550 float x, float y, SkPaint* paint) { 551 addOp(DisplayList::DrawText); 552 addText(text, bytesCount); 553 addInt(count); 554 addPoint(x, y); 555 addPaint(paint); 556} 557 558void DisplayListRenderer::resetShader() { 559 addOp(DisplayList::ResetShader); 560} 561 562void DisplayListRenderer::setupShader(SkiaShader* shader) { 563 addOp(DisplayList::SetupShader); 564 addShader(shader); 565} 566 567void DisplayListRenderer::resetColorFilter() { 568 addOp(DisplayList::ResetColorFilter); 569} 570 571void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) { 572 addOp(DisplayList::SetupColorFilter); 573 addColorFilter(filter); 574} 575 576void DisplayListRenderer::resetShadow() { 577 addOp(DisplayList::ResetShadow); 578} 579 580void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) { 581 addOp(DisplayList::SetupShadow); 582 addFloat(radius); 583 addPoint(dx, dy); 584 addInt(color); 585} 586 587}; // namespace uirenderer 588}; // namespace android 589