rsdGL.cpp revision 5575cf16fa6e263ead96526683aed2f2cfd8ac96
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
20#include <system/window.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
44#include <gui/SurfaceTextureClient.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    struct EGLUtils {
53        static const char *strerror(EGLint err) {
54            switch (err){
55                case EGL_SUCCESS:           return "EGL_SUCCESS";
56                case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
57                case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
58                case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
59                case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
60                case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
61                case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
62                case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
63                case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
64                case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
65                case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
66                case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
67                case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
68                case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
69                case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
70                default: return "UNKNOWN";
71            }
72        }
73    };
74
75    if (returnVal != EGL_TRUE) {
76        fprintf(stderr, "%s() returned %d\n", op, returnVal);
77    }
78
79    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
80            = eglGetError()) {
81        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
82                error);
83    }
84}
85
86static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
87
88#define X(VAL) {VAL, #VAL}
89    struct {EGLint attribute; const char* name;} names[] = {
90    X(EGL_BUFFER_SIZE),
91    X(EGL_ALPHA_SIZE),
92    X(EGL_BLUE_SIZE),
93    X(EGL_GREEN_SIZE),
94    X(EGL_RED_SIZE),
95    X(EGL_DEPTH_SIZE),
96    X(EGL_STENCIL_SIZE),
97    X(EGL_CONFIG_CAVEAT),
98    X(EGL_CONFIG_ID),
99    X(EGL_LEVEL),
100    X(EGL_MAX_PBUFFER_HEIGHT),
101    X(EGL_MAX_PBUFFER_PIXELS),
102    X(EGL_MAX_PBUFFER_WIDTH),
103    X(EGL_NATIVE_RENDERABLE),
104    X(EGL_NATIVE_VISUAL_ID),
105    X(EGL_NATIVE_VISUAL_TYPE),
106    X(EGL_SAMPLES),
107    X(EGL_SAMPLE_BUFFERS),
108    X(EGL_SURFACE_TYPE),
109    X(EGL_TRANSPARENT_TYPE),
110    X(EGL_TRANSPARENT_RED_VALUE),
111    X(EGL_TRANSPARENT_GREEN_VALUE),
112    X(EGL_TRANSPARENT_BLUE_VALUE),
113    X(EGL_BIND_TO_TEXTURE_RGB),
114    X(EGL_BIND_TO_TEXTURE_RGBA),
115    X(EGL_MIN_SWAP_INTERVAL),
116    X(EGL_MAX_SWAP_INTERVAL),
117    X(EGL_LUMINANCE_SIZE),
118    X(EGL_ALPHA_MASK_SIZE),
119    X(EGL_COLOR_BUFFER_TYPE),
120    X(EGL_RENDERABLE_TYPE),
121    X(EGL_CONFORMANT),
122   };
123#undef X
124
125    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
126        EGLint value = -1;
127        EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
128        if (returnVal) {
129            ALOGV(" %s: %d (0x%x)", names[j].name, value, value);
130        }
131    }
132}
133
134static void DumpDebug(RsdHal *dc) {
135    ALOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion);
136    ALOGE(" EGL context %p  surface %p,  Display=%p", dc->gl.egl.context, dc->gl.egl.surface,
137         dc->gl.egl.display);
138    ALOGE(" GL vendor: %s", dc->gl.gl.vendor);
139    ALOGE(" GL renderer: %s", dc->gl.gl.renderer);
140    ALOGE(" GL Version: %s", dc->gl.gl.version);
141    ALOGE(" GL Extensions: %s", dc->gl.gl.extensions);
142    ALOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion);
143
144    ALOGV("MAX Textures %i, %i  %i", dc->gl.gl.maxVertexTextureUnits,
145         dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits);
146    ALOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs);
147    ALOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors,
148         dc->gl.gl.maxFragmentUniformVectors);
149    ALOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors);
150}
151
152void rsdGLShutdown(const Context *rsc) {
153    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
154
155    dc->gl.shaderCache->cleanupAll();
156    delete dc->gl.shaderCache;
157    delete dc->gl.vertexArrayState;
158
159    if (dc->gl.egl.context != EGL_NO_CONTEXT) {
160        RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display,
161                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
162        RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault);
163        if (dc->gl.egl.surface != EGL_NO_SURFACE) {
164            RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface);
165        }
166        RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context);
167        checkEglError("eglDestroyContext");
168    }
169
170    gGLContextCount--;
171    if (!gGLContextCount) {
172        RSD_CALL_GL(eglTerminate, dc->gl.egl.display);
173    }
174}
175
176bool rsdGLInit(const Context *rsc) {
177    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
178
179    dc->gl.egl.numConfigs = -1;
180    EGLint configAttribs[128];
181    EGLint *configAttribsPtr = configAttribs;
182    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
183
184    memset(configAttribs, 0, sizeof(configAttribs));
185
186    configAttribsPtr[0] = EGL_SURFACE_TYPE;
187    configAttribsPtr[1] = EGL_WINDOW_BIT;
188    configAttribsPtr += 2;
189
190    configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
191    configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
192    configAttribsPtr += 2;
193
194    configAttribsPtr[0] = EGL_RED_SIZE;
195    configAttribsPtr[1] = 8;
196    configAttribsPtr += 2;
197
198    configAttribsPtr[0] = EGL_GREEN_SIZE;
199    configAttribsPtr[1] = 8;
200    configAttribsPtr += 2;
201
202    configAttribsPtr[0] = EGL_BLUE_SIZE;
203    configAttribsPtr[1] = 8;
204    configAttribsPtr += 2;
205
206    if (rsc->mUserSurfaceConfig.alphaMin > 0) {
207        configAttribsPtr[0] = EGL_ALPHA_SIZE;
208        configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
209        configAttribsPtr += 2;
210    }
211
212    if (rsc->mUserSurfaceConfig.depthMin > 0) {
213        configAttribsPtr[0] = EGL_DEPTH_SIZE;
214        configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
215        configAttribsPtr += 2;
216    }
217
218    if (rsc->mDev->mForceSW) {
219        configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
220        configAttribsPtr[1] = EGL_SLOW_CONFIG;
221        configAttribsPtr += 2;
222    }
223
224    configAttribsPtr[0] = EGL_NONE;
225    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
226
227    ALOGV("%p initEGL start", rsc);
228    rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
229    dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
230    checkEglError("eglGetDisplay");
231
232    RSD_CALL_GL(eglInitialize, dc->gl.egl.display,
233                &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
234    checkEglError("eglInitialize");
235
236    EGLBoolean ret;
237
238    EGLint numConfigs = -1, n = 0;
239    rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
240    ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
241    checkEglError("eglGetConfigs", ret);
242
243    eglSwapInterval(dc->gl.egl.display, 0);
244
245    if (numConfigs) {
246        EGLConfig* const configs = new EGLConfig[numConfigs];
247
248        rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
249        ret = eglChooseConfig(dc->gl.egl.display,
250                configAttribs, configs, numConfigs, &n);
251        if (!ret || !n) {
252            checkEglError("eglChooseConfig", ret);
253            ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
254        }
255
256        // The first config is guaranteed to over-satisfy the constraints
257        dc->gl.egl.config = configs[0];
258
259        // go through the list and skip configs that over-satisfy our needs
260        for (int i=0 ; i<n ; i++) {
261            if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
262                EGLint alphaSize;
263                eglGetConfigAttrib(dc->gl.egl.display,
264                        configs[i], EGL_ALPHA_SIZE, &alphaSize);
265                if (alphaSize > 0) {
266                    continue;
267                }
268            }
269
270            if (rsc->mUserSurfaceConfig.depthMin <= 0) {
271                EGLint depthSize;
272                eglGetConfigAttrib(dc->gl.egl.display,
273                        configs[i], EGL_DEPTH_SIZE, &depthSize);
274                if (depthSize > 0) {
275                    continue;
276                }
277            }
278
279            // Found one!
280            dc->gl.egl.config = configs[i];
281            break;
282        }
283
284        delete [] configs;
285    }
286
287    //if (props.mLogVisual) {
288    if (0) {
289        printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
290    }
291    //}
292
293    rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
294    dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
295                                          EGL_NO_CONTEXT, context_attribs2);
296    checkEglError("eglCreateContext");
297    if (dc->gl.egl.context == EGL_NO_CONTEXT) {
298        ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
299        rsc->setWatchdogGL(NULL, 0, NULL);
300        return false;
301    }
302    gGLContextCount++;
303
304    sp<SurfaceTexture> st(new SurfaceTexture(123));
305    sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st));
306    dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
307                                                       static_cast<ANativeWindow*>(stc.get()),
308                                                       NULL);
309
310    checkEglError("eglCreateWindowSurface");
311    if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
312        ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
313        rsdGLShutdown(rsc);
314        rsc->setWatchdogGL(NULL, 0, NULL);
315        return false;
316    }
317
318    rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
319    ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
320                         dc->gl.egl.surfaceDefault, dc->gl.egl.context);
321    if (ret == EGL_FALSE) {
322        ALOGE("eglMakeCurrent returned EGL_FALSE");
323        checkEglError("eglMakeCurrent", ret);
324        rsdGLShutdown(rsc);
325        rsc->setWatchdogGL(NULL, 0, NULL);
326        return false;
327    }
328
329    dc->gl.gl.version = glGetString(GL_VERSION);
330    dc->gl.gl.vendor = glGetString(GL_VENDOR);
331    dc->gl.gl.renderer = glGetString(GL_RENDERER);
332    dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
333
334    //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
335    //ALOGV("GL Version %s", mGL.mVersion);
336    //ALOGV("GL Vendor %s", mGL.mVendor);
337    //ALOGV("GL Renderer %s", mGL.mRenderer);
338    //ALOGV("GL Extensions %s", mGL.mExtensions);
339
340    const char *verptr = NULL;
341    if (strlen((const char *)dc->gl.gl.version) > 9) {
342        if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
343            verptr = (const char *)dc->gl.gl.version + 12;
344        }
345        if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
346            verptr = (const char *)dc->gl.gl.version + 9;
347        }
348    }
349
350    if (!verptr) {
351        ALOGE("Error, OpenGL ES Lite not supported");
352        rsdGLShutdown(rsc);
353        rsc->setWatchdogGL(NULL, 0, NULL);
354        return false;
355    } else {
356        sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
357    }
358
359    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
360    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
361    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
362
363    glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
364    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
365
366    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
367    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
368
369    dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
370                                                "GL_OES_texture_npot");
371    dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
372                                                   "GL_IMG_texture_npot");
373    dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
374                                                            "GL_NV_texture_npot_2D_mipmap");
375    dc->gl.gl.EXT_texture_max_aniso = 1.0f;
376    bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
377                                   "GL_EXT_texture_filter_anisotropic");
378    if (hasAniso) {
379        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
380    }
381
382    if (0) {
383        DumpDebug(dc);
384    }
385
386    dc->gl.shaderCache = new RsdShaderCache();
387    dc->gl.vertexArrayState = new RsdVertexArrayState();
388    dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
389    dc->gl.currentFrameBuffer = NULL;
390    dc->mHasGraphics = true;
391
392    ALOGV("%p initGLThread end", rsc);
393    rsc->setWatchdogGL(NULL, 0, NULL);
394    return true;
395}
396
397
398bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
399    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
400
401    EGLBoolean ret;
402    // WAR: Some drivers fail to handle 0 size surfaces correcntly.
403    // Use the pbuffer to avoid this pitfall.
404    if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) {
405        rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
406        ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
407                             dc->gl.egl.surfaceDefault, dc->gl.egl.context);
408        checkEglError("eglMakeCurrent", ret);
409
410        rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
411        ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
412        checkEglError("eglDestroySurface", ret);
413
414        dc->gl.egl.surface = NULL;
415        dc->gl.width = 1;
416        dc->gl.height = 1;
417    }
418
419    if (dc->gl.wndSurface != NULL) {
420        dc->gl.wndSurface->decStrong(NULL);
421    }
422
423    dc->gl.wndSurface = (ANativeWindow *)sur;
424    if (dc->gl.wndSurface != NULL) {
425        dc->gl.wndSurface->incStrong(NULL);
426        dc->gl.width = w;
427        dc->gl.height = h;
428
429        rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
430        dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
431                                                    dc->gl.wndSurface, NULL);
432        checkEglError("eglCreateWindowSurface");
433        if (dc->gl.egl.surface == EGL_NO_SURFACE) {
434            ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
435        }
436
437        rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
438        ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
439                             dc->gl.egl.surface, dc->gl.egl.context);
440        checkEglError("eglMakeCurrent", ret);
441    }
442    rsc->setWatchdogGL(NULL, 0, NULL);
443    return true;
444}
445
446void rsdGLSwap(const android::renderscript::Context *rsc) {
447    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
448    RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
449}
450
451void rsdGLSetPriority(const Context *rsc, int32_t priority) {
452    if (priority > 0) {
453        // Mark context as low priority.
454        ALOGV("low pri");
455    } else {
456        ALOGV("normal pri");
457    }
458}
459
460void rsdGLCheckError(const android::renderscript::Context *rsc,
461                     const char *msg, bool isFatal) {
462    GLenum err = glGetError();
463    if (err != GL_NO_ERROR) {
464        char buf[1024];
465        snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
466
467        if (isFatal) {
468            rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
469        } else {
470            switch (err) {
471            case GL_OUT_OF_MEMORY:
472                rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
473                break;
474            default:
475                rsc->setError(RS_ERROR_DRIVER, buf);
476                break;
477            }
478        }
479
480        ALOGE("%p, %s", rsc, buf);
481    }
482
483}
484