2017-07-24 22:21:04 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2017 Red Hat
|
2018-09-05 05:07:59 -04:00
|
|
|
* Copyright (c) 2018 DisplayLink (UK) Ltd.
|
2017-07-24 22:21:04 -04:00
|
|
|
*
|
|
|
|
* 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"
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include <GLES3/gl3.h>
|
2017-08-03 10:42:50 -04:00
|
|
|
#include <drm_fourcc.h>
|
2017-07-24 22:21:04 -04:00
|
|
|
#include <errno.h>
|
2017-10-30 04:08:12 -04:00
|
|
|
#include <gio/gio.h>
|
|
|
|
#include <string.h>
|
2017-07-24 22:21:04 -04:00
|
|
|
|
2017-08-03 10:42:50 -04:00
|
|
|
#include "backends/meta-egl-ext.h"
|
2017-07-24 22:21:04 -04:00
|
|
|
#include "backends/meta-gles3.h"
|
|
|
|
#include "backends/meta-gles3-table.h"
|
|
|
|
|
2017-10-30 04:08:46 -04:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2017-07-24 22:21:04 -04:00
|
|
|
static EGLImageKHR
|
|
|
|
create_egl_image (MetaEgl *egl,
|
|
|
|
EGLDisplay egl_display,
|
|
|
|
EGLContext egl_context,
|
|
|
|
unsigned int width,
|
|
|
|
unsigned int height,
|
2017-08-03 10:42:50 -04:00
|
|
|
uint32_t n_planes,
|
|
|
|
uint32_t *strides,
|
|
|
|
uint32_t *offsets,
|
|
|
|
uint64_t *modifiers,
|
2017-07-24 22:21:04 -04:00
|
|
|
uint32_t format,
|
|
|
|
int fd,
|
|
|
|
GError **error)
|
|
|
|
{
|
2017-08-03 10:42:50 -04:00
|
|
|
EGLint attribs[37];
|
|
|
|
int atti = 0;
|
|
|
|
gboolean has_modifier;
|
|
|
|
|
|
|
|
/* This requires the Mesa commit in
|
|
|
|
* Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
|
|
|
|
* Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
|
|
|
|
* Otherwise Mesa closes the fd behind our back and re-importing
|
|
|
|
* will fail.
|
|
|
|
* https://bugs.freedesktop.org/show_bug.cgi?id=76188
|
|
|
|
*/
|
|
|
|
|
|
|
|
attribs[atti++] = EGL_WIDTH;
|
|
|
|
attribs[atti++] = width;
|
|
|
|
attribs[atti++] = EGL_HEIGHT;
|
|
|
|
attribs[atti++] = height;
|
|
|
|
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
|
|
|
attribs[atti++] = format;
|
|
|
|
|
2018-02-19 13:36:22 -05:00
|
|
|
has_modifier = (modifiers[0] != DRM_FORMAT_MOD_INVALID &&
|
|
|
|
modifiers[0] != DRM_FORMAT_MOD_LINEAR);
|
2017-08-03 10:42:50 -04:00
|
|
|
|
|
|
|
if (n_planes > 0)
|
|
|
|
{
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
|
|
|
attribs[atti++] = fd;
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
|
|
|
attribs[atti++] = offsets[0];
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
|
|
|
attribs[atti++] = strides[0];
|
|
|
|
if (has_modifier)
|
|
|
|
{
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
|
|
|
attribs[atti++] = modifiers[0] & 0xFFFFFFFF;
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
|
|
|
attribs[atti++] = modifiers[0] >> 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n_planes > 1)
|
|
|
|
{
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
|
|
|
attribs[atti++] = fd;
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
|
|
|
attribs[atti++] = offsets[1];
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
|
|
|
attribs[atti++] = strides[1];
|
|
|
|
if (has_modifier)
|
|
|
|
{
|
2018-02-13 14:05:02 -05:00
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
2017-08-03 10:42:50 -04:00
|
|
|
attribs[atti++] = modifiers[1] & 0xFFFFFFFF;
|
2018-02-13 14:05:02 -05:00
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
2017-08-03 10:42:50 -04:00
|
|
|
attribs[atti++] = modifiers[1] >> 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n_planes > 2)
|
|
|
|
{
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
|
|
|
attribs[atti++] = fd;
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
|
|
|
attribs[atti++] = offsets[2];
|
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
|
|
|
attribs[atti++] = strides[2];
|
|
|
|
if (has_modifier)
|
|
|
|
{
|
2018-02-13 14:05:02 -05:00
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
2017-08-03 10:42:50 -04:00
|
|
|
attribs[atti++] = modifiers[2] & 0xFFFFFFFF;
|
2018-02-13 14:05:02 -05:00
|
|
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
2017-08-03 10:42:50 -04:00
|
|
|
attribs[atti++] = modifiers[2] >> 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
attribs[atti++] = EGL_NONE;
|
2017-07-24 22:21:04 -04:00
|
|
|
|
|
|
|
return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
|
|
|
EGL_LINUX_DMA_BUF_EXT, NULL,
|
2017-08-03 10:42:50 -04:00
|
|
|
attribs,
|
2017-07-24 22:21:04 -04:00
|
|
|
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;
|
2017-08-03 10:42:50 -04:00
|
|
|
uint32_t i, n_planes;
|
2018-02-13 14:05:02 -05:00
|
|
|
uint32_t strides[4] = { 0 };
|
|
|
|
uint32_t offsets[4] = { 0 };
|
|
|
|
uint64_t modifiers[4] = { 0 };
|
2017-07-24 22:21:04 -04:00
|
|
|
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);
|
|
|
|
format = gbm_bo_get_format (shared_bo);
|
|
|
|
|
2017-08-03 10:42:50 -04:00
|
|
|
n_planes = gbm_bo_get_plane_count (shared_bo);
|
|
|
|
for (i = 0; i < n_planes; i++)
|
|
|
|
{
|
|
|
|
strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i);
|
|
|
|
offsets[i] = gbm_bo_get_offset (shared_bo, i);
|
|
|
|
modifiers[i] = gbm_bo_get_modifier (shared_bo);
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:21:04 -04:00
|
|
|
egl_image = create_egl_image (egl,
|
|
|
|
egl_display,
|
|
|
|
egl_context,
|
2017-08-03 10:42:50 -04:00
|
|
|
width, height,
|
|
|
|
n_planes,
|
|
|
|
strides, offsets,
|
|
|
|
modifiers, format,
|
2017-07-24 22:21:04 -04:00
|
|
|
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;
|
|
|
|
}
|