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