Home | History | Annotate | Download | only in rendering
      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/SurfaceTexture.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