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