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