rsdGL.cpp revision c33e6903d25b9cd9d88f45c7320534a5a05c9064
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 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 103 EGLint error = eglGetError(); 104 if (returnVal && error == EGL_SUCCESS) { 105 LOGV(" %s: %d (0x%x)", names[j].name, value, value); 106 } 107 } 108} 109 110static void DumpDebug(RsdHal *dc) { 111 LOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion); 112 LOGE(" EGL context %p surface %p, Display=%p", dc->gl.egl.context, dc->gl.egl.surface, 113 dc->gl.egl.display); 114 LOGE(" GL vendor: %s", dc->gl.gl.vendor); 115 LOGE(" GL renderer: %s", dc->gl.gl.renderer); 116 LOGE(" GL Version: %s", dc->gl.gl.version); 117 LOGE(" GL Extensions: %s", dc->gl.gl.extensions); 118 LOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion); 119 120 LOGV("MAX Textures %i, %i %i", dc->gl.gl.maxVertexTextureUnits, 121 dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits); 122 LOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs); 123 LOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors, 124 dc->gl.gl.maxFragmentUniformVectors); 125 LOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors); 126} 127 128void rsdGLShutdown(const Context *rsc) { 129 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 130 131 dc->gl.shaderCache->cleanupAll(); 132 delete dc->gl.shaderCache; 133 134 delete dc->gl.vertexArrayState; 135 136 LOGV("%p, deinitEGL", rsc); 137 138 if (dc->gl.egl.context != EGL_NO_CONTEXT) { 139 eglMakeCurrent(dc->gl.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 140 eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surfaceDefault); 141 if (dc->gl.egl.surface != EGL_NO_SURFACE) { 142 eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 143 } 144 eglDestroyContext(dc->gl.egl.display, dc->gl.egl.context); 145 checkEglError("eglDestroyContext"); 146 } 147 148 gGLContextCount--; 149 if (!gGLContextCount) { 150 eglTerminate(dc->gl.egl.display); 151 } 152} 153 154bool rsdGLInit(const Context *rsc) { 155 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 156 157 dc->gl.egl.numConfigs = -1; 158 EGLint configAttribs[128]; 159 EGLint *configAttribsPtr = configAttribs; 160 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 161 162 memset(configAttribs, 0, sizeof(configAttribs)); 163 164 configAttribsPtr[0] = EGL_SURFACE_TYPE; 165 configAttribsPtr[1] = EGL_WINDOW_BIT; 166 configAttribsPtr += 2; 167 168 configAttribsPtr[0] = EGL_RENDERABLE_TYPE; 169 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; 170 configAttribsPtr += 2; 171 172 if (rsc->mUserSurfaceConfig.depthMin > 0) { 173 configAttribsPtr[0] = EGL_DEPTH_SIZE; 174 configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin; 175 configAttribsPtr += 2; 176 } 177 178 if (rsc->mDev->mForceSW) { 179 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 180 configAttribsPtr[1] = EGL_SLOW_CONFIG; 181 configAttribsPtr += 2; 182 } 183 184 configAttribsPtr[0] = EGL_NONE; 185 rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); 186 187 LOGV("%p initEGL start", rsc); 188 dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 189 checkEglError("eglGetDisplay"); 190 191 eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion); 192 checkEglError("eglInitialize"); 193 194 PixelFormat pf = PIXEL_FORMAT_RGBA_8888; 195 if (rsc->mUserSurfaceConfig.alphaMin == 0) { 196 pf = PIXEL_FORMAT_RGBX_8888; 197 } 198 199 status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs, 200 pf, &dc->gl.egl.config); 201 if (err) { 202 LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc); 203 } 204 //if (props.mLogVisual) { 205 if (0) { 206 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config); 207 } 208 //} 209 210 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config, 211 EGL_NO_CONTEXT, context_attribs2); 212 checkEglError("eglCreateContext"); 213 if (dc->gl.egl.context == EGL_NO_CONTEXT) { 214 LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc); 215 return false; 216 } 217 gGLContextCount++; 218 219 220 EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 221 dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config, 222 pbuffer_attribs); 223 checkEglError("eglCreatePbufferSurface"); 224 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) { 225 LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE"); 226 rsdGLShutdown(rsc); 227 return false; 228 } 229 230 EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 231 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 232 if (ret == EGL_FALSE) { 233 LOGE("eglMakeCurrent returned EGL_FALSE"); 234 checkEglError("eglMakeCurrent", ret); 235 rsdGLShutdown(rsc); 236 return false; 237 } 238 239 dc->gl.gl.version = glGetString(GL_VERSION); 240 dc->gl.gl.vendor = glGetString(GL_VENDOR); 241 dc->gl.gl.renderer = glGetString(GL_RENDERER); 242 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS); 243 244 //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 245 //LOGV("GL Version %s", mGL.mVersion); 246 //LOGV("GL Vendor %s", mGL.mVendor); 247 //LOGV("GL Renderer %s", mGL.mRenderer); 248 //LOGV("GL Extensions %s", mGL.mExtensions); 249 250 const char *verptr = NULL; 251 if (strlen((const char *)dc->gl.gl.version) > 9) { 252 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) { 253 verptr = (const char *)dc->gl.gl.version + 12; 254 } 255 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) { 256 verptr = (const char *)dc->gl.gl.version + 9; 257 } 258 } 259 260 if (!verptr) { 261 LOGE("Error, OpenGL ES Lite not supported"); 262 rsdGLShutdown(rsc); 263 return false; 264 } else { 265 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion); 266 } 267 268 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs); 269 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors); 270 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits); 271 272 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors); 273 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits); 274 275 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits); 276 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors); 277 278 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 279 "GL_OES_texture_npot"); 280 dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 281 "GL_IMG_texture_npot"); 282 dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, 283 "GL_NV_texture_npot_2D_mipmap"); 284 dc->gl.gl.EXT_texture_max_aniso = 1.0f; 285 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, 286 "GL_EXT_texture_filter_anisotropic"); 287 if (hasAniso) { 288 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso); 289 } 290 291 if (0) { 292 DumpDebug(dc); 293 } 294 295 dc->gl.shaderCache = new RsdShaderCache(); 296 dc->gl.vertexArrayState = new RsdVertexArrayState(); 297 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs); 298 dc->gl.currentFrameBuffer = NULL; 299 300 LOGV("initGLThread end %p", rsc); 301 return true; 302} 303 304 305bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) { 306 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 307 308 EGLBoolean ret; 309 // WAR: Some drivers fail to handle 0 size surfaces correcntly. 310 // Use the pbuffer to avoid this pitfall. 311 if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) { 312 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 313 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 314 checkEglError("eglMakeCurrent", ret); 315 316 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 317 checkEglError("eglDestroySurface", ret); 318 319 dc->gl.egl.surface = NULL; 320 dc->gl.width = 1; 321 dc->gl.height = 1; 322 } 323 324 if (dc->gl.wndSurface != NULL) { 325 dc->gl.wndSurface->decStrong(NULL); 326 } 327 328 dc->gl.wndSurface = (ANativeWindow *)sur; 329 if (dc->gl.wndSurface != NULL) { 330 dc->gl.wndSurface->incStrong(NULL); 331 dc->gl.width = w; 332 dc->gl.height = h; 333 334 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 335 dc->gl.wndSurface, NULL); 336 checkEglError("eglCreateWindowSurface"); 337 if (dc->gl.egl.surface == EGL_NO_SURFACE) { 338 LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 339 } 340 341 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface, 342 dc->gl.egl.surface, dc->gl.egl.context); 343 checkEglError("eglMakeCurrent", ret); 344 } 345 return true; 346} 347 348void rsdGLSwap(const android::renderscript::Context *rsc) { 349 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 350 eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface); 351} 352 353void rsdGLCheckError(const android::renderscript::Context *rsc, 354 const char *msg, bool isFatal) { 355 GLenum err = glGetError(); 356 if (err != GL_NO_ERROR) { 357 char buf[1024]; 358 snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg); 359 360 if (isFatal) { 361 rsc->setError(RS_ERROR_FATAL_DRIVER, buf); 362 } else { 363 switch (err) { 364 case GL_OUT_OF_MEMORY: 365 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf); 366 break; 367 default: 368 rsc->setError(RS_ERROR_DRIVER, buf); 369 break; 370 } 371 } 372 373 LOGE("%p, %s", rsc, buf); 374 } 375 376} 377