rsdGL.cpp revision 87fe59a2f4d4c74539bfa0bff5f9a7e320e99415
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 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 LOGV("%p, deinitEGL", rsc); 132 133 if (dc->gl.egl.context != EGL_NO_CONTEXT) { 134 eglMakeCurrent(dc->gl.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 135 eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surfaceDefault); 136 if (dc->gl.egl.surface != EGL_NO_SURFACE) { 137 eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 138 } 139 eglDestroyContext(dc->gl.egl.display, dc->gl.egl.context); 140 checkEglError("eglDestroyContext"); 141 } 142 143 gGLContextCount--; 144 if (!gGLContextCount) { 145 eglTerminate(dc->gl.egl.display); 146 } 147} 148 149bool rsdGLInit(const Context *rsc) { 150 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 151 152 dc->gl.egl.numConfigs = -1; 153 EGLint configAttribs[128]; 154 EGLint *configAttribsPtr = configAttribs; 155 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 156 157 memset(configAttribs, 0, sizeof(configAttribs)); 158 159 configAttribsPtr[0] = EGL_SURFACE_TYPE; 160 configAttribsPtr[1] = EGL_WINDOW_BIT; 161 configAttribsPtr += 2; 162 163 configAttribsPtr[0] = EGL_RENDERABLE_TYPE; 164 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; 165 configAttribsPtr += 2; 166 167 if (rsc->mUserSurfaceConfig.depthMin > 0) { 168 configAttribsPtr[0] = EGL_DEPTH_SIZE; 169 configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin; 170 configAttribsPtr += 2; 171 } 172 173 if (rsc->mDev->mForceSW) { 174 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 175 configAttribsPtr[1] = EGL_SLOW_CONFIG; 176 configAttribsPtr += 2; 177 } 178 179 configAttribsPtr[0] = EGL_NONE; 180 rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); 181 182 LOGV("%p initEGL start", rsc); 183 dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 184 checkEglError("eglGetDisplay"); 185 186 eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion); 187 checkEglError("eglInitialize"); 188 189 PixelFormat pf = PIXEL_FORMAT_RGBA_8888; 190 if (rsc->mUserSurfaceConfig.alphaMin == 0) { 191 pf = PIXEL_FORMAT_RGBX_8888; 192 } 193 194 status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs, 195 pf, &dc->gl.egl.config); 196 if (err) { 197 LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc); 198 } 199 //if (props.mLogVisual) { 200 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config); 201 //} 202 203 dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config, 204 EGL_NO_CONTEXT, context_attribs2); 205 checkEglError("eglCreateContext"); 206 if (dc->gl.egl.context == EGL_NO_CONTEXT) { 207 LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc); 208 return false; 209 } 210 gGLContextCount++; 211 212 213 EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 214 dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config, 215 pbuffer_attribs); 216 checkEglError("eglCreatePbufferSurface"); 217 if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) { 218 LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE"); 219 rsdGLShutdown(rsc); 220 return false; 221 } 222 223 EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 224 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 225 if (ret == EGL_FALSE) { 226 LOGE("eglMakeCurrent returned EGL_FALSE"); 227 checkEglError("eglMakeCurrent", ret); 228 rsdGLShutdown(rsc); 229 return false; 230 } 231 232 dc->gl.gl.version = glGetString(GL_VERSION); 233 dc->gl.gl.vendor = glGetString(GL_VENDOR); 234 dc->gl.gl.renderer = glGetString(GL_RENDERER); 235 dc->gl.gl.extensions = glGetString(GL_EXTENSIONS); 236 237 //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 238 //LOGV("GL Version %s", mGL.mVersion); 239 //LOGV("GL Vendor %s", mGL.mVendor); 240 //LOGV("GL Renderer %s", mGL.mRenderer); 241 //LOGV("GL Extensions %s", mGL.mExtensions); 242 243 const char *verptr = NULL; 244 if (strlen((const char *)dc->gl.gl.version) > 9) { 245 if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) { 246 verptr = (const char *)dc->gl.gl.version + 12; 247 } 248 if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) { 249 verptr = (const char *)dc->gl.gl.version + 9; 250 } 251 } 252 253 if (!verptr) { 254 LOGE("Error, OpenGL ES Lite not supported"); 255 rsdGLShutdown(rsc); 256 return false; 257 } else { 258 sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion); 259 } 260 261 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs); 262 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors); 263 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits); 264 265 glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors); 266 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits); 267 268 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits); 269 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors); 270 271 dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 272 "GL_OES_texture_npot"); 273 dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, 274 "GL_IMG_texture_npot"); 275 dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, 276 "GL_NV_texture_npot_2D_mipmap"); 277 dc->gl.gl.EXT_texture_max_aniso = 1.0f; 278 bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, 279 "GL_EXT_texture_filter_anisotropic"); 280 if (hasAniso) { 281 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso); 282 } 283 284 DumpDebug(dc); 285 286 LOGV("initGLThread end %p", rsc); 287 return true; 288} 289 290 291bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur) { 292 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 293 294 EGLBoolean ret; 295 // WAR: Some drivers fail to handle 0 size surfaces correcntly. 296 // Use the pbuffer to avoid this pitfall. 297 if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) { 298 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault, 299 dc->gl.egl.surfaceDefault, dc->gl.egl.context); 300 checkEglError("eglMakeCurrent", ret); 301 302 ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface); 303 checkEglError("eglDestroySurface", ret); 304 305 dc->gl.egl.surface = NULL; 306 dc->gl.width = 1; 307 dc->gl.height = 1; 308 } 309 310 dc->gl.wndSurface = sur; 311 if (dc->gl.wndSurface != NULL) { 312 dc->gl.width = w; 313 dc->gl.height = h; 314 315 dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config, 316 dc->gl.wndSurface, NULL); 317 checkEglError("eglCreateWindowSurface"); 318 if (dc->gl.egl.surface == EGL_NO_SURFACE) { 319 LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 320 } 321 322 ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface, 323 dc->gl.egl.surface, dc->gl.egl.context); 324 checkEglError("eglMakeCurrent", ret); 325 } 326 return true; 327} 328 329void rsdGLSwap(const android::renderscript::Context *rsc) { 330 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 331 eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface); 332} 333 334