blob: de9fb51f6aa9345986a4cea3808b3b6f676db68e [file] [log] [blame]
Jason Sams4b3de472011-04-06 17:52:23 -07001/*
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
Jason Sams4b3de472011-04-06 17:52:23 -070033#include <string.h>
34
Jason Sams4b3de472011-04-06 17:52:23 -070035#include "rsdCore.h"
36#include "rsdGL.h"
37
38#include <malloc.h>
39#include "rsContext.h"
Alex Sakhartchouka04e30d2011-04-29 16:49:08 -070040#include "rsdShaderCache.h"
41#include "rsdVertexArray.h"
Jason Sams4b3de472011-04-06 17:52:23 -070042
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
Jason Sams87fe59a2011-04-20 15:09:01 -0700109static void DumpDebug(RsdHal *dc) {
Jason Sams4b3de472011-04-06 17:52:23 -0700110 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) {
Jason Sams87fe59a2011-04-20 15:09:01 -0700128 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
Jason Sams4b3de472011-04-06 17:52:23 -0700129
Alex Sakhartchouka04e30d2011-04-29 16:49:08 -0700130 dc->gl.shaderCache->cleanupAll();
131 delete dc->gl.shaderCache;
132
133 delete dc->gl.vertexArrayState;
134
Jason Sams4b3de472011-04-06 17:52:23 -0700135 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) {
Jason Sams87fe59a2011-04-20 15:09:01 -0700154 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
Jason Sams4b3de472011-04-06 17:52:23 -0700155
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) {
Stephen Hines9db7fe22011-04-20 17:08:14 -0700204 if (0) {
Jason Sams4b3de472011-04-06 17:52:23 -0700205 printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
Stephen Hines9db7fe22011-04-20 17:08:14 -0700206 }
Jason Sams4b3de472011-04-06 17:52:23 -0700207 //}
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
Stephen Hines9db7fe22011-04-20 17:08:14 -0700290 if (0) {
291 DumpDebug(dc);
292 }
Jason Sams4b3de472011-04-06 17:52:23 -0700293
Alex Sakhartchouka04e30d2011-04-29 16:49:08 -0700294 dc->gl.shaderCache = new RsdShaderCache();
295 dc->gl.vertexArrayState = new RsdVertexArrayState();
296 dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
297
Jason Sams4b3de472011-04-06 17:52:23 -0700298 LOGV("initGLThread end %p", rsc);
299 return true;
300}
301
302
303bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur) {
Jason Sams87fe59a2011-04-20 15:09:01 -0700304 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
Jason Sams4b3de472011-04-06 17:52:23 -0700305
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) {
Jason Sams87fe59a2011-04-20 15:09:01 -0700342 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
Jason Sams4b3de472011-04-06 17:52:23 -0700343 eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface);
344}
345
Alex Sakhartchoukc19ff012011-05-06 14:59:45 -0700346void 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}