1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #define LOG_TAG "GLUtils" 27 #define LOG_NDEBUG 1 28 29 #include "config.h" 30 #include "GLUtils.h" 31 32 #if USE(ACCELERATED_COMPOSITING) 33 34 #include "AndroidLog.h" 35 #include "BaseRenderer.h" 36 #include "TextureInfo.h" 37 #include "Tile.h" 38 #include "TilesManager.h" 39 #include "TransferQueue.h" 40 41 #include <android/native_window.h> 42 #include <gui/GLConsumer.h> 43 #include <wtf/CurrentTime.h> 44 45 // We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every 46 // LOG_VOLUME_PER_CYCLE seconds. 47 #define LOG_CYCLE 30.0 48 #define LOG_VOLUME_PER_CYCLE 20 49 50 struct ANativeWindowBuffer; 51 52 namespace WebCore { 53 54 using namespace android; 55 56 ///////////////////////////////////////////////////////////////////////////////////////// 57 // Matrix utilities 58 ///////////////////////////////////////////////////////////////////////////////////////// 59 60 void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) 61 { 62 flattened[0] = m.m11(); // scaleX 63 flattened[1] = m.m12(); // skewY 64 flattened[2] = m.m13(); 65 flattened[3] = m.m14(); // persp0 66 flattened[4] = m.m21(); // skewX 67 flattened[5] = m.m22(); // scaleY 68 flattened[6] = m.m23(); 69 flattened[7] = m.m24(); // persp1 70 flattened[8] = m.m31(); 71 flattened[9] = m.m32(); 72 flattened[10] = m.m33(); 73 flattened[11] = m.m34(); 74 flattened[12] = m.m41(); // transX 75 flattened[13] = m.m42(); // transY 76 flattened[14] = m.m43(); 77 flattened[15] = m.m44(); // persp2 78 } 79 80 void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) 81 { 82 matrix[0] = m.m11(); // scaleX 83 matrix[1] = m.m21(); // skewX 84 matrix[2] = m.m41(); // transX 85 matrix[3] = m.m12(); // skewY 86 matrix[4] = m.m22(); // scaleY 87 matrix[5] = m.m42(); // transY 88 matrix[6] = m.m14(); // persp0 89 matrix[7] = m.m24(); // persp1 90 matrix[8] = m.m44(); // persp2 91 } 92 93 void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, 94 float right, float bottom, float nearZ, float farZ) 95 { 96 float deltaX = right - left; 97 float deltaY = top - bottom; 98 float deltaZ = farZ - nearZ; 99 if (!deltaX || !deltaY || !deltaZ) 100 return; 101 102 ortho.setM11(2.0f / deltaX); 103 ortho.setM41(-(right + left) / deltaX); 104 ortho.setM22(2.0f / deltaY); 105 ortho.setM42(-(top + bottom) / deltaY); 106 ortho.setM33(-2.0f / deltaZ); 107 ortho.setM43(-(nearZ + farZ) / deltaZ); 108 } 109 110 bool GLUtils::has3dTransform(const TransformationMatrix& matrix) 111 { 112 return matrix.m13() != 0 || matrix.m23() != 0 113 || matrix.m31() != 0 || matrix.m32() != 0 114 || matrix.m33() != 1 || matrix.m34() != 0 115 || matrix.m43() != 0; 116 } 117 118 ///////////////////////////////////////////////////////////////////////////////////////// 119 // GL & EGL error checks 120 ///////////////////////////////////////////////////////////////////////////////////////// 121 122 double GLUtils::m_previousLogTime = 0; 123 int GLUtils::m_currentLogCounter = 0; 124 125 bool GLUtils::allowGLLog() 126 { 127 if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) { 128 m_currentLogCounter++; 129 return true; 130 } 131 132 // when we are in Log cycle and over the log limit, just return false 133 double currentTime = WTF::currentTime(); 134 double delta = currentTime - m_previousLogTime; 135 bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0); 136 if (inLogCycle) 137 return false; 138 139 // When we are out of Log Cycle and over the log limit, we need to reset 140 // the counter and timer. 141 m_previousLogTime = currentTime; 142 m_currentLogCounter = 0; 143 return false; 144 } 145 146 static void crashIfOOM(GLint errorCode) 147 { 148 const GLint OOM_ERROR_CODE = 0x505; 149 if (errorCode == OOM_ERROR_CODE) { 150 ALOGE("ERROR: Fatal OOM detected."); 151 CRASH(); 152 } 153 } 154 155 void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) 156 { 157 if (returnVal != EGL_TRUE) { 158 #ifndef DEBUG 159 if (allowGLLog()) 160 #endif 161 ALOGE("EGL ERROR - %s() returned %d\n", op, returnVal); 162 } 163 164 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { 165 #ifndef DEBUG 166 if (allowGLLog()) 167 #endif 168 ALOGE("after %s() eglError (0x%x)\n", op, error); 169 crashIfOOM(error); 170 } 171 } 172 173 bool GLUtils::checkGlError(const char* op) 174 { 175 bool ret = false; 176 for (GLint error = glGetError(); error; error = glGetError()) { 177 #ifndef DEBUG 178 if (allowGLLog()) 179 #endif 180 ALOGE("GL ERROR - after %s() glError (0x%x)\n", op, error); 181 crashIfOOM(error); 182 ret = true; 183 } 184 return ret; 185 } 186 187 bool GLUtils::checkGlErrorOn(void* p, const char* op) 188 { 189 bool ret = false; 190 for (GLint error = glGetError(); error; error = glGetError()) { 191 #ifndef DEBUG 192 if (allowGLLog()) 193 #endif 194 ALOGE("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); 195 crashIfOOM(error); 196 ret = true; 197 } 198 return ret; 199 } 200 201 void GLUtils::checkSurfaceTextureError(const char* functionName, int status) 202 { 203 if (status != NO_ERROR) { 204 #ifndef DEBUG 205 if (allowGLLog()) 206 #endif 207 ALOGE("ERROR at calling %s status is (%d)", functionName, status); 208 } 209 } 210 ///////////////////////////////////////////////////////////////////////////////////////// 211 // GL & EGL extension checks 212 ///////////////////////////////////////////////////////////////////////////////////////// 213 214 bool GLUtils::isEGLImageSupported() 215 { 216 const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); 217 const char* glExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); 218 219 return eglExtensions && glExtensions 220 && strstr(eglExtensions, "EGL_KHR_image_base") 221 && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") 222 && strstr(glExtensions, "GL_OES_EGL_image"); 223 } 224 225 bool GLUtils::isEGLFenceSyncSupported() 226 { 227 const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); 228 return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync"); 229 } 230 231 ///////////////////////////////////////////////////////////////////////////////////////// 232 // Textures utilities 233 ///////////////////////////////////////////////////////////////////////////////////////// 234 235 static GLenum getInternalFormat(SkBitmap::Config config) 236 { 237 switch (config) { 238 case SkBitmap::kA8_Config: 239 return GL_ALPHA; 240 case SkBitmap::kARGB_4444_Config: 241 return GL_RGBA; 242 case SkBitmap::kARGB_8888_Config: 243 return GL_RGBA; 244 case SkBitmap::kRGB_565_Config: 245 return GL_RGB; 246 default: 247 return -1; 248 } 249 } 250 251 static GLenum getType(SkBitmap::Config config) 252 { 253 switch (config) { 254 case SkBitmap::kA8_Config: 255 return GL_UNSIGNED_BYTE; 256 case SkBitmap::kARGB_4444_Config: 257 return GL_UNSIGNED_SHORT_4_4_4_4; 258 case SkBitmap::kARGB_8888_Config: 259 return GL_UNSIGNED_BYTE; 260 case SkBitmap::kIndex8_Config: 261 return -1; // No type for compressed data. 262 case SkBitmap::kRGB_565_Config: 263 return GL_UNSIGNED_SHORT_5_6_5; 264 default: 265 return -1; 266 } 267 } 268 269 static EGLConfig defaultPbufferConfig(EGLDisplay display) 270 { 271 EGLConfig config; 272 EGLint numConfigs; 273 274 static const EGLint configAttribs[] = { 275 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 276 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 277 EGL_NONE 278 }; 279 280 eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); 281 GLUtils::checkEglError("eglPbufferConfig"); 282 if (numConfigs != 1) 283 ALOGI("eglPbufferConfig failed (%d)\n", numConfigs); 284 285 return config; 286 } 287 288 static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config, 289 EGLint* errorCode) 290 { 291 const EGLint attribList[] = { 292 EGL_WIDTH, 1, 293 EGL_HEIGHT, 1, 294 EGL_NONE 295 }; 296 EGLSurface surface = eglCreatePbufferSurface(display, config, attribList); 297 298 if (errorCode) 299 *errorCode = eglGetError(); 300 else 301 GLUtils::checkEglError("eglCreatePbufferSurface"); 302 303 if (surface == EGL_NO_SURFACE) 304 return EGL_NO_SURFACE; 305 306 return surface; 307 } 308 309 void GLUtils::deleteTexture(GLuint* texture) 310 { 311 glDeleteTextures(1, texture); 312 GLUtils::checkGlError("glDeleteTexture"); 313 *texture = 0; 314 } 315 316 GLuint GLUtils::createSampleColorTexture(int r, int g, int b) 317 { 318 GLuint texture; 319 glGenTextures(1, &texture); 320 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 321 GLubyte pixels[4 *3] = { 322 r, g, b, 323 r, g, b, 324 r, g, b, 325 r, g, b 326 }; 327 glBindTexture(GL_TEXTURE_2D, texture); 328 GLUtils::checkGlError("glBindTexture"); 329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 330 GLUtils::checkGlError("glTexImage2D"); 331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 333 return texture; 334 } 335 336 GLuint GLUtils::createSampleTexture() 337 { 338 GLuint texture; 339 glGenTextures(1, &texture); 340 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 341 GLubyte pixels[4 *3] = { 342 255, 0, 0, 343 0, 255, 0, 344 0, 0, 255, 345 255, 255, 0 346 }; 347 glBindTexture(GL_TEXTURE_2D, texture); 348 GLUtils::checkGlError("glBindTexture"); 349 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 350 GLUtils::checkGlError("glTexImage2D"); 351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 353 return texture; 354 } 355 356 GLuint GLUtils::createTileGLTexture(int width, int height) 357 { 358 GLuint texture; 359 glGenTextures(1, &texture); 360 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 361 GLubyte* pixels = 0; 362 #ifdef DEBUG 363 int length = width * height * 4; 364 pixels = new GLubyte[length]; 365 for (int i = 0; i < length; i++) 366 pixels[i] = i % 256; 367 #endif 368 glBindTexture(GL_TEXTURE_2D, texture); 369 GLUtils::checkGlError("glBindTexture"); 370 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 371 GLUtils::checkGlError("glTexImage2D"); 372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 376 #ifdef DEBUG 377 delete pixels; 378 #endif 379 return texture; 380 } 381 382 bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) 383 { 384 // If the bitmap is the pure color, skip the transfer step, and update the Tile Info. 385 // This check is taking < 1ms if we do full bitmap check per tile. 386 // TODO: use the SkPicture to determine whether or not a tile is single color. 387 TRACE_METHOD(); 388 pureColor = Color(Color::transparent); 389 bitmap.lockPixels(); 390 bool sameColor = true; 391 int bitmapWidth = bitmap.width(); 392 393 // Create a row of pure color using the first pixel. 394 // TODO: improve the perf here, by either picking a random pixel, or 395 // creating an array of rows with pre-defined commonly used color, add 396 // smart LUT to speed things up if possible. 397 int* firstPixelPtr = static_cast<int*> (bitmap.getPixels()); 398 int* pixelsRow = new int[bitmapWidth]; 399 for (int i = 0; i < bitmapWidth; i++) 400 pixelsRow[i] = (*firstPixelPtr); 401 402 // Then compare the pure color row with each row of the bitmap. 403 for (int j = 0; j < bitmap.height(); j++) { 404 if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) { 405 sameColor = false; 406 break; 407 } 408 } 409 delete pixelsRow; 410 pixelsRow = 0; 411 412 if (sameColor) { 413 unsigned char* rgbaPtr = static_cast<unsigned char*>(bitmap.getPixels()); 414 pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); 415 ALOGV("sameColor tile found , %x at (%d, %d, %d, %d)", 416 *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); 417 } 418 bitmap.unlockPixels(); 419 420 return sameColor; 421 } 422 423 // Return true when the tile is pure color. 424 bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, 425 const SkBitmap& bitmap) 426 { 427 bool skipTransfer = false; 428 Tile* tilePtr = renderInfo->baseTile; 429 430 if (tilePtr) { 431 TileTexture* tileTexture = tilePtr->backTexture(); 432 // Check the bitmap, and make everything ready here. 433 if (tileTexture && renderInfo->isPureColor) { 434 // update basetile's info 435 // Note that we are skipping the whole TransferQueue. 436 renderInfo->textureInfo->m_width = bitmap.width(); 437 renderInfo->textureInfo->m_height = bitmap.height(); 438 renderInfo->textureInfo->m_internalFormat = GL_RGBA; 439 440 TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo); 441 442 skipTransfer = true; 443 } 444 } 445 return skipTransfer; 446 } 447 448 void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, 449 SkBitmap& bitmap) 450 { 451 if (!renderInfo) 452 return; 453 const SkSize& requiredSize = renderInfo->tileSize; 454 TextureInfo* textureInfo = renderInfo->textureInfo; 455 456 if (skipTransferForPureColor(renderInfo, bitmap)) 457 return; 458 459 if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) 460 GLUtils::updateQueueWithBitmap(renderInfo, bitmap); 461 else { 462 if (!requiredSize.equals(bitmap.width(), bitmap.height())) { 463 ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", 464 bitmap.width(), bitmap.height(), 465 requiredSize.width(), requiredSize.height()); 466 } 467 GLUtils::updateQueueWithBitmap(renderInfo, bitmap); 468 469 textureInfo->m_width = bitmap.width(); 470 textureInfo->m_height = bitmap.height(); 471 textureInfo->m_internalFormat = GL_RGBA; 472 } 473 } 474 475 void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, SkBitmap& bitmap) 476 { 477 if (!renderInfo 478 || !renderInfo->textureInfo 479 || !renderInfo->baseTile) 480 return; 481 482 TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); 483 } 484 485 bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) 486 { 487 TRACE_METHOD(); 488 SkAutoLockPixels alp(bitmap); 489 if (!bitmap.getPixels()) 490 return false; 491 ANativeWindow_Buffer buffer; 492 if (ANativeWindow_lock(anw, &buffer, 0)) 493 return false; 494 if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { 495 ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", 496 bitmap.width(), bitmap.height(), 497 buffer.width, buffer.height); 498 ANativeWindow_unlockAndPost(anw); 499 return false; 500 } 501 uint8_t* img = (uint8_t*)buffer.bits; 502 int row; 503 int bpp = 4; // Now we only deal with RGBA8888 format. 504 bitmap.lockPixels(); 505 uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); 506 507 if (buffer.stride != bitmap.width()) 508 // Copied line by line since we need to handle the offsets and stride. 509 for (row = 0 ; row < bitmap.height(); row ++) { 510 uint8_t* dst = &(img[buffer.stride * row * bpp]); 511 uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); 512 memcpy(dst, src, bpp * bitmap.width()); 513 } 514 else 515 memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); 516 517 bitmap.unlockPixels(); 518 ANativeWindow_unlockAndPost(anw); 519 return true; 520 } 521 522 void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) 523 { 524 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 525 glBindTexture(GL_TEXTURE_2D, texture); 526 GLUtils::checkGlError("glBindTexture"); 527 SkBitmap::Config config = bitmap.getConfig(); 528 int internalformat = getInternalFormat(config); 529 int type = getType(config); 530 bitmap.lockPixels(); 531 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(), 532 0, internalformat, type, bitmap.getPixels()); 533 bitmap.unlockPixels(); 534 if (GLUtils::checkGlError("glTexImage2D")) { 535 #ifndef DEBUG 536 if (allowGLLog()) 537 #endif 538 ALOGE("GL ERROR: glTexImage2D parameters are : textureId %d," 539 " bitmap.width() %d, bitmap.height() %d," 540 " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", 541 texture, bitmap.width(), bitmap.height(), internalformat, type, 542 bitmap.getPixels()); 543 } 544 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); 545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 546 } 547 548 void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, 549 const IntRect& inval, GLint filter) 550 { 551 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 552 glBindTexture(GL_TEXTURE_2D, texture); 553 GLUtils::checkGlError("glBindTexture"); 554 SkBitmap::Config config = bitmap.getConfig(); 555 int internalformat = getInternalFormat(config); 556 int type = getType(config); 557 bitmap.lockPixels(); 558 if (inval.isEmpty()) { 559 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), 560 internalformat, type, bitmap.getPixels()); 561 } else { 562 glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(), 563 internalformat, type, bitmap.getPixels()); 564 } 565 bitmap.unlockPixels(); 566 if (GLUtils::checkGlError("glTexSubImage2D")) { 567 #ifndef DEBUG 568 if (allowGLLog()) 569 #endif 570 ALOGE("GL ERROR: glTexSubImage2D parameters are : textureId %d," 571 " bitmap.width() %d, bitmap.height() %d," 572 " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", 573 texture, bitmap.width(), bitmap.height(), internalformat, type, 574 bitmap.getPixels()); 575 } 576 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); 577 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 578 } 579 580 void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) 581 { 582 EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture); 583 static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; 584 *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(), 585 EGL_GL_TEXTURE_2D_KHR, buffer, attr); 586 GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR)); 587 } 588 589 void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) 590 { 591 glBindTexture(GL_TEXTURE_2D, texture); 592 GLUtils::checkGlError("glBindTexture"); 593 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); 594 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); 595 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 596 } 597 598 void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix) 599 { 600 transformMatrix.setMatrix( 601 matrix[0], matrix[1], matrix[2], matrix[3], 602 matrix[4], matrix[5], matrix[6], matrix[7], 603 matrix[8], matrix[9], matrix[10], matrix[11], 604 matrix[12], matrix[13], matrix[14], matrix[15]); 605 } 606 607 void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) 608 { 609 if (!backgroundColor->hasAlpha()) { 610 if (TilesManager::instance()->invertedScreen()) { 611 float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + 612 ((float) backgroundColor->green() / 255.0) + 613 ((float) backgroundColor->blue() / 255.0)) / 3.0); 614 glClearColor(color, color, color, 1); 615 } else { 616 glClearColor((float)backgroundColor->red() / 255.0, 617 (float)backgroundColor->green() / 255.0, 618 (float)backgroundColor->blue() / 255.0, 1); 619 } 620 glClear(GL_COLOR_BUFFER_BIT); 621 } 622 } 623 624 bool GLUtils::deepCopyBitmapSubset(const SkBitmap& sourceBitmap, 625 SkBitmap& subset, int leftOffset, int topOffset) 626 { 627 sourceBitmap.lockPixels(); 628 subset.lockPixels(); 629 char* srcPixels = (char*) sourceBitmap.getPixels(); 630 char* dstPixels = (char*) subset.getPixels(); 631 if (!dstPixels || !srcPixels || !subset.lockPixelsAreWritable()) { 632 ALOGD("no pixels :( %p, %p (writable=%d)", srcPixels, dstPixels, 633 subset.lockPixelsAreWritable()); 634 subset.unlockPixels(); 635 sourceBitmap.unlockPixels(); 636 return false; 637 } 638 int srcRowSize = sourceBitmap.rowBytes(); 639 int destRowSize = subset.rowBytes(); 640 for (int i = 0; i < subset.height(); i++) { 641 int srcOffset = (i + topOffset) * srcRowSize; 642 srcOffset += (leftOffset * sourceBitmap.bytesPerPixel()); 643 int dstOffset = i * destRowSize; 644 memcpy(dstPixels + dstOffset, srcPixels + srcOffset, destRowSize); 645 } 646 subset.unlockPixels(); 647 sourceBitmap.unlockPixels(); 648 return true; 649 } 650 651 } // namespace WebCore 652 653 #endif // USE(ACCELERATED_COMPOSITING) 654