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