• 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/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 
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     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.
skipTransferForPureColor(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)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 
paintTextureWithBitmap(const TileRenderInfo * renderInfo,SkBitmap & bitmap)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 
updateQueueWithBitmap(const TileRenderInfo * renderInfo,SkBitmap & bitmap)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 
updateSharedSurfaceTextureWithBitmap(ANativeWindow * anw,const SkBitmap & bitmap)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 
createTextureWithBitmap(GLuint texture,const SkBitmap & bitmap,GLint filter)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 
updateTextureWithBitmap(GLuint texture,const SkBitmap & bitmap,const IntRect & inval,GLint filter)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 
createEGLImageFromTexture(GLuint texture,EGLImageKHR * image)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 
createTextureFromEGLImage(GLuint texture,EGLImageKHR image,GLint filter)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 
convertToTransformationMatrix(const float * matrix,TransformationMatrix & transformMatrix)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 
clearBackgroundIfOpaque(const Color * backgroundColor)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 
deepCopyBitmapSubset(const SkBitmap & sourceBitmap,SkBitmap & subset,int leftOffset,int topOffset)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