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 <utils/Log.h> 20 #include <utils/String8.h> 21 22 #include "Caches.h" 23 #include "DisplayListRenderer.h" 24 #include "Properties.h" 25 #include "LayerRenderer.h" 26 #include "ShadowTessellator.h" 27 #include "RenderState.h" 28 29 namespace android { 30 31 #ifdef USE_OPENGL_RENDERER 32 using namespace uirenderer; 33 ANDROID_SINGLETON_STATIC_INSTANCE(Caches); 34 #endif 35 36 namespace uirenderer { 37 38 /////////////////////////////////////////////////////////////////////////////// 39 // Macros 40 /////////////////////////////////////////////////////////////////////////////// 41 42 #if DEBUG_CACHE_FLUSH 43 #define FLUSH_LOGD(...) ALOGD(__VA_ARGS__) 44 #else 45 #define FLUSH_LOGD(...) 46 #endif 47 48 /////////////////////////////////////////////////////////////////////////////// 49 // Constructors/destructor 50 /////////////////////////////////////////////////////////////////////////////// 51 52 Caches::Caches(): Singleton<Caches>(), 53 mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(NULL) { 54 init(); 55 initFont(); 56 initConstraints(); 57 initProperties(); 58 initStaticProperties(); 59 initExtensions(); 60 initTempProperties(); 61 62 mDebugLevel = readDebugLevel(); 63 ALOGD("Enabling debug mode %d", mDebugLevel); 64 } 65 66 bool Caches::init() { 67 if (mInitialized) return false; 68 69 ATRACE_NAME("Caches::init"); 70 71 glGenBuffers(1, &meshBuffer); 72 glBindBuffer(GL_ARRAY_BUFFER, meshBuffer); 73 glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW); 74 75 mCurrentBuffer = meshBuffer; 76 mCurrentIndicesBuffer = 0; 77 mCurrentPositionPointer = this; 78 mCurrentPositionStride = 0; 79 mCurrentTexCoordsPointer = this; 80 mCurrentPixelBuffer = 0; 81 82 mTexCoordsArrayEnabled = false; 83 84 glDisable(GL_SCISSOR_TEST); 85 scissorEnabled = false; 86 mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0; 87 88 glActiveTexture(gTextureUnits[0]); 89 mTextureUnit = 0; 90 91 mRegionMesh = NULL; 92 mMeshIndices = 0; 93 mShadowStripsIndices = 0; 94 blend = false; 95 lastSrcMode = GL_ZERO; 96 lastDstMode = GL_ZERO; 97 currentProgram = NULL; 98 99 mFunctorsCount = 0; 100 101 debugLayersUpdates = false; 102 debugOverdraw = false; 103 debugStencilClip = kStencilHide; 104 105 patchCache.init(*this); 106 107 mInitialized = true; 108 109 resetBoundTextures(); 110 111 return true; 112 } 113 114 void Caches::initFont() { 115 fontRenderer = GammaFontRenderer::createRenderer(); 116 } 117 118 void Caches::initExtensions() { 119 if (mExtensions.hasDebugMarker()) { 120 eventMark = glInsertEventMarkerEXT; 121 122 startMark = glPushGroupMarkerEXT; 123 endMark = glPopGroupMarkerEXT; 124 } else { 125 eventMark = eventMarkNull; 126 startMark = startMarkNull; 127 endMark = endMarkNull; 128 } 129 130 if (mExtensions.hasDebugLabel() && (drawDeferDisabled || drawReorderDisabled)) { 131 setLabel = glLabelObjectEXT; 132 getLabel = glGetObjectLabelEXT; 133 } else { 134 setLabel = setLabelNull; 135 getLabel = getLabelNull; 136 } 137 } 138 139 void Caches::initConstraints() { 140 GLint maxTextureUnits; 141 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 142 if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) { 143 ALOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT); 144 } 145 146 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 147 } 148 149 void Caches::initStaticProperties() { 150 gpuPixelBuffersEnabled = false; 151 152 // OpenGL ES 3.0+ specific features 153 if (mExtensions.hasPixelBufferObjects()) { 154 char property[PROPERTY_VALUE_MAX]; 155 if (property_get(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, property, "true") > 0) { 156 gpuPixelBuffersEnabled = !strcmp(property, "true"); 157 } 158 } 159 } 160 161 bool Caches::initProperties() { 162 bool prevDebugLayersUpdates = debugLayersUpdates; 163 bool prevDebugOverdraw = debugOverdraw; 164 StencilClipDebug prevDebugStencilClip = debugStencilClip; 165 166 char property[PROPERTY_VALUE_MAX]; 167 if (property_get(PROPERTY_DEBUG_LAYERS_UPDATES, property, NULL) > 0) { 168 INIT_LOGD(" Layers updates debug enabled: %s", property); 169 debugLayersUpdates = !strcmp(property, "true"); 170 } else { 171 debugLayersUpdates = false; 172 } 173 174 debugOverdraw = false; 175 if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) { 176 INIT_LOGD(" Overdraw debug enabled: %s", property); 177 if (!strcmp(property, "show")) { 178 debugOverdraw = true; 179 mOverdrawDebugColorSet = kColorSet_Default; 180 } else if (!strcmp(property, "show_deuteranomaly")) { 181 debugOverdraw = true; 182 mOverdrawDebugColorSet = kColorSet_Deuteranomaly; 183 } 184 } 185 186 // See Properties.h for valid values 187 if (property_get(PROPERTY_DEBUG_STENCIL_CLIP, property, NULL) > 0) { 188 INIT_LOGD(" Stencil clip debug enabled: %s", property); 189 if (!strcmp(property, "hide")) { 190 debugStencilClip = kStencilHide; 191 } else if (!strcmp(property, "highlight")) { 192 debugStencilClip = kStencilShowHighlight; 193 } else if (!strcmp(property, "region")) { 194 debugStencilClip = kStencilShowRegion; 195 } 196 } else { 197 debugStencilClip = kStencilHide; 198 } 199 200 if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) { 201 drawDeferDisabled = !strcasecmp(property, "true"); 202 INIT_LOGD(" Draw defer %s", drawDeferDisabled ? "disabled" : "enabled"); 203 } else { 204 drawDeferDisabled = false; 205 INIT_LOGD(" Draw defer enabled"); 206 } 207 208 if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) { 209 drawReorderDisabled = !strcasecmp(property, "true"); 210 INIT_LOGD(" Draw reorder %s", drawReorderDisabled ? "disabled" : "enabled"); 211 } else { 212 drawReorderDisabled = false; 213 INIT_LOGD(" Draw reorder enabled"); 214 } 215 216 return (prevDebugLayersUpdates != debugLayersUpdates) || 217 (prevDebugOverdraw != debugOverdraw) || 218 (prevDebugStencilClip != debugStencilClip); 219 } 220 221 void Caches::terminate() { 222 if (!mInitialized) return; 223 224 glDeleteBuffers(1, &meshBuffer); 225 mCurrentBuffer = 0; 226 227 glDeleteBuffers(1, &mMeshIndices); 228 delete[] mRegionMesh; 229 mMeshIndices = 0; 230 mRegionMesh = NULL; 231 232 glDeleteBuffers(1, &mShadowStripsIndices); 233 mShadowStripsIndices = 0; 234 235 fboCache.clear(); 236 237 programCache.clear(); 238 currentProgram = NULL; 239 240 patchCache.clear(); 241 242 clearGarbage(); 243 244 mInitialized = false; 245 } 246 247 /////////////////////////////////////////////////////////////////////////////// 248 // Debug 249 /////////////////////////////////////////////////////////////////////////////// 250 251 uint32_t Caches::getOverdrawColor(uint32_t amount) const { 252 static uint32_t sOverdrawColors[2][4] = { 253 { 0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000 }, 254 { 0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000 } 255 }; 256 if (amount < 1) amount = 1; 257 if (amount > 4) amount = 4; 258 return sOverdrawColors[mOverdrawDebugColorSet][amount - 1]; 259 } 260 261 void Caches::dumpMemoryUsage() { 262 String8 stringLog; 263 dumpMemoryUsage(stringLog); 264 ALOGD("%s", stringLog.string()); 265 } 266 267 void Caches::dumpMemoryUsage(String8 &log) { 268 uint32_t total = 0; 269 log.appendFormat("Current memory usage / total memory usage (bytes):\n"); 270 log.appendFormat(" TextureCache %8d / %8d\n", 271 textureCache.getSize(), textureCache.getMaxSize()); 272 log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n", 273 layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount()); 274 if (mRenderState) { 275 int memused = 0; 276 for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin(); 277 it != mRenderState->mActiveLayers.end(); it++) { 278 const Layer* layer = *it; 279 log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n", 280 layer->getWidth(), layer->getHeight(), 281 layer->isTextureLayer(), layer->getTexture(), 282 layer->getFbo(), layer->getStrongCount()); 283 memused += layer->getWidth() * layer->getHeight() * 4; 284 } 285 log.appendFormat(" Layers total %8d (numLayers = %zu)\n", 286 memused, mRenderState->mActiveLayers.size()); 287 total += memused; 288 } 289 log.appendFormat(" RenderBufferCache %8d / %8d\n", 290 renderBufferCache.getSize(), renderBufferCache.getMaxSize()); 291 log.appendFormat(" GradientCache %8d / %8d\n", 292 gradientCache.getSize(), gradientCache.getMaxSize()); 293 log.appendFormat(" PathCache %8d / %8d\n", 294 pathCache.getSize(), pathCache.getMaxSize()); 295 log.appendFormat(" TessellationCache %8d / %8d\n", 296 tessellationCache.getSize(), tessellationCache.getMaxSize()); 297 log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(), 298 dropShadowCache.getMaxSize()); 299 log.appendFormat(" PatchCache %8d / %8d\n", 300 patchCache.getSize(), patchCache.getMaxSize()); 301 for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) { 302 const uint32_t sizeA8 = fontRenderer->getFontRendererSize(i, GL_ALPHA); 303 const uint32_t sizeRGBA = fontRenderer->getFontRendererSize(i, GL_RGBA); 304 log.appendFormat(" FontRenderer %d A8 %8d / %8d\n", i, sizeA8, sizeA8); 305 log.appendFormat(" FontRenderer %d RGBA %8d / %8d\n", i, sizeRGBA, sizeRGBA); 306 log.appendFormat(" FontRenderer %d total %8d / %8d\n", i, sizeA8 + sizeRGBA, 307 sizeA8 + sizeRGBA); 308 } 309 log.appendFormat("Other:\n"); 310 log.appendFormat(" FboCache %8d / %8d\n", 311 fboCache.getSize(), fboCache.getMaxSize()); 312 313 total += textureCache.getSize(); 314 total += renderBufferCache.getSize(); 315 total += gradientCache.getSize(); 316 total += pathCache.getSize(); 317 total += tessellationCache.getSize(); 318 total += dropShadowCache.getSize(); 319 total += patchCache.getSize(); 320 for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) { 321 total += fontRenderer->getFontRendererSize(i, GL_ALPHA); 322 total += fontRenderer->getFontRendererSize(i, GL_RGBA); 323 } 324 325 log.appendFormat("Total memory usage:\n"); 326 log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f); 327 } 328 329 /////////////////////////////////////////////////////////////////////////////// 330 // Memory management 331 /////////////////////////////////////////////////////////////////////////////// 332 333 void Caches::clearGarbage() { 334 textureCache.clearGarbage(); 335 pathCache.clearGarbage(); 336 patchCache.clearGarbage(); 337 } 338 339 void Caches::flush(FlushMode mode) { 340 FLUSH_LOGD("Flushing caches (mode %d)", mode); 341 342 // We must stop tasks before clearing caches 343 if (mode > kFlushMode_Layers) { 344 tasks.stop(); 345 } 346 347 switch (mode) { 348 case kFlushMode_Full: 349 textureCache.clear(); 350 patchCache.clear(); 351 dropShadowCache.clear(); 352 gradientCache.clear(); 353 fontRenderer->clear(); 354 fboCache.clear(); 355 dither.clear(); 356 // fall through 357 case kFlushMode_Moderate: 358 fontRenderer->flush(); 359 textureCache.flush(); 360 pathCache.clear(); 361 tessellationCache.clear(); 362 // fall through 363 case kFlushMode_Layers: 364 layerCache.clear(); 365 renderBufferCache.clear(); 366 break; 367 } 368 369 clearGarbage(); 370 glFinish(); 371 } 372 373 /////////////////////////////////////////////////////////////////////////////// 374 // VBO 375 /////////////////////////////////////////////////////////////////////////////// 376 377 bool Caches::bindMeshBuffer() { 378 return bindMeshBuffer(meshBuffer); 379 } 380 381 bool Caches::bindMeshBuffer(const GLuint buffer) { 382 if (mCurrentBuffer != buffer) { 383 glBindBuffer(GL_ARRAY_BUFFER, buffer); 384 mCurrentBuffer = buffer; 385 return true; 386 } 387 return false; 388 } 389 390 bool Caches::unbindMeshBuffer() { 391 if (mCurrentBuffer) { 392 glBindBuffer(GL_ARRAY_BUFFER, 0); 393 mCurrentBuffer = 0; 394 return true; 395 } 396 return false; 397 } 398 399 bool Caches::bindIndicesBufferInternal(const GLuint buffer) { 400 if (mCurrentIndicesBuffer != buffer) { 401 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 402 mCurrentIndicesBuffer = buffer; 403 return true; 404 } 405 return false; 406 } 407 408 bool Caches::bindQuadIndicesBuffer() { 409 if (!mMeshIndices) { 410 uint16_t* regionIndices = new uint16_t[gMaxNumberOfQuads * 6]; 411 for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) { 412 uint16_t quad = i * 4; 413 int index = i * 6; 414 regionIndices[index ] = quad; // top-left 415 regionIndices[index + 1] = quad + 1; // top-right 416 regionIndices[index + 2] = quad + 2; // bottom-left 417 regionIndices[index + 3] = quad + 2; // bottom-left 418 regionIndices[index + 4] = quad + 1; // top-right 419 regionIndices[index + 5] = quad + 3; // bottom-right 420 } 421 422 glGenBuffers(1, &mMeshIndices); 423 bool force = bindIndicesBufferInternal(mMeshIndices); 424 glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t), 425 regionIndices, GL_STATIC_DRAW); 426 427 delete[] regionIndices; 428 return force; 429 } 430 431 return bindIndicesBufferInternal(mMeshIndices); 432 } 433 434 bool Caches::bindShadowIndicesBuffer() { 435 if (!mShadowStripsIndices) { 436 uint16_t* shadowIndices = new uint16_t[MAX_SHADOW_INDEX_COUNT]; 437 ShadowTessellator::generateShadowIndices(shadowIndices); 438 glGenBuffers(1, &mShadowStripsIndices); 439 bool force = bindIndicesBufferInternal(mShadowStripsIndices); 440 glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t), 441 shadowIndices, GL_STATIC_DRAW); 442 443 delete[] shadowIndices; 444 return force; 445 } 446 447 return bindIndicesBufferInternal(mShadowStripsIndices); 448 } 449 450 bool Caches::unbindIndicesBuffer() { 451 if (mCurrentIndicesBuffer) { 452 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 453 mCurrentIndicesBuffer = 0; 454 return true; 455 } 456 return false; 457 } 458 459 /////////////////////////////////////////////////////////////////////////////// 460 // PBO 461 /////////////////////////////////////////////////////////////////////////////// 462 463 bool Caches::bindPixelBuffer(const GLuint buffer) { 464 if (mCurrentPixelBuffer != buffer) { 465 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); 466 mCurrentPixelBuffer = buffer; 467 return true; 468 } 469 return false; 470 } 471 472 bool Caches::unbindPixelBuffer() { 473 if (mCurrentPixelBuffer) { 474 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 475 mCurrentPixelBuffer = 0; 476 return true; 477 } 478 return false; 479 } 480 481 /////////////////////////////////////////////////////////////////////////////// 482 // Meshes and textures 483 /////////////////////////////////////////////////////////////////////////////// 484 485 void Caches::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) { 486 if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) { 487 GLuint slot = currentProgram->position; 488 glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices); 489 mCurrentPositionPointer = vertices; 490 mCurrentPositionStride = stride; 491 } 492 } 493 494 void Caches::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) { 495 if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) { 496 GLuint slot = currentProgram->texCoords; 497 glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices); 498 mCurrentTexCoordsPointer = vertices; 499 mCurrentTexCoordsStride = stride; 500 } 501 } 502 503 void Caches::resetVertexPointers() { 504 mCurrentPositionPointer = this; 505 mCurrentTexCoordsPointer = this; 506 } 507 508 void Caches::resetTexCoordsVertexPointer() { 509 mCurrentTexCoordsPointer = this; 510 } 511 512 void Caches::enableTexCoordsVertexArray() { 513 if (!mTexCoordsArrayEnabled) { 514 glEnableVertexAttribArray(Program::kBindingTexCoords); 515 mCurrentTexCoordsPointer = this; 516 mTexCoordsArrayEnabled = true; 517 } 518 } 519 520 void Caches::disableTexCoordsVertexArray() { 521 if (mTexCoordsArrayEnabled) { 522 glDisableVertexAttribArray(Program::kBindingTexCoords); 523 mTexCoordsArrayEnabled = false; 524 } 525 } 526 527 void Caches::activeTexture(GLuint textureUnit) { 528 if (mTextureUnit != textureUnit) { 529 glActiveTexture(gTextureUnits[textureUnit]); 530 mTextureUnit = textureUnit; 531 } 532 } 533 534 void Caches::resetActiveTexture() { 535 mTextureUnit = -1; 536 } 537 538 void Caches::bindTexture(GLuint texture) { 539 if (mBoundTextures[mTextureUnit] != texture) { 540 glBindTexture(GL_TEXTURE_2D, texture); 541 mBoundTextures[mTextureUnit] = texture; 542 } 543 } 544 545 void Caches::bindTexture(GLenum target, GLuint texture) { 546 if (target == GL_TEXTURE_2D) { 547 bindTexture(texture); 548 } else { 549 // GLConsumer directly calls glBindTexture() with 550 // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target 551 // since the cached state could be stale 552 glBindTexture(target, texture); 553 } 554 } 555 556 void Caches::deleteTexture(GLuint texture) { 557 // When glDeleteTextures() is called on a currently bound texture, 558 // OpenGL ES specifies that the texture is then considered unbound 559 // Consider the following series of calls: 560 // 561 // glGenTextures -> creates texture name 2 562 // glBindTexture(2) 563 // glDeleteTextures(2) -> 2 is now unbound 564 // glGenTextures -> can return 2 again 565 // 566 // If we don't call glBindTexture(2) after the second glGenTextures 567 // call, any texture operation will be performed on the default 568 // texture (name=0) 569 570 unbindTexture(texture); 571 572 glDeleteTextures(1, &texture); 573 } 574 575 void Caches::resetBoundTextures() { 576 memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint)); 577 } 578 579 void Caches::unbindTexture(GLuint texture) { 580 for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) { 581 if (mBoundTextures[i] == texture) { 582 mBoundTextures[i] = 0; 583 } 584 } 585 } 586 587 /////////////////////////////////////////////////////////////////////////////// 588 // Scissor 589 /////////////////////////////////////////////////////////////////////////////// 590 591 bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) { 592 if (scissorEnabled && (x != mScissorX || y != mScissorY || 593 width != mScissorWidth || height != mScissorHeight)) { 594 595 if (x < 0) { 596 width += x; 597 x = 0; 598 } 599 if (y < 0) { 600 height += y; 601 y = 0; 602 } 603 if (width < 0) { 604 width = 0; 605 } 606 if (height < 0) { 607 height = 0; 608 } 609 glScissor(x, y, width, height); 610 611 mScissorX = x; 612 mScissorY = y; 613 mScissorWidth = width; 614 mScissorHeight = height; 615 616 return true; 617 } 618 return false; 619 } 620 621 bool Caches::enableScissor() { 622 if (!scissorEnabled) { 623 glEnable(GL_SCISSOR_TEST); 624 scissorEnabled = true; 625 resetScissor(); 626 return true; 627 } 628 return false; 629 } 630 631 bool Caches::disableScissor() { 632 if (scissorEnabled) { 633 glDisable(GL_SCISSOR_TEST); 634 scissorEnabled = false; 635 return true; 636 } 637 return false; 638 } 639 640 void Caches::setScissorEnabled(bool enabled) { 641 if (scissorEnabled != enabled) { 642 if (enabled) glEnable(GL_SCISSOR_TEST); 643 else glDisable(GL_SCISSOR_TEST); 644 scissorEnabled = enabled; 645 } 646 } 647 648 void Caches::resetScissor() { 649 mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0; 650 } 651 652 /////////////////////////////////////////////////////////////////////////////// 653 // Tiling 654 /////////////////////////////////////////////////////////////////////////////// 655 656 void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard) { 657 if (mExtensions.hasTiledRendering() && !debugOverdraw) { 658 glStartTilingQCOM(x, y, width, height, (discard ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM)); 659 } 660 } 661 662 void Caches::endTiling() { 663 if (mExtensions.hasTiledRendering() && !debugOverdraw) { 664 glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); 665 } 666 } 667 668 bool Caches::hasRegisteredFunctors() { 669 return mFunctorsCount > 0; 670 } 671 672 void Caches::registerFunctors(uint32_t functorCount) { 673 mFunctorsCount += functorCount; 674 } 675 676 void Caches::unregisterFunctors(uint32_t functorCount) { 677 if (functorCount > mFunctorsCount) { 678 mFunctorsCount = 0; 679 } else { 680 mFunctorsCount -= functorCount; 681 } 682 } 683 684 /////////////////////////////////////////////////////////////////////////////// 685 // Regions 686 /////////////////////////////////////////////////////////////////////////////// 687 688 TextureVertex* Caches::getRegionMesh() { 689 // Create the mesh, 2 triangles and 4 vertices per rectangle in the region 690 if (!mRegionMesh) { 691 mRegionMesh = new TextureVertex[gMaxNumberOfQuads * 4]; 692 } 693 694 return mRegionMesh; 695 } 696 697 /////////////////////////////////////////////////////////////////////////////// 698 // Temporary Properties 699 /////////////////////////////////////////////////////////////////////////////// 700 701 void Caches::initTempProperties() { 702 propertyLightDiameter = -1.0f; 703 propertyLightPosY = -1.0f; 704 propertyLightPosZ = -1.0f; 705 propertyAmbientRatio = -1.0f; 706 propertyAmbientShadowStrength = -1; 707 propertySpotShadowStrength = -1; 708 } 709 710 void Caches::setTempProperty(const char* name, const char* value) { 711 ALOGD("setting property %s to %s", name, value); 712 if (!strcmp(name, "ambientRatio")) { 713 propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0); 714 ALOGD("ambientRatio = %.2f", propertyAmbientRatio); 715 return; 716 } else if (!strcmp(name, "lightDiameter")) { 717 propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0); 718 ALOGD("lightDiameter = %.2f", propertyLightDiameter); 719 return; 720 } else if (!strcmp(name, "lightPosY")) { 721 propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0); 722 ALOGD("lightPos Y = %.2f", propertyLightPosY); 723 return; 724 } else if (!strcmp(name, "lightPosZ")) { 725 propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0); 726 ALOGD("lightPos Z = %.2f", propertyLightPosZ); 727 return; 728 } else if (!strcmp(name, "ambientShadowStrength")) { 729 propertyAmbientShadowStrength = atoi(value); 730 ALOGD("ambient shadow strength = 0x%x out of 0xff", propertyAmbientShadowStrength); 731 return; 732 } else if (!strcmp(name, "spotShadowStrength")) { 733 propertySpotShadowStrength = atoi(value); 734 ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength); 735 return; 736 } 737 ALOGD(" failed"); 738 } 739 740 }; // namespace uirenderer 741 }; // namespace android 742