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