rsdGL.cpp revision a277734efa210be16f3646bf9c66924e59876c86
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <ui/FramebufferNativeWindow.h> 18#include <ui/PixelFormat.h> 19 20#include <system/window.h> 21 22#include <sys/types.h> 23#include <sys/resource.h> 24#include <sched.h> 25 26#include <cutils/properties.h> 27 28#include <GLES/gl.h> 29#include <GLES/glext.h> 30#include <GLES2/gl2.h> 31#include <GLES2/gl2ext.h> 32 33#include <string.h> 34 35#include "rsdCore.h" 36#include "rsdGL.h" 37 38#include <malloc.h> 39#include "rsContext.h" 40#include "rsdShaderCache.h" 41#include "rsdVertexArray.h" 42#include "rsdFrameBufferObj.h" 43 44#include <gui/SurfaceTextureClient.h> 45 46using namespace android; 47using namespace android::renderscript; 48 49static int32_t gGLContextCount = 0; 50 51static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 52 struct EGLUtils { 53 static const char *strerror(EGLint err) { 54 switch (err){ 55 case EGL_SUCCESS: return "EGL_SUCCESS"; 56 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 57 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 58 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 59 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 60 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 61 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 62 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 63 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 64 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 65 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 66 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 67 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 68 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 69 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 70 default: return "UNKNOWN"; 71 } 72 } 73 }; 74 75 if (returnVal != EGL_TRUE) { 76 fprintf(stderr, "%s() returned %d\n", op, returnVal); 77 } 78 79 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error 80 = eglGetError()) { 81 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), 82 error); 83 } 84} 85 86static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { 87 88#define X(VAL) {VAL, #VAL} 89 struct {EGLint attribute; const char* name;} names[] = { 90 X(EGL_BUFFER_SIZE), 91 X(EGL_ALPHA_SIZE), 92 X(EGL_BLUE_SIZE), 93 X(EGL_GREEN_SIZE), 94 X(EGL_RED_SIZE), 95 X(EGL_DEPTH_SIZE), 96 X(EGL_STENCIL_SIZE), 97 X(EGL_CONFIG_CAVEAT), 98 X(EGL_CONFIG_ID), 99 X(EGL_LEVEL), 100 X(EGL_MAX_PBUFFER_HEIGHT), 101 X(EGL_MAX_PBUFFER_PIXELS), 102 X(EGL_MAX_PBUFFER_WIDTH), 103 X(EGL_NATIVE_RENDERABLE), 104 X(EGL_NATIVE_VISUAL_ID), 105 X(EGL_NATIVE_VISUAL_TYPE), 106 X(EGL_SAMPLES), 107 X(EGL_SAMPLE_BUFFERS), 108 X(EGL_SURFACE_TYPE), 109 X(EGL_TRANSPARENT_TYPE), 110 X(EGL_TRANSPARENT_RED_VALUE), 111 X(EGL_TRANSPARENT_GREEN_VALUE), 112 X(EGL_TRANSPARENT_BLUE_VALUE), 113 X(EGL_BIND_TO_TEXTURE_RGB), 114 X(EGL_BIND_TO_TEXTURE_RGBA), 115 X(EGL_MIN_SWAP_INTERVAL), 116 X(EGL_MAX_SWAP_INTERVAL), 117 X(EGL_LUMINANCE_SIZE), 118 X(EGL_ALPHA_MASK_SIZE), 119 X(EGL_COLOR_BUFFER_TYPE), 120 X(EGL_RENDERABLE_TYPE), 121 X(EGL_CONFORMANT), 122 }; 123#undef X 124 125 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 126 EGLint value = -1; 127 EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 128 if (returnVal) { 129 ALOGV(" %s: %d (0x%x)", names[j].name, value, value); 130 } 131 } 132} 133 134static void DumpDebug(RsdHal *dc) { 135 ALOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion); 136 ALOGE(" EGL context %p surface %p, Display=%p", dc->gl.egl.context, dc->gl.egl.surface, 137 dc->gl.egl.display); 138 ALOGE(" GL vendor: %s", dc->gl.gl.vendor); 139 ALOGE(" GL renderer: %s", dc->gl.gl.renderer); 140 ALOGE(" GL Version: %s", dc->gl.gl.version); 141 ALOGE(" GL Extensions: %s", dc->gl.gl.extensions); 142 ALOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion); 143 144 ALOGV("MAX Textures %i, %i %i", dc->gl.gl.maxVertexTextureUnits, 145 dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits); 146 ALOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs); 147 ALOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors, 148 dc->gl.gl.maxFragmentUniformVectors); 149 ALOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors); 150} 151 152void rsdGLShutdown(const Context *rsc) { 153 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 154 155 dc->gl.shaderCache->cleanupAll(); 156 delete dc->gl.shaderCache; 157 delete dc->gl.vertexArrayState; 158 159 if (dc->gl.egl.context != EGL_NO_CONTEXT) { 160 RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display, 161 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 162 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault); 163 if (dc->gl.egl.surface != EGL_NO_SURFACE) { 164 RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface); 165 } 166 RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context); 167 checkEglError("eglDestroyContext"); 168 } 169 170 gGLContextCount--; 171 if (!gGLContextCount) { 172 RSD_CALL_GL(eglTerminate, dc->gl.egl.display); 173 } 174} 175 176bool rsdGLInit(const Context *rsc) { 177 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 178 179 dc->gl.egl.numConfigs = -1; 180 EGLint configAttribs[128]; 181 EGLint *configAttribsPtr = configAttribs; 182 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 183 184 memset(configAttribs, 0, sizeof(configAttribs)); 185 186 configAttribsPtr[0] = EGL_SURFACE_TYPE; 187 configAttribsPtr[1] = EGL_WINDOW_BIT; 188 configAttribsPtr += 2; 189 190 configAttribsPtr[0] = EGL_RENDERABLE_TYPE; 191 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; 192 configAttribsPtr += 2; 193 194 configAttribsPtr[0] = EGL_RED_SIZE; 195 configAttribsPtr[1] = 8; 196 configAttribsPtr += 2; 197 198 configAttribsPtr[0] = EGL_GREEN_SIZE; 199 configAttribsPtr[1] = 8; 200 configAttribsPtr += 2; 201 202 configAttribsPtr[0] = EGL_BLUE_SIZE; 203 configAttribsPtr[1] = 8; 204 configAttribsPtr += 2; 205 206 if (rsc->mUserSurfaceConfig.alphaMin > 0) { 207 configAttribsPtr[0] = EGL_ALPHA_SIZE; 208 configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin; 209 configAttribsPtr += 2; 210 } 211 212 if (rsc->mUserSurfaceConfig.depthMin > 0) { 213 configAttribsPtr[0] = EGL_DEPTH_SIZE; 214 configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin; 215 configAttribsPtr += 2; 216 } 217 218 if (rsc->mDev->mForceSW) { 219 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 220 configAttribsPtr[1] = EGL_SLOW_CONFIG; 221 configAttribsPtr += 2; 222 } 223 224 configAttribsPtr[0] = EGL_NONE; 225 rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); 226 227 ALOGV("%p initEGL start", rsc); 228 rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__); 229 dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 230 checkEglError("eglGetDisplay"); 231 232 RSD_CALL_GL(eglInitialize, dc->gl.egl.display, 233 &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion); 234 checkEglError("eglInitialize"); 235 236 EGLBoolean ret; 237 238 EGLint numConfigs = -1, n = 0; 239 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__); 240 ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs); 241 checkEglError("eglGetConfigs", ret); 242 243 eglSwapInterval(dc->gl.egl.display, 0); 244 245 if (numConfigs) { 246 EGLConfig* const configs = new EGLConfig[numConfigs]; 247 248 rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__); 249 ret = eglChooseConfig(dc->gl.egl.display, 250 configAttribs, configs, numConfigs, &n); 251 if (!ret || !n) { 252 checkEglError("eglChooseConfig", ret); 253 ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc); 254 } 255 256 // The first config is guaranteed to over-satisfy the constraints 257 dc->gl.egl.config = configs[0]; 258 259 // go through the list and skip configs that over-satisfy our needs 260 for (int i=0 ; i<n ; i++) { 261 if (rsc->mUserSurfaceConfig.alphaMin <= 0) { 262 EGLint alphaSize; 263 eglGetConfigAttrib(dc->gl.egl.display, 264 configs[i], EGL_ALPHA_SIZE, &alphaSize); 265 if (alphaSize > 0) { 266 continue; 267 } 268 } 269 270 if (rsc->mUserSurfaceConfig.depthMin <= 0) { 271 EGLint depthSize; 272 eglGetConfigAttrib(dc->gl.egl.display, 273 configs[i], EGL_DEPTH_SIZE, &depthSize); 274 if (depthSize > 0) { 275 continue; 276 } 277 } 278 279 // Found one! 280 dc->gl.egl.config = configs[i]; 281 break; 282 } 283 284 delete [] configs; 285 } 286 287 //if (props.mLogVisual) { 288 if (0) { 289 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config); 290 } 291 //} 292 293 rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__); 294 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config, 295 EGL_NO_CONTEXT, context_attribs2); 296 checkEglError("eglCreateContext"); 297 if (dc->gl.egl.context == EGL_NO_CONTEXT) { 298 ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc); 299 rsc->setWatchdogGL(NULL, 0, NULL); 300 return false; 301 } 302 gGLContextCount++; 303 304 sp<SurfaceTexture> st(new SurfaceTexture(123)); 305 sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st)); 306 dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 307 static_cast<ANativeWindow*>(stc.get()), 308 NULL); 309 310 checkEglError("eglCreateWindowSurface"); 311 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) { 312 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 313 rsdGLShutdown(rsc); 314 rsc->setWatchdogGL(NULL, 0, NULL); 315 return false; 316 } 317 318 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 319 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 320 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 321 if (ret == EGL_FALSE) { 322 ALOGE("eglMakeCurrent returned EGL_FALSE"); 323 checkEglError("eglMakeCurrent", ret); 324 rsdGLShutdown(rsc); 325 rsc->setWatchdogGL(NULL, 0, NULL); 326 return false; 327 } 328 329 dc->gl.gl.version = glGetString(GL_VERSION); 330 dc->gl.gl.vendor = glGetString(GL_VENDOR); 331 dc->gl.gl.renderer = glGetString(GL_RENDERER); 332 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS); 333 334 //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 335 //ALOGV("GL Version %s", mGL.mVersion); 336 //ALOGV("GL Vendor %s", mGL.mVendor); 337 //ALOGV("GL Renderer %s", mGL.mRenderer); 338 //ALOGV("GL Extensions %s", mGL.mExtensions); 339 340 const char *verptr = NULL; 341 if (strlen((const char *)dc->gl.gl.version) > 9) { 342 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) { 343 verptr = (const char *)dc->gl.gl.version + 12; 344 } 345 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) { 346 verptr = (const char *)dc->gl.gl.version + 9; 347 } 348 } 349 350 if (!verptr) { 351 ALOGE("Error, OpenGL ES Lite not supported"); 352 rsdGLShutdown(rsc); 353 rsc->setWatchdogGL(NULL, 0, NULL); 354 return false; 355 } else { 356 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion); 357 } 358 359 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs); 360 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors); 361 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits); 362 363 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors); 364 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits); 365 366 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits); 367 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors); 368 369 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 370 "GL_OES_texture_npot"); 371 dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 372 "GL_IMG_texture_npot"); 373 dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, 374 "GL_NV_texture_npot_2D_mipmap"); 375 dc->gl.gl.EXT_texture_max_aniso = 1.0f; 376 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, 377 "GL_EXT_texture_filter_anisotropic"); 378 if (hasAniso) { 379 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso); 380 } 381 382 if (0) { 383 DumpDebug(dc); 384 } 385 386 dc->gl.shaderCache = new RsdShaderCache(); 387 dc->gl.vertexArrayState = new RsdVertexArrayState(); 388 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs); 389 dc->gl.currentFrameBuffer = NULL; 390 dc->mHasGraphics = true; 391 392 ALOGV("%p initGLThread end", rsc); 393 rsc->setWatchdogGL(NULL, 0, NULL); 394 return true; 395} 396 397 398bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) { 399 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 400 401 EGLBoolean ret; 402 // WAR: Some drivers fail to handle 0 size surfaces correcntly. 403 // Use the pbuffer to avoid this pitfall. 404 if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) { 405 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 406 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 407 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 408 checkEglError("eglMakeCurrent", ret); 409 410 rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__); 411 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 412 checkEglError("eglDestroySurface", ret); 413 414 dc->gl.egl.surface = NULL; 415 dc->gl.width = 1; 416 dc->gl.height = 1; 417 } 418 419 if (dc->gl.wndSurface != NULL) { 420 dc->gl.wndSurface->decStrong(NULL); 421 } 422 423 dc->gl.wndSurface = (ANativeWindow *)sur; 424 if (dc->gl.wndSurface != NULL) { 425 dc->gl.wndSurface->incStrong(NULL); 426 dc->gl.width = w; 427 dc->gl.height = h; 428 429 rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__); 430 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 431 dc->gl.wndSurface, NULL); 432 checkEglError("eglCreateWindowSurface"); 433 if (dc->gl.egl.surface == EGL_NO_SURFACE) { 434 ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 435 } 436 437 rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__); 438 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface, 439 dc->gl.egl.surface, dc->gl.egl.context); 440 checkEglError("eglMakeCurrent", ret); 441 } 442 rsc->setWatchdogGL(NULL, 0, NULL); 443 return true; 444} 445 446void rsdGLSwap(const android::renderscript::Context *rsc) { 447 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 448 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface); 449} 450 451void rsdGLSetPriority(const Context *rsc, int32_t priority) { 452 if (priority > 0) { 453 // Mark context as low priority. 454 ALOGV("low pri"); 455 } else { 456 ALOGV("normal pri"); 457 } 458} 459 460void rsdGLCheckError(const android::renderscript::Context *rsc, 461 const char *msg, bool isFatal) { 462 GLenum err = glGetError(); 463 if (err != GL_NO_ERROR) { 464 char buf[1024]; 465 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg); 466 467 if (isFatal) { 468 rsc->setError(RS_ERROR_FATAL_DRIVER, buf); 469 } else { 470 switch (err) { 471 case GL_OUT_OF_MEMORY: 472 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf); 473 break; 474 default: 475 rsc->setError(RS_ERROR_DRIVER, buf); 476 break; 477 } 478 } 479 480 ALOGE("%p, %s", rsc, buf); 481 } 482 483} 484 485void rsdGLClearColor(const android::renderscript::Context *rsc, 486 float r, float g, float b, float a) { 487 RSD_CALL_GL(glClearColor, r, g, b, a); 488 RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT); 489} 490 491void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) { 492 RSD_CALL_GL(glClearDepthf, v); 493 RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT); 494} 495 496void rsdGLFinish(const android::renderscript::Context *rsc) { 497 RSD_CALL_GL(glFinish); 498} 499 500void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc, 501 float x1, float y1, float z1, float u1, float v1, 502 float x2, float y2, float z2, float u2, float v2, 503 float x3, float y3, float z3, float u3, float v3, 504 float x4, float y4, float z4, float u4, float v4) { 505 506 float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4}; 507 const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4}; 508 509 RsdVertexArray::Attrib attribs[2]; 510 attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position"); 511 attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0"); 512 513 RsdVertexArray va(attribs, 2); 514 va.setup(rsc); 515 516 RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4); 517} 518