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