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