mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 03:10:09 +00:00
gdk: Redo GL drawing
Reenable GL drawing, but do it without Cairo. Now, the context passed to gdk_window_begin_draw_frame() decides how drawing is going to happen. If it is NULL, Cairo is used like before. If a context is passed, Cairo may not be used for drawing and gdk_drawing_context_get_cairo_context() is going to return NULL. Instead, the GL renderer must draw to the GL backbuffer and end_draw_frame() is then swapping that to the front. The GskGLRenderer has lost the texture it used to render to and adapted to render directly to the backbuffer instead. The only thing missing is for GtkGLArea to gain back a performant way to render. But it didn't have one since the introduction of GSK, this patchset doesn't change anything about it. The new rendering avoids two indirections (the GSK renderer's texture and the GDK double buffering surface). It improves icon count in the fishbowl demo by 30%.
This commit is contained in:
parent
e87b472143
commit
e38bd27d58
@ -240,10 +240,13 @@ gdk_cairo_get_drawing_context (cairo_t *cr)
|
||||
|
||||
/**
|
||||
* gdk_drawing_context_get_cairo_context:
|
||||
* @context:
|
||||
* @context: a #GdkDrawingContext created with a %NULL paint context
|
||||
*
|
||||
* Retrieves a Cairo context to be used to draw on the #GdkWindow
|
||||
* that created the #GdkDrawingContext.
|
||||
* that created the #GdkDrawingContext. The @context must have been
|
||||
* created without a #GdkGLContext for this function to work. If
|
||||
* gdk_drawing_context_get_paint_context() does not return %NULL,
|
||||
* then this function will.
|
||||
*
|
||||
* The returned context is guaranteed to be valid as long as the
|
||||
* #GdkDrawingContext is valid, that is between a call to
|
||||
@ -251,7 +254,8 @@ gdk_cairo_get_drawing_context (cairo_t *cr)
|
||||
*
|
||||
* Returns: (transfer none): a Cairo context to be used to draw
|
||||
* the contents of the #GdkWindow. The context is owned by the
|
||||
* #GdkDrawingContext and should not be destroyed
|
||||
* #GdkDrawingContext and should not be destroyed. %NULL is
|
||||
* returned when a paint context is in used.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
@ -263,6 +267,9 @@ gdk_drawing_context_get_cairo_context (GdkDrawingContext *context)
|
||||
g_return_val_if_fail (GDK_IS_DRAWING_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (priv->window), NULL);
|
||||
|
||||
if (priv->paint_context != NULL)
|
||||
return NULL;
|
||||
|
||||
if (priv->cr == NULL)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
|
@ -2692,10 +2692,6 @@ gdk_window_begin_paint_internal (GdkWindow *window,
|
||||
gboolean needs_surface;
|
||||
cairo_content_t surface_content;
|
||||
|
||||
if (GDK_WINDOW_DESTROYED (window) ||
|
||||
!gdk_window_has_impl (window))
|
||||
return;
|
||||
|
||||
if (window->current_paint.surface != NULL)
|
||||
{
|
||||
g_warning ("A paint operation on the window is alredy in progress. "
|
||||
@ -2744,10 +2740,6 @@ gdk_window_end_paint_internal (GdkWindow *window)
|
||||
GdkWindowImplClass *impl_class;
|
||||
cairo_t *cr;
|
||||
|
||||
if (GDK_WINDOW_DESTROYED (window) ||
|
||||
!gdk_window_has_impl (window))
|
||||
return;
|
||||
|
||||
if (window->current_paint.surface == NULL)
|
||||
{
|
||||
g_warning (G_STRLOC": no preceding call to gdk_window_begin_draw_frame(), see documentation");
|
||||
@ -2828,16 +2820,21 @@ gdk_window_begin_draw_frame (GdkWindow *window,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GdkDrawingContext *context;
|
||||
cairo_region_t *real_region;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
|
||||
g_return_val_if_fail (gdk_window_has_native (window), NULL);
|
||||
g_return_val_if_fail (gdk_window_is_toplevel (window), NULL);
|
||||
g_return_val_if_fail (region != NULL, NULL);
|
||||
if (gl_context != NULL)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (gl_context), NULL);
|
||||
g_return_val_if_fail (gdk_gl_context_get_window (gl_context) == window, NULL);
|
||||
}
|
||||
|
||||
if (GDK_WINDOW_DESTROYED (window))
|
||||
return NULL;
|
||||
|
||||
if (window->drawing_context != NULL)
|
||||
{
|
||||
g_critical ("The window %p already has a drawing context. You cannot "
|
||||
@ -2846,16 +2843,23 @@ gdk_window_begin_draw_frame (GdkWindow *window,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
real_region = cairo_region_copy (region);
|
||||
|
||||
if (gl_context)
|
||||
gdk_gl_context_begin_frame (gl_context, real_region);
|
||||
else
|
||||
gdk_window_begin_paint_internal (window, real_region);
|
||||
|
||||
context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
|
||||
"window", window,
|
||||
"paint-context", gl_context,
|
||||
"clip", region,
|
||||
"clip", real_region,
|
||||
NULL);
|
||||
|
||||
/* Do not take a reference, to avoid creating cycles */
|
||||
window->drawing_context = context;
|
||||
|
||||
gdk_window_begin_paint_internal (window, region);
|
||||
cairo_region_destroy (real_region);
|
||||
|
||||
return context;
|
||||
}
|
||||
@ -2879,11 +2883,34 @@ void
|
||||
gdk_window_end_draw_frame (GdkWindow *window,
|
||||
GdkDrawingContext *context)
|
||||
{
|
||||
GdkGLContext *paint_context;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
|
||||
|
||||
if (GDK_WINDOW_DESTROYED (window))
|
||||
return;
|
||||
|
||||
if (window->drawing_context == NULL)
|
||||
{
|
||||
g_critical ("The window %p has no drawing context. You must call "
|
||||
"gdk_window_begin_draw_frame() before calling "
|
||||
"gdk_window_end_draw_frame().", window);
|
||||
return;
|
||||
}
|
||||
g_return_if_fail (window->drawing_context == context);
|
||||
|
||||
gdk_window_end_paint_internal (window);
|
||||
paint_context = gdk_drawing_context_get_paint_context (context);
|
||||
if (paint_context)
|
||||
{
|
||||
gdk_gl_context_end_frame (paint_context,
|
||||
gdk_drawing_context_get_clip (context),
|
||||
window->active_update_area);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_window_end_paint_internal (window);
|
||||
}
|
||||
|
||||
window->drawing_context = NULL;
|
||||
|
||||
|
@ -99,7 +99,6 @@ struct _GskGLRenderer
|
||||
|
||||
guint frame_buffer;
|
||||
guint depth_stencil_buffer;
|
||||
guint texture_id;
|
||||
|
||||
GQuark uniforms[N_UNIFORMS];
|
||||
GQuark attributes[N_ATTRIBUTES];
|
||||
@ -150,17 +149,6 @@ gsk_gl_renderer_create_buffers (GskGLRenderer *self,
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Creating buffers (w:%d, h:%d, scale:%d)\n", width, height, scale_factor));
|
||||
|
||||
if (self->texture_id == 0)
|
||||
{
|
||||
self->texture_id = gsk_gl_driver_create_texture (self->gl_driver,
|
||||
width * scale_factor,
|
||||
height * scale_factor);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, self->texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self->gl_driver, self->texture_id);
|
||||
}
|
||||
|
||||
gsk_gl_driver_create_render_target (self->gl_driver, self->texture_id, TRUE, TRUE);
|
||||
|
||||
self->has_buffers = TRUE;
|
||||
}
|
||||
|
||||
@ -177,12 +165,6 @@ gsk_gl_renderer_destroy_buffers (GskGLRenderer *self)
|
||||
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
if (self->texture_id != 0)
|
||||
{
|
||||
gsk_gl_driver_destroy_texture (self->gl_driver, self->texture_id);
|
||||
self->texture_id = 0;
|
||||
}
|
||||
|
||||
self->has_buffers = FALSE;
|
||||
}
|
||||
|
||||
@ -695,7 +677,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
item.render_data.render_target_id = self->texture_id;
|
||||
item.render_data.render_target_id = 0;
|
||||
item.children = NULL;
|
||||
}
|
||||
|
||||
@ -732,7 +714,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
|
||||
else
|
||||
{
|
||||
/* If the node does not draw anything, we skip it */
|
||||
if (item.render_data.render_target_id == self->texture_id)
|
||||
if (item.render_data.render_target_id == 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -845,7 +827,6 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
graphene_rect_t viewport;
|
||||
guint i;
|
||||
int scale_factor;
|
||||
GdkDrawingContext *context;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GskProfiler *profiler;
|
||||
gint64 gpu_time, cpu_time;
|
||||
@ -854,8 +835,6 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
if (self->gl_context == NULL)
|
||||
return;
|
||||
|
||||
context = gsk_renderer_get_drawing_context (renderer);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
profiler = gsk_renderer_get_profiler (renderer);
|
||||
#endif
|
||||
@ -890,7 +869,7 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
#endif
|
||||
|
||||
/* Ensure that the viewport is up to date */
|
||||
if (gsk_gl_driver_bind_render_target (self->gl_driver, self->texture_id))
|
||||
if (gsk_gl_driver_bind_render_target (self->gl_driver, 0))
|
||||
gsk_gl_renderer_resize_viewport (self, &viewport, scale_factor);
|
||||
|
||||
gsk_gl_renderer_clear (self);
|
||||
@ -925,31 +904,6 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
#endif
|
||||
|
||||
out:
|
||||
{
|
||||
GdkWindow *window;
|
||||
cairo_t *cr;
|
||||
|
||||
if (context != NULL)
|
||||
{
|
||||
/* XXX: Add GdkDrawingContext API */
|
||||
cr = gdk_drawing_context_get_cairo_context (context);
|
||||
window = gdk_drawing_context_get_window (context);
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = gsk_renderer_get_cairo_context (renderer);
|
||||
window = gsk_renderer_get_window (renderer);
|
||||
}
|
||||
|
||||
gdk_cairo_draw_from_gl (cr, window,
|
||||
self->texture_id,
|
||||
GL_TEXTURE,
|
||||
scale_factor,
|
||||
0, 0,
|
||||
viewport.size.width * scale_factor,
|
||||
viewport.size.height * scale_factor);
|
||||
}
|
||||
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
gsk_gl_renderer_clear_tree (self);
|
||||
gsk_gl_renderer_destroy_buffers (self);
|
||||
|
Loading…
Reference in New Issue
Block a user