From cffc6da294666022356a35e1731e698786c2bdd3 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Tue, 26 Oct 2021 19:24:17 +0900 Subject: Add gl-simple-dmabuf-egl Change-Id: Ibb776aeb4fa457de991d52cce1086703ff643a3d Signed-off-by: Joonbum Ko --- gl-novice/src/gl-simple-dmabuf-egl/CMakeLists.txt | 39 + .../gl-simple-dmabuf-egl-description.txt | 25 + .../gl-simple-dmabuf-egl/gl-simple-dmabuf-egl.c | 859 +++++++++++++++++++++ 3 files changed, 923 insertions(+) create mode 100755 gl-novice/src/gl-simple-dmabuf-egl/CMakeLists.txt create mode 100644 gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl-description.txt create mode 100644 gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl.c diff --git a/gl-novice/src/gl-simple-dmabuf-egl/CMakeLists.txt b/gl-novice/src/gl-simple-dmabuf-egl/CMakeLists.txt new file mode 100755 index 0000000..9e439ae --- /dev/null +++ b/gl-novice/src/gl-simple-dmabuf-egl/CMakeLists.txt @@ -0,0 +1,39 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +INCLUDE(FindPkgConfig) + +SET(TEST_NAME "gl-simple-dmabuf-egl") + +SET(SRCS + ${TEST_NAME}.c + +#please write your test sources +) + +pkg_check_modules(pkgs REQUIRED + glesv2 + egl + libtbm + wayland-egl + wayland-egl-tizen + wayland-client + glib-2.0 + ttrace + #please write require package +) + +ADD_DEFINITIONS(${pkgs_CFLAGS} -g) + +include_directories("../../include") + +ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.c ${SRCS}) +TARGET_LINK_LIBRARIES(${TEST_NAME} ${pkgs_LDFLAGS} -lm) + +INSTALL(PROGRAMS ${TEST_NAME} + DESTINATION /usr/local/bin/novice/${TEST_NAME} +) +INSTALL(FILES ${TEST_NAME}-description.txt + DESTINATION /usr/local/bin/novice/${TEST_NAME} +) + +SET(CMAKE_C_FLAGS " -fPIE -Wall") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib -pie") diff --git a/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl-description.txt b/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl-description.txt new file mode 100644 index 0000000..b82d5c7 --- /dev/null +++ b/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl-description.txt @@ -0,0 +1,25 @@ +Title +#Please write your test program Title +#========================================================================== +GL resize test. + +Date +#Please write Date +#========================================================================== +2017-07-26 + +Author +#Please write Author +#========================================================================== +Joonbum Ko + +Module +#Please write your test program Module +#========================================================================== +GL + +Description +#Please write your test program detail description +#========================================================================== +It is a test sample that sleep one second after rendering one frame and proceeds +to resize the next frame. diff --git a/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl.c b/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl.c new file mode 100644 index 0000000..41bb054 --- /dev/null +++ b/gl-novice/src/gl-simple-dmabuf-egl/gl-simple-dmabuf-egl.c @@ -0,0 +1,859 @@ +/* + * Copyright © 2011 Benjamin Franzke + * Copyright © 2010 Intel Corporation + * Copyright © 2014,2018 Collabora Ltd. + * + * 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, sublicense, 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 + * NONINFRINGEMENT. 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "egl-helpers.h" +#include "helpers.h" + + +#define BUFFER_FORMAT TBM_FORMAT_ARGB8888 +#define MAX_BUFFER_PLANES 4 + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + + struct { + EGLDisplay display; + EGLContext context; + EGLConfig conf; + bool has_dma_buf_import_modifiers; + //PFNEGLQUERYDMABUFMODIFIERSEXTPROC query_dma_buf_modifiers; + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; + } egl; + + tbm_bufmgr bufmgr; +}; + +struct buffer { + struct display *display; + + tbm_surface_h tbm_surface; + + int width; + int height; + int format; + uint64_t modifier; + int plane_count; + int dmabuf_fds[MAX_BUFFER_PLANES]; + uint32_t strides[MAX_BUFFER_PLANES]; + uint32_t offsets[MAX_BUFFER_PLANES]; + + EGLImageKHR egl_image; + GLuint gl_texture; + GLuint gl_fbo; +}; + +#define NUM_BUFFERS 3 + +struct window { + struct display *display; + int width, height; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct buffer buffers[NUM_BUFFERS]; + struct wl_callback *callback; + struct wl_egl_window *native; + bool initialized; + bool wait_for_configure; + struct { + GLuint program; + GLuint pos; + GLuint color; + GLuint offset_uniform; + } gl; + + struct { + EGLSurface surface; + } egl; + + int current_idx; +}; + +static sig_atomic_t running = 1; + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time); + + +static void +buffer_free(struct buffer *buf) +{ + if (buf->gl_fbo) + glDeleteFramebuffers(1, &buf->gl_fbo); + + if (buf->gl_texture) + glDeleteTextures(1, &buf->gl_texture); + + if (buf->egl_image) { + buf->display->egl.destroy_image(buf->display->egl.display, + buf->egl_image); + } + + if (buf->tbm_surface) + tbm_surface_destroy(buf->tbm_surface); + +} + +static bool +create_fbo_for_buffer(struct display *display, struct buffer *buffer) +{ + static const int general_attribs = 3; + static const int plane_attribs = 5; + static const int entries_per_attrib = 2; + EGLint attribs[(general_attribs + plane_attribs * MAX_BUFFER_PLANES) * + entries_per_attrib + 1]; + unsigned int atti = 0; + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = buffer->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = buffer->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = buffer->format; + +#define ADD_PLANE_ATTRIBS(plane_idx) { \ + attribs[atti++] = EGL_DMA_BUF_PLANE ## plane_idx ## _FD_EXT; \ + attribs[atti++] = buffer->dmabuf_fds[plane_idx]; \ + attribs[atti++] = EGL_DMA_BUF_PLANE ## plane_idx ## _OFFSET_EXT; \ + attribs[atti++] = (int) buffer->offsets[plane_idx]; \ + attribs[atti++] = EGL_DMA_BUF_PLANE ## plane_idx ## _PITCH_EXT; \ + attribs[atti++] = (int) buffer->strides[plane_idx]; \ + } + + if (buffer->plane_count > 0) + ADD_PLANE_ATTRIBS(0); + + if (buffer->plane_count > 1) + ADD_PLANE_ATTRIBS(1); + + if (buffer->plane_count > 2) + ADD_PLANE_ATTRIBS(2); + +#undef ADD_PLANE_ATTRIBS + + attribs[atti] = EGL_NONE; + + assert(atti < ARRAY_LENGTH(attribs)); + + buffer->egl_image = display->egl.create_image(display->egl.display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, attribs); + if (buffer->egl_image == EGL_NO_IMAGE_KHR) { + fprintf(stderr, "EGLImageKHR creation failed\n"); + return false; + } + + //eglMakeCurrent(display->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + // display->egl.context); + + glGenTextures(1, &buffer->gl_texture); + glBindTexture(GL_TEXTURE_2D, buffer->gl_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + display->egl.image_target_texture_2d(GL_TEXTURE_2D, buffer->egl_image); + + glGenFramebuffers(1, &buffer->gl_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, buffer->gl_fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, buffer->gl_texture, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "FBO creation failed\n"); + return false; + } + + return true; + + return true; +} + +static int +create_tbm_buffer(struct display *display, struct buffer *buffer, + int width, int height, uint32_t opts) +{ + int i = 0; + + buffer->display = display; + buffer->width = width; + buffer->height = height; + buffer->format = BUFFER_FORMAT; + + if (buffer->tbm_surface == NULL) + buffer->tbm_surface = tbm_surface_create(buffer->width, + buffer->height, + buffer->format); + + if (!buffer->tbm_surface) { + fprintf(stderr, "create_tbm_buffer failed\n"); + goto error; + } + + buffer->plane_count = tbm_surface_internal_get_num_planes(buffer->format); + + for (i = 0; i < buffer->plane_count; ++i) { + int bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer->tbm_surface, i); + tbm_bo bo = tbm_surface_internal_get_bo(buffer->tbm_surface, bo_idx); + + buffer->dmabuf_fds[i] = tbm_bo_export_fd(bo); + + tbm_surface_internal_get_plane_data(buffer->tbm_surface, i, + NULL, + &buffer->offsets[i], + &buffer->strides[i]); + } + + if (!create_fbo_for_buffer(display, buffer)) + goto error; + + return 0; + +error: + buffer_free(buffer); + return -1; +} + +static void +handle_ping(void *data, struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong(shell_surface, serial); +} + +static void +handle_configure(void *data, struct wl_shell_surface *shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ + struct window *window = data; + + if (window->initialized && window->wait_for_configure) + redraw(window, NULL, 0); + window->wait_for_configure = false; + +} + +static void +handle_popup_done(void *data, struct wl_shell_surface *shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, + handle_configure, + handle_popup_done +}; + + +static const char *vert_shader_text = + "uniform float offset;\n" + "attribute vec4 pos;\n" + "attribute vec4 color;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_Position = pos + vec4(offset, offset, 0.0, 0.0);\n" + " v_color = color;\n" + "}\n"; + +static const char *frag_shader_text = + "precision mediump float;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_FragColor = v_color;\n" + "}\n"; + + +static GLuint +create_shader(const char *source, GLenum shader_type) +{ + GLuint shader; + GLint status; + + shader = glCreateShader(shader_type); + assert(shader != 0); + + glShaderSource(shader, 1, (const char **) &source, NULL); + glCompileShader(shader); + + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (!status) { + char log[1000]; + GLsizei len; + glGetShaderInfoLog(shader, 1000, &len, log); + fprintf(stderr, "Error: compiling %s: %.*s\n", + shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", + len, log); + return 0; + } + + return shader; +} + +static GLuint +create_and_link_program(GLuint vert, GLuint frag) +{ + GLint status; + GLuint program = glCreateProgram(); + + glAttachShader(program, vert); + glAttachShader(program, frag); + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + if (!status) { + char log[1000]; + GLsizei len; + glGetProgramInfoLog(program, 1000, &len, log); + fprintf(stderr, "Error: linking:\n%.*s\n", len, log); + return 0; + } + + return program; +} + +static bool +window_set_up_gl(struct window *window) +{ + EGLBoolean ret; + + assert(ret); + + GLuint vert = create_shader(vert_shader_text, + GL_VERTEX_SHADER); + GLuint frag = create_shader(frag_shader_text, + GL_FRAGMENT_SHADER); + + window->gl.program = create_and_link_program(vert, frag); + + glDeleteShader(vert); + glDeleteShader(frag); + + window->gl.pos = glGetAttribLocation(window->gl.program, "pos"); + window->gl.color = glGetAttribLocation(window->gl.program, "color"); + + glUseProgram(window->gl.program); + + window->gl.offset_uniform = + glGetUniformLocation(window->gl.program, "offset"); + + return window->gl.program != 0; +} + +static void +destroy_window(struct window *window) +{ + int i; + + eglMakeCurrent(window->display->egl.display, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + if (window->egl.surface) + platform_destroy_egl_surface(window->display->egl.display, + window->egl.surface); + + if (window->native) + wl_egl_window_destroy(window->native); + + if (window->gl.program) + glDeleteProgram(window->gl.program); + + if (window->callback) + wl_callback_destroy(window->callback); + + for (i = 0; i < NUM_BUFFERS; i++) { + buffer_free(&window->buffers[i]); + } + + wl_shell_surface_destroy(window->shell_surface); + + wl_surface_destroy(window->surface); + free(window); +} + +static struct window * +create_window(struct display *display, int width, int height, int opts) +{ + struct window *window; + int i; + int ret; + + window = (struct window *)calloc(1, sizeof(struct window)); + if (!window) + return NULL; + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->current_idx = 0; + window->surface = wl_compositor_create_surface(display->compositor); + + if (display->shell) { + window->shell_surface = wl_shell_get_shell_surface(display->shell, + window->surface); + + assert(window->shell_surface); + + wl_shell_surface_add_listener(window->shell_surface, + &shell_surface_listener, window); + + wl_shell_surface_set_title(window->shell_surface, "simple-dmabuf-egl"); + + window->wait_for_configure = true; + + window->native = wl_egl_window_create(window->surface, + window->width, + window->height); + window->egl.surface = + platform_create_egl_surface(display->egl.display, + display->egl.conf, + window->native, NULL); + ret = eglMakeCurrent(window->display->egl.display, window->egl.surface, + window->egl.surface, window->display->egl.context); + assert(ret); + + } else { + assert(0); + } + + for (i = 0; i < NUM_BUFFERS; ++i) { + window->buffers[i].tbm_surface = NULL; + } + + for (i = 0; i < NUM_BUFFERS; ++i) { + ret = create_tbm_buffer(display, &window->buffers[i], + width, height, opts); + + if (ret < 0) + goto error; + } + + if (!window_set_up_gl(window)) + goto error; + + return window; + +error: + if (window) + destroy_window(window); + + return NULL; +} + +static struct buffer * +window_next_buffer(struct window *window) +{ + int i = window->current_idx; + + window->current_idx++; + + if (window->current_idx >= NUM_BUFFERS) { + window->current_idx = 0; + } + + return &window->buffers[i]; +} + +static const struct wl_callback_listener frame_listener; + +/* Renders a square moving from the lower left corner to the + * upper right corner of the window. The square's vertices have + * the following colors: + * + * green +-----+ yellow + * | | + * | | + * red +-----+ blue + */ +static void +render(struct window *window, struct buffer *buffer) +{ + /* Complete a movement iteration in 5000 ms. */ + static const uint64_t iteration_ms = 5000; + static const GLfloat verts[4][2] = { + { -0.5, -0.5 }, + { -0.5, 0.5 }, + { 0.5, -0.5 }, + { 0.5, 0.5 } + }; + static const GLfloat colors[4][3] = { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 1, 1, 0 } + }; + GLfloat offset; + struct timeval tv; + uint64_t time_ms; + + gettimeofday(&tv, NULL); + time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + /* Split time_ms in repeating windows of [0, iteration_ms) and map them + * to offsets in the [-0.5, 0.5) range. */ + offset = (time_ms % iteration_ms) / (float) iteration_ms - 0.5; + + /* Direct all GL draws to the buffer through the FBO */ + glBindFramebuffer(GL_FRAMEBUFFER, buffer->gl_fbo); + + glViewport(0, 0, window->width, window->height); + + glUniform1f(window->gl.offset_uniform, offset); + + glClearColor(0.0,0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(window->gl.color, 3, GL_FLOAT, GL_FALSE, 0, colors); + glEnableVertexAttribArray(window->gl.pos); + glEnableVertexAttribArray(window->gl.color); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(window->gl.pos); + glDisableVertexAttribArray(window->gl.color); + + glFinish(); + + { + char name[50]; + snprintf(name, sizeof(name), "tbm_surface_%p_%d_x_%d", buffer->tbm_surface, buffer->width, buffer->height); + tbm_surface_internal_capture_buffer(buffer->tbm_surface, "/tmp/gl-novice", name, "png"); + } + +} + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + struct window *window = data; + struct buffer *buffer; + char name[50]; + int ret; + + buffer = window_next_buffer(window); + if (!buffer) { + fprintf(stderr, + !callback ? "Failed to create the first buffer.\n" : + "All buffers busy at redraw(). Server bug?\n"); + abort(); + } + ret = eglMakeCurrent(window->display->egl.display, window->egl.surface, + window->egl.surface, window->display->egl.context); + assert(ret); + + render(window, buffer); + + //window->callback = wl_surface_frame(window->surface); + //wl_callback_add_listener(window->callback, &frame_listener, window); + +#if 0 + //glFinish(); + + snprintf(name, sizeof(name), "tbm_surface_%p_%d_x_%d", buffer->tbm_surface, buffer->width, buffer->height); + tbm_surface_internal_capture_buffer(buffer->tbm_surface, "/tmp/gl-novice", name, "png"); +#else + ret = eglSwapBuffers(buffer->display->egl.display, window->egl.surface); + if (!ret) + printf("Failed to succeed eglSwapBuffers\n"); +#endif +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shell") == 0) { + d->shell = wl_registry_bind(registry, id, + &wl_shell_interface, 1); + } +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static void +destroy_display(struct display *display) +{ + printf("destroy_display %d\n", display->egl.display); + if (display->egl.context != EGL_NO_CONTEXT) + eglDestroyContext(display->egl.display, display->egl.context); + + if (display->egl.display != EGL_NO_DISPLAY) + eglTerminate(display->egl.display); + + if (display->shell) + wl_shell_destroy(display->shell); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + if (display->registry) + wl_registry_destroy(display->registry); + + if (display->bufmgr) + tbm_bufmgr_deinit(display->bufmgr); + + if (display->display) { + wl_display_flush(display->display); + wl_display_disconnect(display->display); + } + + free(display); +} + +static bool +display_set_up_egl(struct display *display) +{ + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint major, minor, ret, count; + const char *egl_extensions = NULL; + + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + display->egl.display = eglGetDisplay(display->display); + + if (display->egl.display == EGL_NO_DISPLAY) { + fprintf(stderr, "Failed to create EGLDisplay\n"); + goto error; + } + + if (eglInitialize(display->egl.display, &major, &minor) == EGL_FALSE) { + fprintf(stderr, "Failed to initialize EGLDisplay\n"); + goto error; + } + + if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { + fprintf(stderr, "Failed to bind OpenGL ES API\n"); + goto error; + } + + egl_extensions = eglQueryString(display->egl.display, EGL_EXTENSIONS); + assert(egl_extensions != NULL); + + if (!check_egl_extension(egl_extensions, + "EGL_EXT_image_dma_buf_import")) { + fprintf(stderr, "EGL_EXT_image_dma_buf_import not supported\n"); + goto error; + } + + if (!check_egl_extension(egl_extensions, + "EGL_KHR_surfaceless_context")) { + fprintf(stderr, "EGL_KHR_surfaceless_context not supported\n"); + goto error; + } + + ret = eglChooseConfig(display->egl.display, config_attribs, + &display->egl.conf, 1, &count); + assert(ret && count >= 1); + + display->egl.context = eglCreateContext(display->egl.display, + display->egl.conf, + EGL_NO_CONTEXT, + context_attribs); + if (display->egl.context == EGL_NO_CONTEXT) { + fprintf(stderr, "Failed to create EGLContext\n"); + goto error; + } +#if 0 + eglMakeCurrent(display->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + display->egl.context); + + if (check_egl_extension(egl_extensions, + "EGL_EXT_image_dma_buf_import_modifiers")) { + display->egl.has_dma_buf_import_modifiers = true; + display->egl.query_dma_buf_modifiers = + (void *) eglGetProcAddress("eglQueryDmaBufModifiersEXT"); + assert(display->egl.query_dma_buf_modifiers); + } +#endif + display->egl.create_image = + (void *) eglGetProcAddress("eglCreateImageKHR"); + assert(display->egl.create_image); + + display->egl.destroy_image = + (void *) eglGetProcAddress("eglDestroyImageKHR"); + assert(display->egl.destroy_image); + + display->egl.image_target_texture_2d = + (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); + assert(display->egl.image_target_texture_2d); + + return true; + +error: + return false; +} + +static struct display * +create_display() +{ + struct display *display = NULL; + + display = (struct display *)calloc(1, sizeof(struct display)); + if (display == NULL) { + fprintf(stderr, "out of memory\n"); + goto error; + } + + display->bufmgr = tbm_bufmgr_init(-1); + + display->display = wl_display_connect(NULL); + assert(display->display); + + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + + if (!display_set_up_egl(display)) + goto error; + + return display; + +error: + if (display != NULL) + destroy_display(display); + return NULL; +} + +static void +signal_int(int signum) +{ + running = 0; +} + +int +main(int argc, char **argv) +{ + struct sigaction sigint; + struct display *display; + struct window *window; + int opts = 0; + char const *drm_render_node = "/dev/dri/renderD128"; + int ret = 0; + int window_size = 256; + + + display = create_display(); + if (!display) + return 1; + + window = create_window(display, window_size, window_size, opts); + if (!window) + return 1; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Here we retrieve the linux-dmabuf objects if executed without immed, + * or error */ + wl_display_roundtrip(display->display); + + if (!running) + return 1; + + window->initialized = true; + + //if (!window->wait_for_configure) + redraw(window, NULL, 0); + + while (running && ret != -1) { + ret = wl_display_dispatch_pending(display->display); + redraw(window, NULL, 0); + } + + fprintf(stderr, "simple-egl-tbm-fbo exiting\n"); + destroy_window(window); + destroy_display(display); + + return 0; +} -- cgit v1.2.3