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