mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 19:10:43 -05:00
renderer-native: Add hybrid GPU system support
A hybrid GPU system is a system where more than one GPU is connected to connectors. A common configuration is having a integrated GPU (iGPU) connected to a laptop panel, and a dedicated GPU (dGPU) connected to one or more external connector (such as HDMI). This commit adds support for rendering the compositor stage using the iGPU, then copying the framebuffer content onto a secondary framebuffer that will be page flipped on the CRTC of the dGPU. This can work in two different ways: GPU accelerated using Open GL ES 3, or CPU unaccelerated. When supported, GPU accelerated copying works by exporting the iGPU onscreen framebuffer as a DMA-BUF, importing it as a texture on a separate dGPU EGL context, then using glBlitFramebuffer(), blitting it onto a framebuffer on the dGPU that can then be page flipped on the dGPU CRTC. When GPU acceleration is not available, copying works by creating two dumb buffers, and each frame glReadPixels() from the iGPU EGL render context directly into the dumb buffer. The dumb buffer is then page flipped on the dGPU CRTC. https://bugzilla.gnome.org/show_bug.cgi?id=785381
This commit is contained in:
parent
492d2eb573
commit
c9259c2b15
@ -476,6 +476,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
||||
backends/native/meta-output-kms.h \
|
||||
backends/native/meta-renderer-native.c \
|
||||
backends/native/meta-renderer-native.h \
|
||||
backends/native/meta-renderer-native-gles3.c \
|
||||
backends/native/meta-renderer-native-gles3.h \
|
||||
backends/native/meta-stage-native.c \
|
||||
backends/native/meta-stage-native.h \
|
||||
backends/native/dbus-utils.c \
|
||||
|
169
src/backends/native/meta-renderer-native-gles3.c
Normal file
169
src/backends/native/meta-renderer-native-gles3.c
Normal file
@ -0,0 +1,169 @@
|
||||
/* -*- 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 <errno.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-gles3.h"
|
||||
#include "backends/meta-gles3-table.h"
|
||||
#include "backends/native/meta-renderer-native.h"
|
||||
|
||||
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,
|
||||
MetaGpuKms *gpu_kms,
|
||||
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));
|
||||
}
|
||||
}
|
47
src/backends/native/meta-renderer-native-gles3.h
Normal file
47
src/backends/native/meta-renderer-native-gles3.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef META_RENDERER_NATIVE_GLES3_H
|
||||
#define META_RENDERER_NATIVE_GLES3_H
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
#include "backends/meta-egl.h"
|
||||
#include "backends/meta-gles3.h"
|
||||
#include "backends/native/meta-gpu-kms.h"
|
||||
|
||||
gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
MetaGpuKms *gpu_kms,
|
||||
EGLDisplay egl_display,
|
||||
EGLContext egl_context,
|
||||
EGLSurface egl_surface,
|
||||
struct gbm_bo *shared_bo,
|
||||
GError **error);
|
||||
|
||||
void meta_renderer_native_gles3_read_pixels (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *target_data);
|
||||
|
||||
#endif /* META_RENDERER_NATIVE_GLES3_H */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user