Caches.cpp revision 087bc0c14bdccf7c258dce0cdef46a69a839b427
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<Layer*> layers; 319 320 { // scope for the lock 321 Mutex::Autolock _l(mGarbageLock); 322 layers = mLayerGarbage; 323 mLayerGarbage.clear(); 324 } 325 326 size_t count = layers.size(); 327 for (size_t i = 0; i < count; i++) { 328 Layer* layer = layers.itemAt(i); 329 delete layer; 330 } 331 layers.clear(); 332} 333 334void Caches::deleteLayerDeferred(Layer* layer) { 335 Mutex::Autolock _l(mGarbageLock); 336 mLayerGarbage.push(layer); 337} 338 339void 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 // fall through 362 case kFlushMode_Layers: 363 layerCache.clear(); 364 renderBufferCache.clear(); 365 break; 366 } 367 368 clearGarbage(); 369} 370 371/////////////////////////////////////////////////////////////////////////////// 372// VBO 373/////////////////////////////////////////////////////////////////////////////// 374 375bool Caches::bindMeshBuffer() { 376 return bindMeshBuffer(meshBuffer); 377} 378 379bool Caches::bindMeshBuffer(const GLuint buffer) { 380 if (mCurrentBuffer != buffer) { 381 glBindBuffer(GL_ARRAY_BUFFER, buffer); 382 mCurrentBuffer = buffer; 383 return true; 384 } 385 return false; 386} 387 388bool Caches::unbindMeshBuffer() { 389 if (mCurrentBuffer) { 390 glBindBuffer(GL_ARRAY_BUFFER, 0); 391 mCurrentBuffer = 0; 392 return true; 393 } 394 return false; 395} 396 397bool Caches::bindIndicesBufferInternal(const GLuint buffer) { 398 if (mCurrentIndicesBuffer != buffer) { 399 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 400 mCurrentIndicesBuffer = buffer; 401 return true; 402 } 403 return false; 404} 405 406bool Caches::bindQuadIndicesBuffer() { 407 if (!mMeshIndices) { 408 uint16_t* regionIndices = new uint16_t[gMaxNumberOfQuads * 6]; 409 for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) { 410 uint16_t quad = i * 4; 411 int index = i * 6; 412 regionIndices[index ] = quad; // top-left 413 regionIndices[index + 1] = quad + 1; // top-right 414 regionIndices[index + 2] = quad + 2; // bottom-left 415 regionIndices[index + 3] = quad + 2; // bottom-left 416 regionIndices[index + 4] = quad + 1; // top-right 417 regionIndices[index + 5] = quad + 3; // bottom-right 418 } 419 420 glGenBuffers(1, &mMeshIndices); 421 bool force = bindIndicesBufferInternal(mMeshIndices); 422 glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t), 423 regionIndices, GL_STATIC_DRAW); 424 425 delete[] regionIndices; 426 return force; 427 } 428 429 return bindIndicesBufferInternal(mMeshIndices); 430} 431 432bool Caches::bindShadowIndicesBuffer() { 433 if (!mShadowStripsIndices) { 434 uint16_t* shadowIndices = new uint16_t[MAX_SHADOW_INDEX_COUNT]; 435 ShadowTessellator::generateShadowIndices(shadowIndices); 436 glGenBuffers(1, &mShadowStripsIndices); 437 bool force = bindIndicesBufferInternal(mShadowStripsIndices); 438 glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t), 439 shadowIndices, GL_STATIC_DRAW); 440 441 delete[] shadowIndices; 442 return force; 443 } 444 445 return bindIndicesBufferInternal(mShadowStripsIndices); 446} 447 448bool Caches::unbindIndicesBuffer() { 449 if (mCurrentIndicesBuffer) { 450 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 451 mCurrentIndicesBuffer = 0; 452 return true; 453 } 454 return false; 455} 456 457/////////////////////////////////////////////////////////////////////////////// 458// PBO 459/////////////////////////////////////////////////////////////////////////////// 460 461bool Caches::bindPixelBuffer(const GLuint buffer) { 462 if (mCurrentPixelBuffer != buffer) { 463 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); 464 mCurrentPixelBuffer = buffer; 465 return true; 466 } 467 return false; 468} 469 470bool Caches::unbindPixelBuffer() { 471 if (mCurrentPixelBuffer) { 472 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 473 mCurrentPixelBuffer = 0; 474 return true; 475 } 476 return false; 477} 478 479/////////////////////////////////////////////////////////////////////////////// 480// Meshes and textures 481/////////////////////////////////////////////////////////////////////////////// 482 483void Caches::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) { 484 if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) { 485 GLuint slot = currentProgram->position; 486 glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices); 487 mCurrentPositionPointer = vertices; 488 mCurrentPositionStride = stride; 489 } 490} 491 492void Caches::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) { 493 if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) { 494 GLuint slot = currentProgram->texCoords; 495 glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices); 496 mCurrentTexCoordsPointer = vertices; 497 mCurrentTexCoordsStride = stride; 498 } 499} 500 501void Caches::resetVertexPointers() { 502 mCurrentPositionPointer = this; 503 mCurrentTexCoordsPointer = this; 504} 505 506void Caches::resetTexCoordsVertexPointer() { 507 mCurrentTexCoordsPointer = this; 508} 509 510void Caches::enableTexCoordsVertexArray() { 511 if (!mTexCoordsArrayEnabled) { 512 glEnableVertexAttribArray(Program::kBindingTexCoords); 513 mCurrentTexCoordsPointer = this; 514 mTexCoordsArrayEnabled = true; 515 } 516} 517 518void Caches::disableTexCoordsVertexArray() { 519 if (mTexCoordsArrayEnabled) { 520 glDisableVertexAttribArray(Program::kBindingTexCoords); 521 mTexCoordsArrayEnabled = false; 522 } 523} 524 525void Caches::activeTexture(GLuint textureUnit) { 526 if (mTextureUnit != textureUnit) { 527 glActiveTexture(gTextureUnits[textureUnit]); 528 mTextureUnit = textureUnit; 529 } 530} 531 532void Caches::resetActiveTexture() { 533 mTextureUnit = -1; 534} 535 536void Caches::bindTexture(GLuint texture) { 537 if (mBoundTextures[mTextureUnit] != texture) { 538 glBindTexture(GL_TEXTURE_2D, texture); 539 mBoundTextures[mTextureUnit] = texture; 540 } 541} 542 543void Caches::bindTexture(GLenum target, GLuint texture) { 544 if (mBoundTextures[mTextureUnit] != texture) { 545 glBindTexture(target, texture); 546 mBoundTextures[mTextureUnit] = texture; 547 } 548} 549 550void Caches::deleteTexture(GLuint texture) { 551 // When glDeleteTextures() is called on a currently bound texture, 552 // OpenGL ES specifies that the texture is then considered unbound 553 // Consider the following series of calls: 554 // 555 // glGenTextures -> creates texture name 2 556 // glBindTexture(2) 557 // glDeleteTextures(2) -> 2 is now unbound 558 // glGenTextures -> can return 2 again 559 // 560 // If we don't call glBindTexture(2) after the second glGenTextures 561 // call, any texture operation will be performed on the default 562 // texture (name=0) 563 564 for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) { 565 if (mBoundTextures[i] == texture) { 566 mBoundTextures[i] = 0; 567 } 568 } 569 glDeleteTextures(1, &texture); 570} 571 572void Caches::resetBoundTextures() { 573 memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint)); 574} 575 576/////////////////////////////////////////////////////////////////////////////// 577// Scissor 578/////////////////////////////////////////////////////////////////////////////// 579 580bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) { 581 if (scissorEnabled && (x != mScissorX || y != mScissorY || 582 width != mScissorWidth || height != mScissorHeight)) { 583 584 if (x < 0) { 585 width += x; 586 x = 0; 587 } 588 if (y < 0) { 589 height += y; 590 y = 0; 591 } 592 if (width < 0) { 593 width = 0; 594 } 595 if (height < 0) { 596 height = 0; 597 } 598 glScissor(x, y, width, height); 599 600 mScissorX = x; 601 mScissorY = y; 602 mScissorWidth = width; 603 mScissorHeight = height; 604 605 return true; 606 } 607 return false; 608} 609 610bool Caches::enableScissor() { 611 if (!scissorEnabled) { 612 glEnable(GL_SCISSOR_TEST); 613 scissorEnabled = true; 614 resetScissor(); 615 return true; 616 } 617 return false; 618} 619 620bool Caches::disableScissor() { 621 if (scissorEnabled) { 622 glDisable(GL_SCISSOR_TEST); 623 scissorEnabled = false; 624 return true; 625 } 626 return false; 627} 628 629void Caches::setScissorEnabled(bool enabled) { 630 if (scissorEnabled != enabled) { 631 if (enabled) glEnable(GL_SCISSOR_TEST); 632 else glDisable(GL_SCISSOR_TEST); 633 scissorEnabled = enabled; 634 } 635} 636 637void Caches::resetScissor() { 638 mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0; 639} 640 641/////////////////////////////////////////////////////////////////////////////// 642// Tiling 643/////////////////////////////////////////////////////////////////////////////// 644 645void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard) { 646 if (mExtensions.hasTiledRendering() && !debugOverdraw) { 647 glStartTilingQCOM(x, y, width, height, (discard ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM)); 648 } 649} 650 651void Caches::endTiling() { 652 if (mExtensions.hasTiledRendering() && !debugOverdraw) { 653 glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); 654 } 655} 656 657bool Caches::hasRegisteredFunctors() { 658 return mFunctorsCount > 0; 659} 660 661void Caches::registerFunctors(uint32_t functorCount) { 662 mFunctorsCount += functorCount; 663} 664 665void Caches::unregisterFunctors(uint32_t functorCount) { 666 if (functorCount > mFunctorsCount) { 667 mFunctorsCount = 0; 668 } else { 669 mFunctorsCount -= functorCount; 670 } 671} 672 673/////////////////////////////////////////////////////////////////////////////// 674// Regions 675/////////////////////////////////////////////////////////////////////////////// 676 677TextureVertex* Caches::getRegionMesh() { 678 // Create the mesh, 2 triangles and 4 vertices per rectangle in the region 679 if (!mRegionMesh) { 680 mRegionMesh = new TextureVertex[gMaxNumberOfQuads * 4]; 681 } 682 683 return mRegionMesh; 684} 685 686/////////////////////////////////////////////////////////////////////////////// 687// Temporary Properties 688/////////////////////////////////////////////////////////////////////////////// 689 690void Caches::initTempProperties() { 691 propertyAmbientShadowStrength = 25; 692 propertySpotShadowStrength = 25; 693 694 propertyLightPosXScale = 0.5f; 695 propertyLightPosYScale = 0.0f; 696 propertyLightPosZScale = 1.0f; 697} 698 699void Caches::setTempProperty(const char* name, const char* value) { 700 ALOGD("setting property %s to %s", name, value); 701 if (!strcmp(name, "ambientShadowStrength")) { 702 propertyAmbientShadowStrength = atoi(value); 703 ALOGD("ambient shadow strength = 0x%x out of 0xff", propertyAmbientShadowStrength); 704 return; 705 } else if (!strcmp(name, "spotShadowStrength")) { 706 propertySpotShadowStrength = atoi(value); 707 ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength); 708 return; 709 } else if (!strcmp(name, "lightPosXScale")) { 710 propertyLightPosXScale = fmin(fmax(atof(value), 0.0), 1.0); 711 ALOGD("lightPos X Scale = %.2f", propertyLightPosXScale); 712 return; 713 } else if (!strcmp(name, "lightPosYScale")) { 714 propertyLightPosYScale = fmin(fmax(atof(value), 0.0), 1.0); 715 ALOGD("lightPos Y Scale = %.2f", propertyLightPosXScale); 716 return; 717 } else if (!strcmp(name, "lightPosZScale")) { 718 propertyLightPosZScale = fmin(fmax(atof(value), 0.0), 1.0); 719 ALOGD("lightPos Z Scale = %.2f", propertyLightPosXScale); 720 return; 721 } 722 ALOGD(" failed"); 723} 724 725}; // namespace uirenderer 726}; // namespace android 727