/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2017 Red Hat * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #define GL_GLEXT_PROTOTYPES #include "backends/native/meta-renderer-native-gles3.h" #include #include #include #include #include "backends/meta-gles3.h" #include "backends/meta-gles3-table.h" /* * GL/gl.h being included may conflit with gl3.h on some architectures. * Make sure that hasn't happened on any architecture. */ #ifdef GL_VERSION_1_1 #error "Somehow included OpenGL headers when we shouldn't have" #endif static EGLImageKHR create_egl_image (MetaEgl *egl, EGLDisplay egl_display, EGLContext egl_context, unsigned int width, unsigned int height, uint32_t stride, uint32_t format, int fd, GError **error) { EGLint attributes[] = { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_LINUX_DRM_FOURCC_EXT, format, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, EGL_NONE }; return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attributes, error); } static void paint_egl_image (MetaGles3 *gles3, EGLImageKHR egl_image, int width, int height) { GLuint texture; GLuint framebuffer; meta_gles3_clear_error (gles3); GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); GLBAS (gles3, glGenTextures, (1, &texture)); GLBAS (gles3, glBindTexture, (GL_TEXTURE_2D, texture)); GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_2D, egl_image)); GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R_OES, GL_CLAMP_TO_EDGE)); GLBAS (gles3, glFramebufferTexture2D, (GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0)); GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); GLBAS (gles3, glBlitFramebuffer, (0, height, width, 0, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)); } gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, MetaGles3 *gles3, EGLDisplay egl_display, EGLContext egl_context, EGLSurface egl_surface, struct gbm_bo *shared_bo, GError **error) { int shared_bo_fd; unsigned int width; unsigned int height; uint32_t stride; uint32_t format; EGLImageKHR egl_image; shared_bo_fd = gbm_bo_get_fd (shared_bo); if (shared_bo_fd < 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to export gbm_bo: %s", strerror (errno)); return FALSE; } width = gbm_bo_get_width (shared_bo); height = gbm_bo_get_height (shared_bo); stride = gbm_bo_get_stride (shared_bo); format = gbm_bo_get_format (shared_bo); egl_image = create_egl_image (egl, egl_display, egl_context, width, height, stride, format, shared_bo_fd, error); close (shared_bo_fd); if (!egl_image) return FALSE; paint_egl_image (gles3, egl_image, width, height); meta_egl_destroy_image (egl, egl_display, egl_image, NULL); return TRUE; } void meta_renderer_native_gles3_read_pixels (MetaEgl *egl, MetaGles3 *gles3, int width, int height, uint8_t *target_data) { int y; GLBAS (gles3, glFinish, ()); for (y = 0; y < height; y++) { GLBAS (gles3, glReadPixels, (0, height - y, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, target_data + width * y * 4)); } }