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