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