• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
toGLMatrix(GLfloat * flattened,const TransformationMatrix & m)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 
toSkMatrix(SkMatrix & matrix,const TransformationMatrix & m)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 
setOrthographicMatrix(TransformationMatrix & ortho,float left,float top,float right,float bottom,float nearZ,float farZ)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 
has3dTransform(const TransformationMatrix & matrix)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 
allowGLLog()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 
crashIfOOM(GLint errorCode)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 
checkEglError(const char * op,EGLBoolean returnVal)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 
checkGlError(const char * op)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 
checkGlErrorOn(void * p,const char * op)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 
checkSurfaceTextureError(const char * functionName,int status)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 
isEGLImageSupported()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 
isEGLFenceSyncSupported()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 
getInternalFormat(SkBitmap::Config config)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 
getType(SkBitmap::Config config)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 
defaultPbufferConfig(EGLDisplay display)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 
createPbufferSurface(EGLDisplay display,const EGLConfig & config,EGLint * errorCode)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 
deleteTexture(GLuint * texture)309 void GLUtils::deleteTexture(GLuint* texture)
310 {
311     glDeleteTextures(1, texture);
312     GLUtils::checkGlError("glDeleteTexture");
313     *texture = 0;
314 }
315 
createSampleColorTexture(int r,int g,int b)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 
createSampleTexture()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 
createTileGLTexture(int width,int height)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 
isPureColorBitmap(const SkBitmap & bitmap,Color & pureColor)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     pureColor = Color(Color::transparent);
388     bitmap.lockPixels();
389     bool sameColor = true;
390     int bitmapWidth = bitmap.width();
391 
392     // Create a row of pure color using the first pixel.
393     // TODO: improve the perf here, by either picking a random pixel, or
394     // creating an array of rows with pre-defined commonly used color, add
395     // smart LUT to speed things up if possible.
396     int* firstPixelPtr = static_cast<int*> (bitmap.getPixels());
397     int* pixelsRow = new int[bitmapWidth];
398     for (int i = 0; i < bitmapWidth; i++)
399         pixelsRow[i] = (*firstPixelPtr);
400 
401     // Then compare the pure color row with each row of the bitmap.
402     for (int j = 0; j < bitmap.height(); j++) {
403         if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) {
404             sameColor = false;
405             break;
406         }
407     }
408     delete pixelsRow;
409     pixelsRow = 0;
410 
411     if (sameColor) {
412         char* rgbaPtr = static_cast<char*>(bitmap.getPixels());
413         pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]);
414         ALOGV("sameColor tile found , %x at (%d, %d, %d, %d)",
415               *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]);
416     }
417     bitmap.unlockPixels();
418 
419     return sameColor;
420 }
421 
422 // Return true when the tile is pure color.
skipTransferForPureColor(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)423 bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo,
424                                        const SkBitmap& bitmap)
425 {
426     bool skipTransfer = false;
427     Tile* tilePtr = renderInfo->baseTile;
428 
429     if (tilePtr) {
430         TileTexture* tileTexture = tilePtr->backTexture();
431         // Check the bitmap, and make everything ready here.
432         if (tileTexture && renderInfo->isPureColor) {
433             // update basetile's info
434             // Note that we are skipping the whole TransferQueue.
435             renderInfo->textureInfo->m_width = bitmap.width();
436             renderInfo->textureInfo->m_height = bitmap.height();
437             renderInfo->textureInfo->m_internalFormat = GL_RGBA;
438 
439             TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo);
440 
441             skipTransfer = true;
442         }
443     }
444     return skipTransfer;
445 }
446 
paintTextureWithBitmap(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)447 void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
448                                      const SkBitmap& bitmap)
449 {
450     if (!renderInfo)
451         return;
452     const SkSize& requiredSize = renderInfo->tileSize;
453     TextureInfo* textureInfo = renderInfo->textureInfo;
454 
455     if (skipTransferForPureColor(renderInfo, bitmap))
456         return;
457 
458     if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height))
459         GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
460     else {
461         if (!requiredSize.equals(bitmap.width(), bitmap.height())) {
462             ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)",
463                   bitmap.width(), bitmap.height(),
464                   requiredSize.width(), requiredSize.height());
465         }
466         GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
467 
468         textureInfo->m_width = bitmap.width();
469         textureInfo->m_height = bitmap.height();
470         textureInfo->m_internalFormat = GL_RGBA;
471     }
472 }
473 
updateQueueWithBitmap(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)474 void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap)
475 {
476     if (!renderInfo
477         || !renderInfo->textureInfo
478         || !renderInfo->baseTile)
479         return;
480 
481     TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap);
482 }
483 
updateSharedSurfaceTextureWithBitmap(ANativeWindow * anw,const SkBitmap & bitmap)484 bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap)
485 {
486     SkAutoLockPixels alp(bitmap);
487     if (!bitmap.getPixels())
488         return false;
489     ANativeWindow_Buffer buffer;
490     if (ANativeWindow_lock(anw, &buffer, 0))
491         return false;
492     if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) {
493         ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!",
494                 bitmap.width(), bitmap.height(),
495                 buffer.width, buffer.height);
496         ANativeWindow_unlockAndPost(anw);
497         return false;
498     }
499     uint8_t* img = (uint8_t*)buffer.bits;
500     int row;
501     int bpp = 4; // Now we only deal with RGBA8888 format.
502     bitmap.lockPixels();
503     uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
504 
505     if (buffer.stride != bitmap.width())
506         // Copied line by line since we need to handle the offsets and stride.
507         for (row = 0 ; row < bitmap.height(); row ++) {
508             uint8_t* dst = &(img[buffer.stride * row * bpp]);
509             uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
510             memcpy(dst, src, bpp * bitmap.width());
511         }
512     else
513         memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height());
514 
515     bitmap.unlockPixels();
516     ANativeWindow_unlockAndPost(anw);
517     return true;
518 }
519 
createTextureWithBitmap(GLuint texture,const SkBitmap & bitmap,GLint filter)520 void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter)
521 {
522     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
523     glBindTexture(GL_TEXTURE_2D, texture);
524     GLUtils::checkGlError("glBindTexture");
525     SkBitmap::Config config = bitmap.getConfig();
526     int internalformat = getInternalFormat(config);
527     int type = getType(config);
528     bitmap.lockPixels();
529     glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(),
530                  0, internalformat, type, bitmap.getPixels());
531     bitmap.unlockPixels();
532     if (GLUtils::checkGlError("glTexImage2D")) {
533 #ifndef DEBUG
534         if (allowGLLog())
535 #endif
536         ALOGE("GL ERROR: glTexImage2D parameters are : textureId %d,"
537               " bitmap.width() %d, bitmap.height() %d,"
538               " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
539               texture, bitmap.width(), bitmap.height(), internalformat, type,
540               bitmap.getPixels());
541     }
542     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
543     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
544 }
545 
updateTextureWithBitmap(GLuint texture,const SkBitmap & bitmap,const IntRect & inval,GLint filter)546 void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap,
547                                       const IntRect& inval, GLint filter)
548 {
549     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
550     glBindTexture(GL_TEXTURE_2D, texture);
551     GLUtils::checkGlError("glBindTexture");
552     SkBitmap::Config config = bitmap.getConfig();
553     int internalformat = getInternalFormat(config);
554     int type = getType(config);
555     bitmap.lockPixels();
556     if (inval.isEmpty()) {
557         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
558                         internalformat, type, bitmap.getPixels());
559     } else {
560         glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(),
561                         internalformat, type, bitmap.getPixels());
562     }
563     bitmap.unlockPixels();
564     if (GLUtils::checkGlError("glTexSubImage2D")) {
565 #ifndef DEBUG
566         if (allowGLLog())
567 #endif
568         ALOGE("GL ERROR: glTexSubImage2D parameters are : textureId %d,"
569               " bitmap.width() %d, bitmap.height() %d,"
570               " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
571               texture, bitmap.width(), bitmap.height(), internalformat, type,
572               bitmap.getPixels());
573     }
574     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
575     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
576 }
577 
createEGLImageFromTexture(GLuint texture,EGLImageKHR * image)578 void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image)
579 {
580     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture);
581     static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
582     *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(),
583                                EGL_GL_TEXTURE_2D_KHR, buffer, attr);
584     GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR));
585 }
586 
createTextureFromEGLImage(GLuint texture,EGLImageKHR image,GLint filter)587 void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter)
588 {
589     glBindTexture(GL_TEXTURE_2D, texture);
590     GLUtils::checkGlError("glBindTexture");
591     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
592     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
593     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
594 }
595 
convertToTransformationMatrix(const float * matrix,TransformationMatrix & transformMatrix)596 void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix)
597 {
598     transformMatrix.setMatrix(
599         matrix[0], matrix[1], matrix[2], matrix[3],
600         matrix[4], matrix[5], matrix[6], matrix[7],
601         matrix[8], matrix[9], matrix[10], matrix[11],
602         matrix[12], matrix[13], matrix[14], matrix[15]);
603 }
604 
clearBackgroundIfOpaque(const Color * backgroundColor)605 void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor)
606 {
607     if (!backgroundColor->hasAlpha()) {
608         if (TilesManager::instance()->invertedScreen()) {
609             float color = 1.0 - ((((float) backgroundColor->red() / 255.0) +
610                           ((float) backgroundColor->green() / 255.0) +
611                           ((float) backgroundColor->blue() / 255.0)) / 3.0);
612             glClearColor(color, color, color, 1);
613         } else {
614             glClearColor((float)backgroundColor->red() / 255.0,
615                          (float)backgroundColor->green() / 255.0,
616                          (float)backgroundColor->blue() / 255.0, 1);
617         }
618         glClear(GL_COLOR_BUFFER_BIT);
619     }
620 }
621 
deepCopyBitmapSubset(const SkBitmap & sourceBitmap,SkBitmap & subset,int leftOffset,int topOffset)622 bool GLUtils::deepCopyBitmapSubset(const SkBitmap& sourceBitmap,
623                                    SkBitmap& subset, int leftOffset, int topOffset)
624 {
625     sourceBitmap.lockPixels();
626     subset.lockPixels();
627     char* srcPixels = (char*) sourceBitmap.getPixels();
628     char* dstPixels = (char*) subset.getPixels();
629     if (!dstPixels || !srcPixels || !subset.lockPixelsAreWritable()) {
630         ALOGD("no pixels :( %p, %p (writable=%d)", srcPixels, dstPixels,
631               subset.lockPixelsAreWritable());
632         subset.unlockPixels();
633         sourceBitmap.unlockPixels();
634         return false;
635     }
636     int srcRowSize = sourceBitmap.rowBytes();
637     int destRowSize = subset.rowBytes();
638     for (int i = 0; i < subset.height(); i++) {
639         int srcOffset = (i + topOffset) * srcRowSize;
640         srcOffset += (leftOffset * sourceBitmap.bytesPerPixel());
641         int dstOffset = i * destRowSize;
642         memcpy(dstPixels + dstOffset, srcPixels + srcOffset, destRowSize);
643     }
644     subset.unlockPixels();
645     sourceBitmap.unlockPixels();
646     return true;
647 }
648 
649 } // namespace WebCore
650 
651 #endif // USE(ACCELERATED_COMPOSITING)
652