rsdGL.cpp revision a277734efa210be16f3646bf9c66924e59876c86
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
485void rsdGLClearColor(const android::renderscript::Context *rsc,
486                     float r, float g, float b, float a) {
487    RSD_CALL_GL(glClearColor, r, g, b, a);
488    RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT);
489}
490
491void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) {
492    RSD_CALL_GL(glClearDepthf, v);
493    RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT);
494}
495
496void rsdGLFinish(const android::renderscript::Context *rsc) {
497    RSD_CALL_GL(glFinish);
498}
499
500void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc,
501                            float x1, float y1, float z1, float u1, float v1,
502                            float x2, float y2, float z2, float u2, float v2,
503                            float x3, float y3, float z3, float u3, float v3,
504                            float x4, float y4, float z4, float u4, float v4) {
505
506    float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
507    const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
508
509    RsdVertexArray::Attrib attribs[2];
510    attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
511    attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
512
513    RsdVertexArray va(attribs, 2);
514    va.setup(rsc);
515
516    RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4);
517}
518