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