mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
wip! renderer/native: start to add stream copy mode
At the moment, mutter only supports using GBM for doing GPU blits to secondary video cards. This commit starts to sketch out using eglstreams for doing the copy. FIXME: in order to get memcpy fastpath we get inverted colors and have to fix it up in the shader. FIXME: need to move some of the globals to be in a more structured place Closes https://gitlab.gnome.org/GNOME/mutter/issues/205
This commit is contained in:
parent
8f538671d6
commit
82f03c51ac
@ -179,6 +179,97 @@ paint_egl_image (MetaGles3 *gles3,
|
||||
GL_NEAREST));
|
||||
}
|
||||
|
||||
/* FIXME: all these declarations are just floating here
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) position
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) texture_coordinate
|
||||
{
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) vertex
|
||||
{
|
||||
struct position position;
|
||||
struct texture_coordinate texture_coordinate;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) triangle
|
||||
{
|
||||
unsigned int first_vertex;
|
||||
unsigned int middle_vertex;
|
||||
unsigned int last_vertex;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RIGHT_TOP_VERTEX = 0,
|
||||
BOTTOM_RIGHT_VERTEX,
|
||||
BOTTOM_LEFT_VERTEX,
|
||||
TOP_LEFT_VERTEX
|
||||
};
|
||||
|
||||
static const float view_left = -1.0f, view_right = 1.0f, view_top = 1.0f, view_bottom = -1.0f;
|
||||
static const float texture_left = 0.0f, texture_right = 1.0f, texture_top = 0.0f, texture_bottom = 1.0f;
|
||||
static GLuint vertex_array;
|
||||
static GLuint vertex_buffer;
|
||||
static GLuint triangle_buffer;
|
||||
|
||||
struct vertex vertices[] = {
|
||||
[RIGHT_TOP_VERTEX] = {{view_right, view_top},
|
||||
{texture_right, texture_top}},
|
||||
[BOTTOM_RIGHT_VERTEX] = {{view_right, view_bottom},
|
||||
{texture_right, texture_bottom}},
|
||||
[BOTTOM_LEFT_VERTEX] = {{view_left, view_bottom},
|
||||
{texture_left, texture_bottom}},
|
||||
[TOP_LEFT_VERTEX] = {{view_left, view_top},
|
||||
{texture_left, texture_top}},
|
||||
};
|
||||
|
||||
struct triangle triangles[] = {
|
||||
{TOP_LEFT_VERTEX, BOTTOM_RIGHT_VERTEX, BOTTOM_LEFT_VERTEX},
|
||||
{TOP_LEFT_VERTEX, RIGHT_TOP_VERTEX, BOTTOM_RIGHT_VERTEX},
|
||||
};
|
||||
|
||||
gboolean
|
||||
meta_renderer_native_gles3_draw_pixels (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
uint8_t *pixels,
|
||||
GError **error)
|
||||
{
|
||||
meta_gles3_clear_error (gles3);
|
||||
|
||||
GLBAS (gles3, glClearColor, (0.0,1.0,0.0,1.0));
|
||||
GLBAS (gles3, glClear, (GL_COLOR_BUFFER_BIT));
|
||||
|
||||
GLBAS (gles3, glViewport, (0, 0, width, height));
|
||||
GLBAS (gles3, glTexImage2D, (GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
width, height, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
GLBAS (gles3, glBindBuffer, (GL_ARRAY_BUFFER, vertex_buffer));
|
||||
GLBAS (gles3, glEnableVertexAttribArray, (0));
|
||||
GLBAS (gles3, glVertexAttribPointer, (0,
|
||||
sizeof (struct position) / sizeof (float), GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof (struct vertex), (void *) offsetof (struct vertex, position)));
|
||||
GLBAS (gles3, glEnableVertexAttribArray, (1));
|
||||
GLBAS (gles3, glVertexAttribPointer, (1,
|
||||
sizeof (struct texture_coordinate) / sizeof (float), GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof (struct vertex), (void *) offsetof (struct vertex, texture_coordinate)));
|
||||
GLBAS (gles3, glDrawElements, (GL_TRIANGLES,
|
||||
G_N_ELEMENTS (triangles) * (sizeof (struct triangle) / sizeof (unsigned int)), GL_UNSIGNED_INT,
|
||||
0));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
@ -238,3 +329,126 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_native_gles3_load_basic_shaders (MetaEgl *egl,
|
||||
MetaGles3 *gles3)
|
||||
{
|
||||
GLuint vertex_shader = 0, fragment_shader = 0, shader_program;
|
||||
gboolean status = FALSE;
|
||||
const char *vertex_shader_source =
|
||||
"#version 330 core\n"
|
||||
"layout (location = 0) in vec2 position;\n"
|
||||
"layout (location = 1) in vec2 input_texture_coords;\n"
|
||||
"out vec2 texture_coords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);\n"
|
||||
" texture_coords = input_texture_coords;\n"
|
||||
"}\n";
|
||||
|
||||
const char *fragment_shader_source =
|
||||
"#version 330 core\n"
|
||||
"uniform sampler2D input_texture;\n"
|
||||
"in vec2 texture_coords;\n"
|
||||
"out vec4 output_color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
/* FIXME: cogl uses a framebuffer format of COGL_PIXEL_FORMAT_RGBA_8888_PRE
|
||||
* by default which maps to DRM_FORMAT_ABGR8888 on little endian. The
|
||||
* destination format is DRM_FORMAT_XRGB8888, so the color channels are
|
||||
* swapped. The .bgra swizzle here swaps it back, but we should see if
|
||||
* we can find a better fix (this probably breaks on big endian) */
|
||||
" output_color = texture(input_texture, texture_coords).bgra;\n"
|
||||
"}\n";
|
||||
|
||||
vertex_shader = glCreateShader (GL_VERTEX_SHADER);
|
||||
glShaderSource (vertex_shader, 1, &vertex_shader_source, NULL);
|
||||
glCompileShader (vertex_shader);
|
||||
glGetShaderiv (vertex_shader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
char compile_log[1024] = "";
|
||||
glGetShaderInfoLog (vertex_shader, sizeof (compile_log), NULL, compile_log);
|
||||
g_warning ("vertex shader compilation failed:\n %s\n", compile_log);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
|
||||
glShaderSource (fragment_shader, 1, &fragment_shader_source, NULL);
|
||||
glCompileShader (fragment_shader);
|
||||
glGetShaderiv (fragment_shader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
char compile_log[1024] = "";
|
||||
glGetShaderInfoLog (fragment_shader, sizeof (compile_log), NULL, compile_log);
|
||||
g_warning ("fragment shader compilation failed:\n %s\n", compile_log);
|
||||
goto out;
|
||||
}
|
||||
|
||||
shader_program = glCreateProgram ();
|
||||
glAttachShader (shader_program, vertex_shader);
|
||||
glAttachShader (shader_program, fragment_shader);
|
||||
glLinkProgram (shader_program);
|
||||
|
||||
glGetProgramiv (shader_program, GL_LINK_STATUS, &status);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
char link_log[1024] = "";
|
||||
|
||||
glGetProgramInfoLog (shader_program, sizeof (link_log), NULL, link_log);
|
||||
g_warning ("shader link failed:\n %s\n", link_log);
|
||||
goto out;
|
||||
}
|
||||
|
||||
glUseProgram (shader_program);
|
||||
|
||||
out:
|
||||
if (vertex_shader)
|
||||
glDeleteShader (vertex_shader);
|
||||
if (fragment_shader)
|
||||
glDeleteShader (fragment_shader);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_renderer_native_gles3_prepare_for_drawing (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
GError **error)
|
||||
{
|
||||
GLuint texture;
|
||||
|
||||
meta_renderer_native_gles3_load_basic_shaders (egl, gles3);
|
||||
|
||||
meta_gles3_clear_error (gles3);
|
||||
|
||||
GLBAS (gles3, glGenVertexArrays, (1, &vertex_array));
|
||||
GLBAS (gles3, glBindVertexArray, (vertex_array));
|
||||
|
||||
GLBAS (gles3, glGenBuffers, (1, &vertex_buffer));
|
||||
GLBAS (gles3, glBindBuffer, (GL_ARRAY_BUFFER, vertex_buffer));
|
||||
GLBAS (gles3, glBufferData, (GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STREAM_DRAW));
|
||||
|
||||
GLBAS (gles3, glGenBuffers, (1, &triangle_buffer));
|
||||
GLBAS (gles3, glBindBuffer, (GL_ELEMENT_ARRAY_BUFFER, triangle_buffer));
|
||||
GLBAS (gles3, glBufferData, (GL_ELEMENT_ARRAY_BUFFER, sizeof (triangles), triangles, GL_STREAM_DRAW));
|
||||
|
||||
GLBAS (gles3, glActiveTexture, (GL_TEXTURE0));
|
||||
GLBAS (gles3, glGenTextures, (1, &texture));
|
||||
GLBAS (gles3, glBindTexture, (GL_TEXTURE_2D, texture));
|
||||
|
||||
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));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -37,4 +37,15 @@ gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
||||
struct gbm_bo *shared_bo,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_renderer_native_gles3_prepare_for_drawing (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_renderer_native_gles3_draw_pixels (MetaEgl *egl,
|
||||
MetaGles3 *gles3,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
uint8_t *pixels,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_RENDERER_NATIVE_GLES3_H */
|
||||
|
@ -84,7 +84,10 @@ static GParamSpec *obj_props[PROP_LAST];
|
||||
typedef enum _MetaSharedFramebufferCopyMode
|
||||
{
|
||||
META_SHARED_FRAMEBUFFER_COPY_MODE_GPU,
|
||||
META_SHARED_FRAMEBUFFER_COPY_MODE_CPU
|
||||
META_SHARED_FRAMEBUFFER_COPY_MODE_CPU,
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM
|
||||
#endif
|
||||
} MetaSharedFramebufferCopyMode;
|
||||
|
||||
typedef struct _MetaRendererNativeGpuData
|
||||
@ -111,6 +114,7 @@ typedef struct _MetaRendererNativeGpuData
|
||||
* Fields used for blitting iGPU framebuffer content onto dGPU framebuffers.
|
||||
*/
|
||||
struct {
|
||||
MetaRendererNativeMode mode;
|
||||
MetaSharedFramebufferCopyMode copy_mode;
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
@ -150,6 +154,14 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
||||
struct gbm_bo *next_bo;
|
||||
} gbm;
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
struct {
|
||||
uint8_t *copied_pixels;
|
||||
MetaDumbBuffer dumb_fb;
|
||||
EGLStreamKHR stream;
|
||||
} egl;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
MetaDumbBuffer *dumb_fb;
|
||||
MetaDumbBuffer dumb_fbs[2];
|
||||
@ -235,6 +247,19 @@ init_dumb_fb (MetaDumbBuffer *dumb_fb,
|
||||
uint32_t format,
|
||||
GError **error);
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
static gboolean
|
||||
meta_renderer_native_create_surface_egl_device (CoglOnscreen *onscreen,
|
||||
MetaMonitor *monitor,
|
||||
EGLDisplay egl_display,
|
||||
EGLConfig egl_config,
|
||||
int width,
|
||||
int height,
|
||||
EGLStreamKHR *out_egl_stream,
|
||||
EGLSurface *out_egl_surface,
|
||||
GError **error);
|
||||
#endif
|
||||
|
||||
static MetaEgl *
|
||||
meta_renderer_native_get_egl (MetaRendererNative *renderer_native);
|
||||
|
||||
@ -640,6 +665,63 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
static gboolean
|
||||
init_secondary_gpu_state_stream_copy_mode (MetaRendererNative *renderer_native,
|
||||
CoglOnscreen *onscreen,
|
||||
MetaMonitor *monitor,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
MetaGpuKms *gpu_kms,
|
||||
GError **error)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
EGLStreamKHR egl_stream;
|
||||
int width, height;
|
||||
EGLSurface egl_surface;
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||
|
||||
width = cogl_framebuffer_get_width (framebuffer);
|
||||
height = cogl_framebuffer_get_height (framebuffer);
|
||||
|
||||
secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1);
|
||||
|
||||
if (!init_dumb_fb (&secondary_gpu_state->egl.dumb_fb,
|
||||
gpu_kms,
|
||||
width, height,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
error))
|
||||
goto failed;
|
||||
|
||||
if (!meta_renderer_native_create_surface_egl_device (onscreen,
|
||||
monitor,
|
||||
renderer_gpu_data->secondary.egl_display,
|
||||
renderer_gpu_data->secondary.egl_config,
|
||||
width, height,
|
||||
&egl_stream,
|
||||
&egl_surface,
|
||||
error))
|
||||
goto failed;
|
||||
|
||||
secondary_gpu_state->gpu_kms = gpu_kms;
|
||||
secondary_gpu_state->renderer_gpu_data = renderer_gpu_data;
|
||||
secondary_gpu_state->egl.stream = egl_stream;
|
||||
secondary_gpu_state->egl.copied_pixels = g_malloc (width * height * 4);
|
||||
secondary_gpu_state->egl_surface = egl_surface;
|
||||
|
||||
g_hash_table_insert (onscreen_native->secondary_gpu_states,
|
||||
gpu_kms, secondary_gpu_state);
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
if (secondary_gpu_state->egl.dumb_fb.fb_id)
|
||||
release_dumb_fb (&secondary_gpu_state->egl.dumb_fb, gpu_kms);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
|
||||
{
|
||||
@ -648,6 +730,25 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
|
||||
MetaGpuKms *gpu_kms = secondary_gpu_state->gpu_kms;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
if (secondary_gpu_state->egl.dumb_fb.fb_id)
|
||||
release_dumb_fb (&secondary_gpu_state->egl.dumb_fb, gpu_kms);
|
||||
|
||||
if (secondary_gpu_state->egl.stream != EGL_NO_STREAM_KHR)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
|
||||
renderer_gpu_data = secondary_gpu_state->renderer_gpu_data;
|
||||
meta_egl_destroy_stream (egl,
|
||||
renderer_gpu_data->secondary.egl_display,
|
||||
secondary_gpu_state->egl.stream,
|
||||
NULL);
|
||||
secondary_gpu_state->egl.stream = EGL_NO_STREAM_KHR;
|
||||
g_clear_pointer (&secondary_gpu_state->egl.copied_pixels,
|
||||
g_free);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (secondary_gpu_state->egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
@ -720,6 +821,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat
|
||||
static gboolean
|
||||
init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
||||
CoglOnscreen *onscreen,
|
||||
MetaMonitor *monitor,
|
||||
MetaGpuKms *gpu_kms,
|
||||
GError **error)
|
||||
{
|
||||
@ -738,6 +840,17 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
||||
error))
|
||||
return FALSE;
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM:
|
||||
if (!init_secondary_gpu_state_stream_copy_mode (renderer_native,
|
||||
onscreen,
|
||||
monitor,
|
||||
renderer_gpu_data,
|
||||
gpu_kms,
|
||||
error))
|
||||
return FALSE;
|
||||
break;
|
||||
#endif
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
|
||||
if (!init_secondary_gpu_state_cpu_copy_mode (renderer_native,
|
||||
onscreen,
|
||||
@ -838,6 +951,10 @@ free_current_secondary_bo (MetaGpuKms *gpu_kms,
|
||||
secondary_gpu_state->gbm.current_bo = NULL;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM:
|
||||
break;
|
||||
#endif
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
|
||||
break;
|
||||
}
|
||||
@ -1272,6 +1389,10 @@ free_next_secondary_bo (MetaGpuKms *gpu_kms,
|
||||
secondary_gpu_state->gbm.next_bo = NULL;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM:
|
||||
break;
|
||||
#endif
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
|
||||
break;
|
||||
}
|
||||
@ -1395,6 +1516,29 @@ flip_primary_egl_stream (MetaOnscreenNative *onscreen_native,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
flip_secondary_gpu_egl_stream (MetaOnscreenNative *onscreen_native,
|
||||
MetaGpuKms *gpu_kms,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
GClosure *flip_closure)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
gboolean ret;
|
||||
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
|
||||
gpu_kms);
|
||||
|
||||
ret = flip_egl_stream (onscreen_native,
|
||||
gpu_kms,
|
||||
renderer_gpu_data->secondary.egl_display,
|
||||
secondary_gpu_state->egl.stream,
|
||||
flip_closure);
|
||||
g_closure_ref (flip_closure);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_EGL_DEVICE */
|
||||
|
||||
static void
|
||||
@ -1423,7 +1567,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
||||
}
|
||||
|
||||
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
||||
render_gpu);
|
||||
gpu_kms);
|
||||
|
||||
if (gpu_kms == render_gpu)
|
||||
{
|
||||
@ -1460,9 +1604,25 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
if (flip_primary_egl_stream (onscreen_native,
|
||||
flip_closure))
|
||||
onscreen_native->total_pending_flips++;
|
||||
if (gpu_kms == render_gpu)
|
||||
{
|
||||
if (!flip_primary_egl_stream (onscreen_native,
|
||||
flip_closure))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!flip_secondary_gpu_egl_stream (onscreen_native,
|
||||
gpu_kms,
|
||||
secondary_gpu_state,
|
||||
flip_closure))
|
||||
return;
|
||||
}
|
||||
|
||||
onscreen_native->total_pending_flips++;
|
||||
if (secondary_gpu_state)
|
||||
secondary_gpu_state->pending_flips++;
|
||||
|
||||
*fb_in_use = TRUE;
|
||||
break;
|
||||
#endif
|
||||
@ -1496,12 +1656,25 @@ set_crtc_fb (MetaLogicalMonitor *logical_monitor,
|
||||
else
|
||||
{
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
|
||||
secondary_gpu_state = get_secondary_gpu_state (onscreen, gpu_kms);
|
||||
if (!secondary_gpu_state)
|
||||
return;
|
||||
|
||||
fb_id = secondary_gpu_state->gbm.next_fb_id;
|
||||
renderer_gpu_data = secondary_gpu_state->renderer_gpu_data;
|
||||
|
||||
switch (renderer_gpu_data->secondary.mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
fb_id = secondary_gpu_state->gbm.next_fb_id;
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
fb_id = secondary_gpu_state->egl.dumb_fb.fb_id;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
x = crtc->rect.x - logical_monitor->rect.x;
|
||||
@ -1849,6 +2022,60 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
||||
&secondary_gpu_state->gbm.next_fb_id);
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
static void
|
||||
draw_shared_framebuffer_stream (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
gboolean *egl_context_changed)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
||||
GError *error = NULL;
|
||||
MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
|
||||
uint32_t width, height;
|
||||
void *target_data;
|
||||
|
||||
width = cogl_framebuffer_get_width (framebuffer);
|
||||
height = cogl_framebuffer_get_height (framebuffer);
|
||||
|
||||
target_data = secondary_gpu_state->egl.copied_pixels;
|
||||
|
||||
if (!meta_egl_make_current (egl,
|
||||
renderer_gpu_data->secondary.egl_display,
|
||||
secondary_gpu_state->egl_surface,
|
||||
secondary_gpu_state->egl_surface,
|
||||
renderer_gpu_data->secondary.egl_context,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to make current: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
*egl_context_changed = TRUE;
|
||||
|
||||
meta_renderer_native_gles3_draw_pixels (egl,
|
||||
renderer_native->gles3,
|
||||
width,
|
||||
height,
|
||||
target_data,
|
||||
&error);
|
||||
|
||||
if (!meta_egl_swap_buffers (egl,
|
||||
renderer_gpu_data->secondary.egl_display,
|
||||
secondary_gpu_state->egl_surface,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to swap buffers: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct _PixelFormatMap {
|
||||
uint32_t drm_format;
|
||||
CoglPixelFormat cogl_format;
|
||||
@ -1968,6 +2195,48 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
|
||||
secondary_gpu_state->gbm.next_fb_id = target_fb_id;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
static void
|
||||
copy_shared_framebuffer_stream (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *cogl_context = framebuffer->context;
|
||||
int width, height;
|
||||
uint8_t *target_data;
|
||||
uint32_t target_drm_format = DRM_FORMAT_XRGB8888;
|
||||
CoglBitmap *dumb_bitmap;
|
||||
CoglPixelFormat cogl_format;
|
||||
gboolean ret;
|
||||
|
||||
width = cogl_framebuffer_get_width (framebuffer);
|
||||
height = cogl_framebuffer_get_height (framebuffer);
|
||||
target_data = secondary_gpu_state->egl.copied_pixels;
|
||||
|
||||
ret = cogl_pixel_format_from_drm_format (target_drm_format,
|
||||
&cogl_format,
|
||||
NULL);
|
||||
g_assert (ret);
|
||||
|
||||
dumb_bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width,
|
||||
height,
|
||||
cogl_format,
|
||||
width * 4,
|
||||
target_data);
|
||||
|
||||
if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
|
||||
0 /* x */,
|
||||
0 /* y */,
|
||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||
dumb_bitmap))
|
||||
g_warning ("Failed to read pixels from primary renderer");
|
||||
|
||||
cogl_object_unref (dumb_bitmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen)
|
||||
{
|
||||
@ -1989,6 +2258,13 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen)
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_GPU:
|
||||
/* Done after eglSwapBuffers. */
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM:
|
||||
copy_shared_framebuffer_stream (onscreen,
|
||||
secondary_gpu_state,
|
||||
renderer_gpu_data);
|
||||
break;
|
||||
#endif
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
|
||||
copy_shared_framebuffer_cpu (onscreen,
|
||||
secondary_gpu_state,
|
||||
@ -2026,6 +2302,14 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
||||
renderer_gpu_data,
|
||||
egl_context_changed);
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM:
|
||||
draw_shared_framebuffer_stream (onscreen,
|
||||
secondary_gpu_state,
|
||||
renderer_gpu_data,
|
||||
egl_context_changed);
|
||||
break;
|
||||
#endif
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
|
||||
/* Done before eglSwapBuffers. */
|
||||
break;
|
||||
@ -2815,7 +3099,7 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
|
||||
if (get_secondary_gpu_state (onscreen, gpu_kms))
|
||||
continue;
|
||||
|
||||
if (!init_secondary_gpu_state (renderer_native, onscreen, gpu_kms, error))
|
||||
if (!init_secondary_gpu_state (renderer_native, onscreen, monitor, gpu_kms, error))
|
||||
{
|
||||
cogl_object_unref (onscreen);
|
||||
return NULL;
|
||||
@ -3267,11 +3551,55 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
|
||||
renderer_gpu_data->secondary.egl_context = egl_context;
|
||||
renderer_gpu_data->secondary.egl_config = egl_config;
|
||||
renderer_gpu_data->secondary.mode = META_RENDERER_NATIVE_MODE_GBM;
|
||||
renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_GPU;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
static gboolean
|
||||
init_secondary_gpu_data_stream (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
||||
MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
|
||||
EGLDisplay egl_display = renderer_gpu_data->secondary.egl_display;
|
||||
EGLConfig egl_config;
|
||||
EGLContext egl_context;
|
||||
|
||||
if (!create_secondary_egl_config (egl,
|
||||
renderer_gpu_data->secondary.mode, egl_display,
|
||||
&egl_config, error))
|
||||
return FALSE;
|
||||
|
||||
egl_context = create_secondary_egl_context (egl, egl_display, egl_config, error);
|
||||
if (egl_context == EGL_NO_CONTEXT)
|
||||
return FALSE;
|
||||
|
||||
meta_renderer_native_ensure_gles3 (renderer_native);
|
||||
|
||||
if (!meta_egl_make_current (egl,
|
||||
egl_display,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
egl_context,
|
||||
error))
|
||||
{
|
||||
meta_egl_destroy_context (egl, egl_display, egl_context, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta_renderer_native_gles3_prepare_for_drawing (egl, renderer_native->gles3, NULL);
|
||||
|
||||
renderer_gpu_data->secondary.egl_context = egl_context;
|
||||
renderer_gpu_data->secondary.egl_config = egl_config;
|
||||
renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_STREAM;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
init_secondary_gpu_data_cpu (MetaRendererNativeGpuData *renderer_gpu_data)
|
||||
{
|
||||
@ -3283,8 +3611,20 @@ init_secondary_gpu_data (MetaRendererNativeGpuData *renderer_gpu_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (init_secondary_gpu_data_gpu (renderer_gpu_data, &error))
|
||||
return;
|
||||
switch (renderer_gpu_data->secondary.mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
if (init_secondary_gpu_data_gpu (renderer_gpu_data, &error))
|
||||
return;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
if (init_secondary_gpu_data_stream (renderer_gpu_data, &error))
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
g_warning ("Failed to initialize accelerated iGPU/dGPU framebuffer sharing: %s",
|
||||
error->message);
|
||||
|
Loading…
Reference in New Issue
Block a user