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