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