OpenGLRenderer.cpp revision 1f8c9602eeff0a35f8af70bd3fdcd770f0127775
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 <stdlib.h> 20#include <stdint.h> 21#include <sys/types.h> 22 23#include <SkCanvas.h> 24#include <SkTypeface.h> 25 26#include <cutils/properties.h> 27#include <utils/Log.h> 28 29#include "OpenGLRenderer.h" 30#include "Properties.h" 31 32namespace android { 33namespace uirenderer { 34 35/////////////////////////////////////////////////////////////////////////////// 36// Defines 37/////////////////////////////////////////////////////////////////////////////// 38 39#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f 40#define DEFAULT_LAYER_CACHE_SIZE 6.0f 41#define DEFAULT_PATH_CACHE_SIZE 6.0f 42#define DEFAULT_PATCH_CACHE_SIZE 100 43#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f 44#define DEFAULT_DROP_SHADOW_CACHE_SIZE 1.0f 45 46#define REQUIRED_TEXTURE_UNITS_COUNT 3 47 48// Converts a number of mega-bytes into bytes 49#define MB(s) s * 1024 * 1024 50 51// Generates simple and textured vertices 52#define FV(x, y, u, v) { { x, y }, { u, v } } 53 54/////////////////////////////////////////////////////////////////////////////// 55// Globals 56/////////////////////////////////////////////////////////////////////////////// 57 58// This array is never used directly but used as a memcpy source in the 59// OpenGLRenderer constructor 60static const TextureVertex gMeshVertices[] = { 61 FV(0.0f, 0.0f, 0.0f, 0.0f), 62 FV(1.0f, 0.0f, 1.0f, 0.0f), 63 FV(0.0f, 1.0f, 0.0f, 1.0f), 64 FV(1.0f, 1.0f, 1.0f, 1.0f) 65}; 66static const GLsizei gMeshStride = sizeof(TextureVertex); 67static const GLsizei gMeshCount = 4; 68 69/** 70 * Structure mapping Skia xfermodes to OpenGL blending factors. 71 */ 72struct Blender { 73 SkXfermode::Mode mode; 74 GLenum src; 75 GLenum dst; 76}; // struct Blender 77 78// In this array, the index of each Blender equals the value of the first 79// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] 80static const Blender gBlends[] = { 81 { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, 82 { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, 83 { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, 84 { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 85 { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 86 { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO }, 87 { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 88 { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 89 { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 90 { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 91 { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 92 { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA } 93}; 94 95static const GLenum gTextureUnits[] = { 96 GL_TEXTURE0, 97 GL_TEXTURE1, 98 GL_TEXTURE2 99}; 100 101/////////////////////////////////////////////////////////////////////////////// 102// Constructors/destructor 103/////////////////////////////////////////////////////////////////////////////// 104 105OpenGLRenderer::OpenGLRenderer(): 106 mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO), 107 mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)), 108 mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)), 109 mGradientCache(MB(DEFAULT_GRADIENT_CACHE_SIZE)), 110 mPathCache(MB(DEFAULT_PATH_CACHE_SIZE)), 111 mPatchCache(DEFAULT_PATCH_CACHE_SIZE), 112 mDropShadowCache(MB(DEFAULT_DROP_SHADOW_CACHE_SIZE)) { 113 LOGD("Create OpenGLRenderer"); 114 115 char property[PROPERTY_VALUE_MAX]; 116 if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { 117 LOGD(" Setting texture cache size to %sMB", property); 118 mTextureCache.setMaxSize(MB(atof(property))); 119 } else { 120 LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); 121 } 122 123 if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) { 124 LOGD(" Setting layer cache size to %sMB", property); 125 mLayerCache.setMaxSize(MB(atof(property))); 126 } else { 127 LOGD(" Using default layer cache size of %.2fMB", DEFAULT_LAYER_CACHE_SIZE); 128 } 129 130 if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) { 131 LOGD(" Setting gradient cache size to %sMB", property); 132 mGradientCache.setMaxSize(MB(atof(property))); 133 } else { 134 LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); 135 } 136 137 if (property_get(PROPERTY_PATH_CACHE_SIZE, property, NULL) > 0) { 138 LOGD(" Setting path cache size to %sMB", property); 139 mPathCache.setMaxSize(MB(atof(property))); 140 } else { 141 LOGD(" Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE); 142 } 143 144 if (property_get(PROPERTY_DROP_SHADOW_CACHE_SIZE, property, NULL) > 0) { 145 LOGD(" Setting drop shadow cache size to %sMB", property); 146 mDropShadowCache.setMaxSize(MB(atof(property))); 147 } else { 148 LOGD(" Using default drop shadow cache size of %.2fMB", DEFAULT_DROP_SHADOW_CACHE_SIZE); 149 } 150 mDropShadowCache.setFontRenderer(mFontRenderer); 151 152 mCurrentProgram = NULL; 153 mShader = NULL; 154 mColorFilter = NULL; 155 mHasShadow = false; 156 157 memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); 158 159 mFirstSnapshot = new Snapshot; 160 161 GLint maxTextureUnits; 162 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 163 if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) { 164 LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT); 165 } 166} 167 168OpenGLRenderer::~OpenGLRenderer() { 169 LOGD("Destroy OpenGLRenderer"); 170 171 mTextureCache.clear(); 172 mLayerCache.clear(); 173 mGradientCache.clear(); 174 mPathCache.clear(); 175 mPatchCache.clear(); 176 mProgramCache.clear(); 177 mDropShadowCache.clear(); 178} 179 180/////////////////////////////////////////////////////////////////////////////// 181// Setup 182/////////////////////////////////////////////////////////////////////////////// 183 184void OpenGLRenderer::setViewport(int width, int height) { 185 glViewport(0, 0, width, height); 186 mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 187 188 mWidth = width; 189 mHeight = height; 190 mFirstSnapshot->height = height; 191 mFirstSnapshot->viewport.set(0, 0, width, height); 192} 193 194void OpenGLRenderer::prepare() { 195 mSnapshot = new Snapshot(mFirstSnapshot); 196 mSaveCount = 1; 197 198 glDisable(GL_SCISSOR_TEST); 199 200 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 201 glClear(GL_COLOR_BUFFER_BIT); 202 203 glEnable(GL_SCISSOR_TEST); 204 glScissor(0, 0, mWidth, mHeight); 205 206 mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); 207} 208 209/////////////////////////////////////////////////////////////////////////////// 210// State management 211/////////////////////////////////////////////////////////////////////////////// 212 213int OpenGLRenderer::getSaveCount() const { 214 return mSaveCount; 215} 216 217int OpenGLRenderer::save(int flags) { 218 return saveSnapshot(); 219} 220 221void OpenGLRenderer::restore() { 222 if (mSaveCount > 1) { 223 restoreSnapshot(); 224 } 225} 226 227void OpenGLRenderer::restoreToCount(int saveCount) { 228 if (saveCount < 1) saveCount = 1; 229 230 while (mSaveCount > saveCount) { 231 restoreSnapshot(); 232 } 233} 234 235int OpenGLRenderer::saveSnapshot() { 236 mSnapshot = new Snapshot(mSnapshot); 237 return mSaveCount++; 238} 239 240bool OpenGLRenderer::restoreSnapshot() { 241 bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; 242 bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; 243 bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho; 244 245 sp<Snapshot> current = mSnapshot; 246 sp<Snapshot> previous = mSnapshot->previous; 247 248 if (restoreOrtho) { 249 Rect& r = previous->viewport; 250 glViewport(r.left, r.top, r.right, r.bottom); 251 mOrthoMatrix.load(current->orthoMatrix); 252 } 253 254 if (restoreLayer) { 255 composeLayer(current, previous); 256 } 257 258 mSaveCount--; 259 mSnapshot = previous; 260 261 if (restoreClip) { 262 setScissorFromClip(); 263 } 264 265 return restoreClip; 266} 267 268/////////////////////////////////////////////////////////////////////////////// 269// Layers 270/////////////////////////////////////////////////////////////////////////////// 271 272int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, 273 const SkPaint* p, int flags) { 274 int count = saveSnapshot(); 275 276 int alpha = 255; 277 SkXfermode::Mode mode; 278 279 if (p) { 280 alpha = p->getAlpha(); 281 const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 282 if (!isMode) { 283 // Assume SRC_OVER 284 mode = SkXfermode::kSrcOver_Mode; 285 } 286 } else { 287 mode = SkXfermode::kSrcOver_Mode; 288 } 289 290 createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags); 291 292 return count; 293} 294 295int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, 296 int alpha, int flags) { 297 int count = saveSnapshot(); 298 createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags); 299 return count; 300} 301 302bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, 303 float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) { 304 LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top); 305 LAYER_LOGD("Layer cache size = %d", mLayerCache.getSize()); 306 307 GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; 308 LayerSize size(right - left, bottom - top); 309 310 Layer* layer = mLayerCache.get(size, previousFbo); 311 if (!layer) { 312 return false; 313 } 314 315 glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); 316 317 // Clear the FBO 318 glDisable(GL_SCISSOR_TEST); 319 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 320 glClear(GL_COLOR_BUFFER_BIT); 321 glEnable(GL_SCISSOR_TEST); 322 323 layer->mode = mode; 324 layer->alpha = alpha / 255.0f; 325 layer->layer.set(left, top, right, bottom); 326 327 // Save the layer in the snapshot 328 snapshot->flags |= Snapshot::kFlagIsLayer; 329 snapshot->layer = layer; 330 snapshot->fbo = layer->fbo; 331 332 snapshot->transform.loadTranslate(-left, -top, 0.0f); 333 snapshot->setClip(0.0f, 0.0f, right - left, bottom - top); 334 snapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top); 335 snapshot->height = bottom - top; 336 snapshot->flags |= Snapshot::kFlagDirtyOrtho; 337 snapshot->orthoMatrix.load(mOrthoMatrix); 338 339 setScissorFromClip(); 340 341 // Change the ortho projection 342 glViewport(0, 0, right - left, bottom - top); 343 // Don't flip the FBO, it will get flipped when drawing back to the framebuffer 344 mOrthoMatrix.loadOrtho(0.0f, right - left, 0.0f, bottom - top, -1.0f, 1.0f); 345 346 return true; 347} 348 349void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { 350 if (!current->layer) { 351 LOGE("Attempting to compose a layer that does not exist"); 352 return; 353 } 354 355 // Unbind current FBO and restore previous one 356 // Most of the time, previous->fbo will be 0 to bind the default buffer 357 glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); 358 359 // Restore the clip from the previous snapshot 360 const Rect& clip = previous->clipRect; 361 glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); 362 363 Layer* layer = current->layer; 364 const Rect& rect = layer->layer; 365 366 drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, 367 layer->texture, layer->alpha, layer->mode, layer->blend); 368 369 LayerSize size(rect.getWidth(), rect.getHeight()); 370 // Failing to add the layer to the cache should happen only if the 371 // layer is too large 372 if (!mLayerCache.put(size, layer)) { 373 LAYER_LOGD("Deleting layer"); 374 375 glDeleteFramebuffers(1, &layer->fbo); 376 glDeleteTextures(1, &layer->texture); 377 378 delete layer; 379 } 380} 381 382/////////////////////////////////////////////////////////////////////////////// 383// Transforms 384/////////////////////////////////////////////////////////////////////////////// 385 386void OpenGLRenderer::translate(float dx, float dy) { 387 mSnapshot->transform.translate(dx, dy, 0.0f); 388} 389 390void OpenGLRenderer::rotate(float degrees) { 391 mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f); 392} 393 394void OpenGLRenderer::scale(float sx, float sy) { 395 mSnapshot->transform.scale(sx, sy, 1.0f); 396} 397 398void OpenGLRenderer::setMatrix(SkMatrix* matrix) { 399 mSnapshot->transform.load(*matrix); 400} 401 402void OpenGLRenderer::getMatrix(SkMatrix* matrix) { 403 mSnapshot->transform.copyTo(*matrix); 404} 405 406void OpenGLRenderer::concatMatrix(SkMatrix* matrix) { 407 mat4 m(*matrix); 408 mSnapshot->transform.multiply(m); 409} 410 411/////////////////////////////////////////////////////////////////////////////// 412// Clipping 413/////////////////////////////////////////////////////////////////////////////// 414 415void OpenGLRenderer::setScissorFromClip() { 416 const Rect& clip = mSnapshot->clipRect; 417 glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight()); 418} 419 420const Rect& OpenGLRenderer::getClipBounds() { 421 return mSnapshot->getLocalClip(); 422} 423 424bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { 425 Rect r(left, top, right, bottom); 426 mSnapshot->transform.mapRect(r); 427 return !mSnapshot->clipRect.intersects(r); 428} 429 430bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 431 bool clipped = mSnapshot->clip(left, top, right, bottom, op); 432 if (clipped) { 433 setScissorFromClip(); 434 } 435 return !mSnapshot->clipRect.isEmpty(); 436} 437 438/////////////////////////////////////////////////////////////////////////////// 439// Drawing 440/////////////////////////////////////////////////////////////////////////////// 441 442void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { 443 const float right = left + bitmap->width(); 444 const float bottom = top + bitmap->height(); 445 446 if (quickReject(left, top, right, bottom)) { 447 return; 448 } 449 450 glActiveTexture(GL_TEXTURE0); 451 const Texture* texture = mTextureCache.get(bitmap); 452 if (!texture) return; 453 const AutoTexture autoCleanup(texture); 454 455 drawTextureRect(left, top, right, bottom, texture, paint); 456} 457 458void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) { 459 Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height()); 460 const mat4 transform(*matrix); 461 transform.mapRect(r); 462 463 if (quickReject(r.left, r.top, r.right, r.bottom)) { 464 return; 465 } 466 467 glActiveTexture(GL_TEXTURE0); 468 const Texture* texture = mTextureCache.get(bitmap); 469 if (!texture) return; 470 const AutoTexture autoCleanup(texture); 471 472 drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint); 473} 474 475void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, 476 float srcLeft, float srcTop, float srcRight, float srcBottom, 477 float dstLeft, float dstTop, float dstRight, float dstBottom, 478 const SkPaint* paint) { 479 if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { 480 return; 481 } 482 483 glActiveTexture(GL_TEXTURE0); 484 const Texture* texture = mTextureCache.get(bitmap); 485 if (!texture) return; 486 const AutoTexture autoCleanup(texture); 487 488 const float width = texture->width; 489 const float height = texture->height; 490 491 const float u1 = srcLeft / width; 492 const float v1 = srcTop / height; 493 const float u2 = srcRight / width; 494 const float v2 = srcBottom / height; 495 496 resetDrawTextureTexCoords(u1, v1, u2, v2); 497 498 drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint); 499 500 resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 501} 502 503void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, 504 float left, float top, float right, float bottom, const SkPaint* paint) { 505 if (quickReject(left, top, right, bottom)) { 506 return; 507 } 508 509 glActiveTexture(GL_TEXTURE0); 510 const Texture* texture = mTextureCache.get(bitmap); 511 if (!texture) return; 512 const AutoTexture autoCleanup(texture); 513 514 int alpha; 515 SkXfermode::Mode mode; 516 getAlphaAndMode(paint, &alpha, &mode); 517 518 Patch* mesh = mPatchCache.get(patch); 519 mesh->updateVertices(bitmap, left, top, right, bottom, 520 &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs); 521 522 // Specify right and bottom as +1.0f from left/top to prevent scaling since the 523 // patch mesh already defines the final size 524 drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f, 525 mode, texture->blend, &mesh->vertices[0].position[0], 526 &mesh->vertices[0].texture[0], mesh->indices, mesh->indicesCount); 527} 528 529void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { 530 const Rect& clip = mSnapshot->clipRect; 531 drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); 532} 533 534void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { 535 if (quickReject(left, top, right, bottom)) { 536 return; 537 } 538 539 SkXfermode::Mode mode; 540 541 const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 542 if (!isMode) { 543 // Assume SRC_OVER 544 mode = SkXfermode::kSrcOver_Mode; 545 } 546 547 // Skia draws using the color's alpha channel if < 255 548 // Otherwise, it uses the paint's alpha 549 int color = p->getColor(); 550 if (((color >> 24) & 0xff) == 255) { 551 color |= p->getAlpha() << 24; 552 } 553 554 drawColorRect(left, top, right, bottom, color, mode); 555} 556 557void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, 558 float x, float y, SkPaint* paint) { 559 if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { 560 return; 561 } 562 563 float length = -1.0f; 564 switch (paint->getTextAlign()) { 565 case SkPaint::kCenter_Align: 566 length = paint->measureText(text, bytesCount); 567 x -= length / 2.0f; 568 break; 569 case SkPaint::kRight_Align: 570 length = paint->measureText(text, bytesCount); 571 x -= length; 572 break; 573 default: 574 break; 575 } 576 577 int alpha; 578 SkXfermode::Mode mode; 579 getAlphaAndMode(paint, &alpha, &mode); 580 581 uint32_t color = paint->getColor(); 582 const GLfloat a = alpha / 255.0f; 583 const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 584 const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 585 const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 586 587 mFontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize()); 588 if (mHasShadow) { 589 glActiveTexture(gTextureUnits[0]); 590 const ShadowTexture* shadow = mDropShadowCache.get(paint, text, bytesCount, 591 count, mShadowRadius); 592 const AutoTexture autoCleanup(shadow); 593 594 setupShadow(shadow, x, y, mode, a); 595 596 // Draw the mesh 597 glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 598 glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); 599 } 600 601 GLuint textureUnit = 0; 602 glActiveTexture(gTextureUnits[textureUnit]); 603 604 setupTextureAlpha8(mFontRenderer.getTexture(), 0, 0, textureUnit, x, y, r, g, b, a, 605 mode, false, true); 606 607 const Rect& clip = mSnapshot->getLocalClip(); 608 mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y); 609 610 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 611 glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); 612 613 drawTextDecorations(text, bytesCount, length, x, y, paint); 614} 615 616void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { 617 GLuint textureUnit = 0; 618 glActiveTexture(gTextureUnits[textureUnit]); 619 620 const PathTexture* texture = mPathCache.get(path, paint); 621 if (!texture) return; 622 const AutoTexture autoCleanup(texture); 623 624 int alpha; 625 SkXfermode::Mode mode; 626 getAlphaAndMode(paint, &alpha, &mode); 627 628 uint32_t color = paint->getColor(); 629 const GLfloat a = alpha / 255.0f; 630 const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 631 const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 632 const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 633 634 const float x = texture->left - texture->offset; 635 const float y = texture->top - texture->offset; 636 637 setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true); 638 639 // Draw the mesh 640 glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 641 glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); 642} 643 644/////////////////////////////////////////////////////////////////////////////// 645// Shaders 646/////////////////////////////////////////////////////////////////////////////// 647 648void OpenGLRenderer::resetShader() { 649 mShader = NULL; 650} 651 652void OpenGLRenderer::setupShader(SkiaShader* shader) { 653 mShader = shader; 654 if (mShader) { 655 mShader->set(&mTextureCache, &mGradientCache); 656 } 657} 658 659/////////////////////////////////////////////////////////////////////////////// 660// Color filters 661/////////////////////////////////////////////////////////////////////////////// 662 663void OpenGLRenderer::resetColorFilter() { 664 mColorFilter = NULL; 665} 666 667void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) { 668 mColorFilter = filter; 669} 670 671/////////////////////////////////////////////////////////////////////////////// 672// Drop shadow 673/////////////////////////////////////////////////////////////////////////////// 674 675void OpenGLRenderer::resetShadow() { 676 mHasShadow = false; 677} 678 679void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { 680 mHasShadow = true; 681 mShadowRadius = radius; 682 mShadowDx = dx; 683 mShadowDy = dy; 684 mShadowColor = color; 685} 686 687/////////////////////////////////////////////////////////////////////////////// 688// Drawing implementation 689/////////////////////////////////////////////////////////////////////////////// 690 691void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, 692 SkXfermode::Mode mode, float alpha) { 693 const float sx = x - texture->left + mShadowDx; 694 const float sy = y - texture->top + mShadowDy; 695 696 const int shadowAlpha = ((mShadowColor >> 24) & 0xFF); 697 const GLfloat a = shadowAlpha < 255 ? shadowAlpha / 255.0f : alpha; 698 const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; 699 const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; 700 const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; 701 702 GLuint textureUnit = 0; 703 setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false); 704} 705 706void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, 707 float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, 708 bool transforms, bool applyFilters) { 709 setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit, 710 x, y, r, g, b, a, mode, transforms, applyFilters); 711} 712 713void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, 714 GLuint& textureUnit, float x, float y, float r, float g, float b, float a, 715 SkXfermode::Mode mode, bool transforms, bool applyFilters) { 716 // Describe the required shaders 717 ProgramDescription description; 718 description.hasTexture = true; 719 description.hasAlpha8Texture = true; 720 721 if (applyFilters) { 722 if (mShader) { 723 mShader->describe(description, mExtensions); 724 } 725 if (mColorFilter) { 726 mColorFilter->describe(description, mExtensions); 727 } 728 } 729 730 // Build and use the appropriate shader 731 useProgram(mProgramCache.get(description)); 732 733 // Setup the blending mode 734 chooseBlending(true, mode); 735 bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); 736 glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); 737 738 int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); 739 glEnableVertexAttribArray(texCoordsSlot); 740 741 // Setup attributes 742 glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, 743 gMeshStride, &mMeshVertices[0].position[0]); 744 glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, 745 gMeshStride, &mMeshVertices[0].texture[0]); 746 747 // Setup uniforms 748 if (transforms) { 749 mModelView.loadTranslate(x, y, 0.0f); 750 mModelView.scale(width, height, 1.0f); 751 } else { 752 mModelView.loadIdentity(); 753 } 754 mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 755 glUniform4f(mCurrentProgram->color, r, g, b, a); 756 757 textureUnit++; 758 if (applyFilters) { 759 // Setup attributes and uniforms required by the shaders 760 if (mShader) { 761 mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); 762 } 763 if (mColorFilter) { 764 mColorFilter->setupProgram(mCurrentProgram); 765 } 766 } 767} 768 769#define kStdStrikeThru_Offset (-6.0f / 21.0f) 770#define kStdUnderline_Offset (1.0f / 9.0f) 771#define kStdUnderline_Thickness (1.0f / 18.0f) 772 773void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, 774 float x, float y, SkPaint* paint) { 775 // Handle underline and strike-through 776 uint32_t flags = paint->getFlags(); 777 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { 778 float underlineWidth = length; 779 // If length is > 0.0f, we already measured the text for the text alignment 780 if (length <= 0.0f) { 781 underlineWidth = paint->measureText(text, bytesCount); 782 } 783 784 float offsetX = 0; 785 switch (paint->getTextAlign()) { 786 case SkPaint::kCenter_Align: 787 offsetX = underlineWidth * 0.5f; 788 break; 789 case SkPaint::kRight_Align: 790 offsetX = underlineWidth; 791 break; 792 default: 793 break; 794 } 795 796 if (underlineWidth > 0.0f) { 797 float textSize = paint->getTextSize(); 798 float height = textSize * kStdUnderline_Thickness; 799 800 float left = x - offsetX; 801 float top = 0.0f; 802 float right = left + underlineWidth; 803 float bottom = 0.0f; 804 805 if (flags & SkPaint::kUnderlineText_Flag) { 806 top = y + textSize * kStdUnderline_Offset; 807 bottom = top + height; 808 drawRect(left, top, right, bottom, paint); 809 } 810 811 if (flags & SkPaint::kStrikeThruText_Flag) { 812 top = y + textSize * kStdStrikeThru_Offset; 813 bottom = top + height; 814 drawRect(left, top, right, bottom, paint); 815 } 816 } 817 } 818} 819 820void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, 821 int color, SkXfermode::Mode mode, bool ignoreTransform) { 822 // If a shader is set, preserve only the alpha 823 if (mShader) { 824 color |= 0x00ffffff; 825 } 826 827 // Render using pre-multiplied alpha 828 const int alpha = (color >> 24) & 0xFF; 829 const GLfloat a = alpha / 255.0f; 830 const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 831 const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 832 const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 833 834 GLuint textureUnit = 0; 835 836 // Setup the blending mode 837 chooseBlending(alpha < 255 || (mShader && mShader->blend()), mode); 838 839 // Describe the required shaders 840 ProgramDescription description; 841 if (mShader) { 842 mShader->describe(description, mExtensions); 843 } 844 if (mColorFilter) { 845 mColorFilter->describe(description, mExtensions); 846 } 847 848 // Build and use the appropriate shader 849 useProgram(mProgramCache.get(description)); 850 851 // Setup attributes 852 glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, 853 gMeshStride, &mMeshVertices[0].position[0]); 854 855 // Setup uniforms 856 mModelView.loadTranslate(left, top, 0.0f); 857 mModelView.scale(right - left, bottom - top, 1.0f); 858 if (!ignoreTransform) { 859 mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 860 } else { 861 mat4 identity; 862 mCurrentProgram->set(mOrthoMatrix, mModelView, identity); 863 } 864 glUniform4f(mCurrentProgram->color, r, g, b, a); 865 866 // Setup attributes and uniforms required by the shaders 867 if (mShader) { 868 mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); 869 } 870 if (mColorFilter) { 871 mColorFilter->setupProgram(mCurrentProgram); 872 } 873 874 // Draw the mesh 875 glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 876} 877 878void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 879 const Texture* texture, const SkPaint* paint) { 880 int alpha; 881 SkXfermode::Mode mode; 882 getAlphaAndMode(paint, &alpha, &mode); 883 884 drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend, 885 &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL); 886} 887 888void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 889 GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) { 890 drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend, 891 &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL); 892} 893 894void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom, 895 GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, 896 GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) { 897 ProgramDescription description; 898 description.hasTexture = true; 899 if (mColorFilter) { 900 mColorFilter->describe(description, mExtensions); 901 } 902 903 mModelView.loadTranslate(left, top, 0.0f); 904 mModelView.scale(right - left, bottom - top, 1.0f); 905 906 useProgram(mProgramCache.get(description)); 907 mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 908 909 chooseBlending(blend || alpha < 1.0f, mode); 910 911 // Texture 912 bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); 913 glUniform1i(mCurrentProgram->getUniform("sampler"), 0); 914 915 // Always premultiplied 916 glUniform4f(mCurrentProgram->color, alpha, alpha, alpha, alpha); 917 918 // Mesh 919 int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); 920 glEnableVertexAttribArray(texCoordsSlot); 921 glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, 922 gMeshStride, vertices); 923 glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); 924 925 // Color filter 926 if (mColorFilter) { 927 mColorFilter->setupProgram(mCurrentProgram); 928 } 929 930 if (!indices) { 931 glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 932 } else { 933 glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices); 934 } 935 glDisableVertexAttribArray(texCoordsSlot); 936} 937 938void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) { 939 blend = blend || mode != SkXfermode::kSrcOver_Mode; 940 if (blend) { 941 if (!mBlend) { 942 glEnable(GL_BLEND); 943 } 944 945 GLenum sourceMode = gBlends[mode].src; 946 GLenum destMode = gBlends[mode].dst; 947 if (!isPremultiplied && sourceMode == GL_ONE) { 948 sourceMode = GL_SRC_ALPHA; 949 } 950 951 if (sourceMode != mLastSrcMode || destMode != mLastDstMode) { 952 glBlendFunc(sourceMode, destMode); 953 mLastSrcMode = sourceMode; 954 mLastDstMode = destMode; 955 } 956 } else if (mBlend) { 957 glDisable(GL_BLEND); 958 } 959 mBlend = blend; 960} 961 962bool OpenGLRenderer::useProgram(Program* program) { 963 if (!program->isInUse()) { 964 if (mCurrentProgram != NULL) mCurrentProgram->remove(); 965 program->use(); 966 mCurrentProgram = program; 967 return false; 968 } 969 return true; 970} 971 972void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { 973 TextureVertex* v = &mMeshVertices[0]; 974 TextureVertex::setUV(v++, u1, v1); 975 TextureVertex::setUV(v++, u2, v1); 976 TextureVertex::setUV(v++, u1, v2); 977 TextureVertex::setUV(v++, u2, v2); 978} 979 980void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) { 981 if (paint) { 982 const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode); 983 if (!isMode) { 984 // Assume SRC_OVER 985 *mode = SkXfermode::kSrcOver_Mode; 986 } 987 988 // Skia draws using the color's alpha channel if < 255 989 // Otherwise, it uses the paint's alpha 990 int color = paint->getColor(); 991 *alpha = (color >> 24) & 0xFF; 992 if (*alpha == 255) { 993 *alpha = paint->getAlpha(); 994 } 995 } else { 996 *mode = SkXfermode::kSrcOver_Mode; 997 *alpha = 255; 998 } 999} 1000 1001void OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) { 1002 glActiveTexture(gTextureUnits[textureUnit]); 1003 glBindTexture(GL_TEXTURE_2D, texture); 1004 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 1005 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 1006} 1007 1008}; // namespace uirenderer 1009}; // namespace android 1010