/* * Copyright (c) 2017 Rob Clark * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "common.h" static struct gbm gbm; #ifdef HAVE_GBM_MODIFIERS static int get_modifiers(uint64_t **mods) { /* Assumed LINEAR is supported everywhere */ static uint64_t modifiers[] = {DRM_FORMAT_MOD_LINEAR}; *mods = modifiers; return 1; } #endif const struct gbm * init_gbm(int drm_fd, int w, int h, uint64_t modifier) { gbm.dev = gbm_create_device(drm_fd); #ifndef HAVE_GBM_MODIFIERS if (modifier != DRM_FORMAT_MOD_INVALID) { fprintf(stderr, "Modifiers requested but support isn't available\n"); return NULL; } gbm.surface = gbm_surface_create(gbm.dev, w, h, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); #else uint64_t *mods; int count; if (modifier != DRM_FORMAT_MOD_INVALID) { count = 1; mods = &modifier; } else { count = get_modifiers(&mods); } gbm.surface = gbm_surface_create_with_modifiers(gbm.dev, w, h, GBM_FORMAT_XRGB8888, mods, count); #endif if (!gbm.surface) { printf("failed to create gbm surface\n"); return NULL; } gbm.width = w; gbm.height = h; return &gbm; } int init_egl(struct egl *egl, const struct gbm *gbm) { EGLint major, minor, n; static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; static const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; #define get_proc(name) do { \ egl->name = (void *)eglGetProcAddress(#name); \ } while (0) get_proc(eglGetPlatformDisplayEXT); get_proc(eglCreateImageKHR); get_proc(eglDestroyImageKHR); get_proc(glEGLImageTargetTexture2DOES); get_proc(eglCreateSyncKHR); get_proc(eglDestroySyncKHR); get_proc(eglWaitSyncKHR); get_proc(eglDupNativeFenceFDANDROID); if (egl->eglGetPlatformDisplayEXT) { egl->display = egl->eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, gbm->dev, NULL); } else { egl->display = eglGetDisplay((void *)gbm->dev); } if (!eglInitialize(egl->display, &major, &minor)) { printf("failed to initialize\n"); return -1; } printf("Using display %p with EGL version %d.%d\n", egl->display, major, minor); printf("EGL Version \"%s\"\n", eglQueryString(egl->display, EGL_VERSION)); printf("EGL Vendor \"%s\"\n", eglQueryString(egl->display, EGL_VENDOR)); printf("EGL Extensions \"%s\"\n", eglQueryString(egl->display, EGL_EXTENSIONS)); if (!eglBindAPI(EGL_OPENGL_ES_API)) { printf("failed to bind api EGL_OPENGL_ES_API\n"); return -1; } if (!eglChooseConfig(egl->display, config_attribs, &egl->config, 1, &n) || n != 1) { printf("failed to choose config: %d\n", n); return -1; } egl->context = eglCreateContext(egl->display, egl->config, EGL_NO_CONTEXT, context_attribs); if (egl->context == NULL) { printf("failed to create context\n"); return -1; } egl->surface = eglCreateWindowSurface(egl->display, egl->config, (EGLNativeWindowType)gbm->surface, NULL); if (egl->surface == EGL_NO_SURFACE) { printf("failed to create egl surface\n"); return -1; } /* connect the context to the surface */ eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context); printf("GL Extensions: \"%s\"\n", glGetString(GL_EXTENSIONS)); return 0; } int create_program(const char *vs_src, const char *fs_src) { GLuint vertex_shader, fragment_shader, program; GLint ret; vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, &vs_src, NULL); glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &ret); if (!ret) { char *log; printf("vertex shader compilation failed!:\n"); glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &ret); if (ret > 1) { log = malloc(ret); glGetShaderInfoLog(vertex_shader, ret, NULL, log); printf("%s", log); } return -1; } fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, &fs_src, NULL); glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &ret); if (!ret) { char *log; printf("fragment shader compilation failed!:\n"); glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &ret); if (ret > 1) { log = malloc(ret); glGetShaderInfoLog(fragment_shader, ret, NULL, log); printf("%s", log); } return -1; } program = glCreateProgram(); glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); return program; } int link_program(unsigned program) { GLint ret; glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &ret); if (!ret) { char *log; printf("program linking failed!:\n"); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &ret); if (ret > 1) { log = malloc(ret); glGetProgramInfoLog(program, ret, NULL, log); printf("%s", log); } return -1; } return 0; }