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