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