broadway: Add and use GdkBroadwayDrawContext

This commit is contained in:
Alexander Larsson 2018-04-24 15:39:53 +02:00 committed by Benjamin Otte
parent 99c46f263e
commit a329de63ea
6 changed files with 197 additions and 169 deletions

View File

@ -44,92 +44,6 @@
#endif
#include <sys/types.h>
static gboolean
compare_surface (cairo_surface_t *a,
cairo_surface_t *b,
int width,
int height)
{
unsigned char *data_a, *data_b;
int stride_a, stride_b;
int y;
data_a = cairo_image_surface_get_data (a);
stride_a = cairo_image_surface_get_stride (a);
data_b = cairo_image_surface_get_data (b);
stride_b = cairo_image_surface_get_stride (b);
for (y = 0; y < height; y++)
{
if (memcmp (data_a, data_b, 4 * width) != 0)
return FALSE;
data_a += stride_a;
data_b += stride_b;
}
return TRUE;
}
static gboolean
gdk_texture_equal (GdkTexture *a,
GdkTexture *b)
{
cairo_surface_t *surface_a;
cairo_surface_t *surface_b;
gboolean res;
if (a == b)
return TRUE;
if (a->width != b->width ||
a->height != b->height)
return FALSE;
surface_a = gdk_texture_download_surface (a);
surface_b = gdk_texture_download_surface (b);
res = compare_surface (surface_a, surface_b, a->width, a->height);
cairo_surface_destroy (surface_a);
cairo_surface_destroy (surface_b);
return res;
}
static guint
gdk_texture_hash (GdkTexture *self)
{
cairo_surface_t *surface;
unsigned char *data;
int stride;
guint32 *row;
guint64 sum;
int x, y, width, height;
guint h;
surface = gdk_texture_download_surface (self);
data = cairo_image_surface_get_data (surface);
stride = cairo_image_surface_get_stride (surface);
width = MIN (self->width, 4);
height = MIN (self->height, 4);
sum = 0;
for (y = 0; y < height; y++, data += stride)
{
row = (guint32 *)data;
for (x = 0; x < width; x++)
sum += row[x];
}
cairo_surface_destroy (surface);
h = sum / (width * height);
return h ^ self->width ^ (self->height << 16);
}
static void gdk_broadway_display_dispose (GObject *object);
static void gdk_broadway_display_finalize (GObject *object);
@ -149,7 +63,6 @@ gdk_broadway_display_init (GdkBroadwayDisplay *display)
NULL);
gdk_monitor_set_manufacturer (display->monitor, "browser");
gdk_monitor_set_model (display->monitor, "0");
display->texture_cache = g_hash_table_new ((GHashFunc)gdk_texture_hash, (GEqualFunc)gdk_texture_equal);
}
static void
@ -439,39 +352,17 @@ gdk_broadway_display_get_last_seen_time (GdkDisplay *display)
typedef struct {
int id;
GdkDisplay *display;
GdkTexture *in_cache;
GList *textures;
} BroadwayTextureData;
static void
broadway_texture_data_notify (BroadwayTextureData *data,
GdkTexture *disposed_texture)
broadway_texture_data_free (BroadwayTextureData *data)
{
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (data->display);
if (data->in_cache == disposed_texture)
{
g_hash_table_remove (broadway_display->texture_cache, disposed_texture);
data->in_cache = NULL;
}
g_object_set_data (G_OBJECT (disposed_texture), "broadway-data", NULL);
data->textures = g_list_remove (data->textures, disposed_texture);
if (data->textures == NULL)
{
gdk_broadway_server_release_texture (broadway_display->server, data->id);
g_object_unref (data->display);
g_free (data);
}
else if (data->in_cache == NULL)
{
GdkTexture *first = data->textures->data;
data->in_cache = first;
g_hash_table_replace (broadway_display->texture_cache,
data->in_cache, data->in_cache);
}
gdk_broadway_server_release_texture (broadway_display->server, data->id);
g_object_unref (data->display);
g_free (data);
}
guint32
@ -480,35 +371,18 @@ gdk_broadway_display_ensure_texture (GdkDisplay *display,
{
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
BroadwayTextureData *data;
guint32 id;
GdkTexture *cached;
data = g_object_get_data (G_OBJECT (texture), "broadway-data");
if (data != NULL)
return data->id;
cached = g_hash_table_lookup (broadway_display->texture_cache, texture);
if (cached)
data = g_object_get_data (G_OBJECT (cached), "broadway-data");
if (data == NULL)
{
id = gdk_broadway_server_upload_texture (broadway_display->server, texture);
guint32 id = gdk_broadway_server_upload_texture (broadway_display->server, texture);
data = g_new0 (BroadwayTextureData, 1);
data->id = id;
data->display = g_object_ref (display);
data->in_cache = texture;
g_hash_table_replace (broadway_display->texture_cache,
data->in_cache, data->in_cache);
g_object_set_data_full (G_OBJECT (texture), "broadway-data", data, (GDestroyNotify)broadway_texture_data_free);
}
data->textures = g_list_prepend (data->textures, texture);
g_object_weak_ref (G_OBJECT (texture), (GWeakNotify)broadway_texture_data_notify, data);
g_object_set_data (G_OBJECT (texture), "broadway-data", data);
return data->id;
}

View File

@ -0,0 +1,100 @@
/* GDK - The GIMP Drawing Kit
*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkconfig.h"
#include "gdkdrawcontext-broadway.h"
#include "gdktextureprivate.h"
#include "gdkprivate-broadway.h"
G_DEFINE_TYPE (GdkBroadwayDrawContext, gdk_broadway_draw_context, GDK_TYPE_DRAW_CONTEXT)
static void
gdk_broadway_draw_context_dispose (GObject *object)
{
G_OBJECT_CLASS (gdk_broadway_draw_context_parent_class)->dispose (object);
}
static void
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
cairo_region_union_rectangle (region,
&(cairo_rectangle_int_t) {
0, 0,
gdk_surface_get_width (surface),
gdk_surface_get_height (surface)
});
g_assert (self->nodes == NULL);
g_assert (self->node_textures == NULL);
self->nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
self->node_textures = g_ptr_array_new_with_free_func (g_object_unref);
}
static void
gdk_broadway_draw_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
gdk_broadway_surface_set_nodes (surface, self->nodes, self->node_textures);
g_array_unref (self->nodes);
self->nodes = NULL;
g_ptr_array_unref (self->node_textures);
self->node_textures = NULL;
}
static void
gdk_broadway_draw_context_surface_resized (GdkDrawContext *draw_context)
{
}
static void
gdk_broadway_draw_context_class_init (GdkBroadwayDrawContextClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
gobject_class->dispose = gdk_broadway_draw_context_dispose;
draw_context_class->begin_frame = gdk_broadway_draw_context_begin_frame;
draw_context_class->end_frame = gdk_broadway_draw_context_end_frame;
draw_context_class->surface_resized = gdk_broadway_draw_context_surface_resized;
}
static void
gdk_broadway_draw_context_init (GdkBroadwayDrawContext *self)
{
}
GdkBroadwayDrawContext *
gdk_broadway_draw_context_context (GdkSurface *surface)
{
return g_object_new (GDK_TYPE_BROADWAY_DRAW_CONTEXT,
"surface", surface,
NULL);
}

View File

@ -0,0 +1,58 @@
/* GDK - The GIMP Drawing Kit
*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_BROADWAY_DRAW_CONTEXT__
#define __GDK_BROADWAY_DRAW_CONTEXT__
#include "gdkconfig.h"
#include "gdkdrawcontextprivate.h"
G_BEGIN_DECLS
#define GDK_TYPE_BROADWAY_DRAW_CONTEXT (gdk_broadway_draw_context_get_type ())
#define GDK_BROADWAY_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContext))
#define GDK_IS_BROADWAY_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT))
#define GDK_BROADWAY_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContextClass))
#define GDK_IS_BROADWAY_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_DRAW_CONTEXT))
#define GDK_BROADWAY_DRAW_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContextClass))
typedef struct _GdkBroadwayDrawContext GdkBroadwayDrawContext;
typedef struct _GdkBroadwayDrawContextClass GdkBroadwayDrawContextClass;
struct _GdkBroadwayDrawContext
{
GdkDrawContext parent_instance;
GPtrArray *node_textures;
GArray *nodes;
};
struct _GdkBroadwayDrawContextClass
{
GdkDrawContextClass parent_class;
};
GDK_AVAILABLE_IN_ALL
GType gdk_broadway_draw_context_get_type (void) G_GNUC_CONST;
GdkBroadwayDrawContext *gdk_broadway_draw_context_context (GdkSurface *surface);
G_END_DECLS
#endif /* __GDK_BROADWAY_DRAW_CONTEXT__ */

View File

@ -33,6 +33,7 @@
#include <gdk/gdkinternals.h>
#include "gdksurface-broadway.h"
#include "gdkdisplay-broadway.h"
#include "gdkdrawcontext-broadway.h"
#include "gdkbroadwaycursor.h"
#include "gdkbroadwaysurface.h"

View File

@ -4,6 +4,7 @@ gdk_broadway_sources = files([
'broadwayd.c',
'gdkbroadway-server.c',
'gdkcairocontext-broadway.c',
'gdkdrawcontext-broadway.c',
'gdkcursor-broadway.c',
'gdkdevice-broadway.c',
'gdkdisplay-broadway.c',

View File

@ -8,11 +8,10 @@
#include "gskrendernodeprivate.h"
#include "gdk/gdktextureprivate.h"
struct _GskBroadwayRenderer
{
GskRenderer parent_instance;
GdkBroadwayDrawContext *draw_context;
};
struct _GskBroadwayRendererClass
@ -23,21 +22,33 @@ struct _GskBroadwayRendererClass
G_DEFINE_TYPE (GskBroadwayRenderer, gsk_broadway_renderer, GSK_TYPE_RENDERER)
static gboolean
gsk_broadway_renderer_realize (GskRenderer *self,
GdkSurface *surface,
gsk_broadway_renderer_realize (GskRenderer *renderer,
GdkSurface *surface,
GError **error)
{
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
if (!GDK_IS_BROADWAY_SURFACE (surface))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Broadway renderer only works for broadway surfaces");
return FALSE;
}
self->draw_context = gdk_broadway_draw_context_context (surface);
return TRUE;
}
static void
gsk_broadway_renderer_unrealize (GskRenderer *self)
gsk_broadway_renderer_unrealize (GskRenderer *renderer)
{
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
g_clear_object (&self->draw_context);
}
static GdkTexture *
gsk_broadway_renderer_render_texture (GskRenderer *self,
gsk_broadway_renderer_render_texture (GskRenderer *renderer,
GskRenderNode *root,
const graphene_rect_t *viewport)
{
@ -443,14 +454,14 @@ node_texture_fallback (GskRenderNode *node,
parent-relative which is what the dom uses, and
which is good for re-using subtrees. */
static void
gsk_broadway_renderer_add_node (GskRenderer *self,
gsk_broadway_renderer_add_node (GskRenderer *renderer,
GArray *nodes,
GPtrArray *node_textures,
GskRenderNode *node,
float offset_x,
float offset_y)
{
GdkDisplay *display = gsk_renderer_get_display (self);
GdkDisplay *display = gsk_renderer_get_display (renderer);
switch (gsk_render_node_get_node_type (node))
{
@ -564,7 +575,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
add_float (nodes, shadow->dy);
add_float (nodes, shadow->radius);
}
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_shadow_node_get_child (node),
offset_x, offset_y);
}
@ -574,7 +585,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
{
add_uint32 (nodes, BROADWAY_NODE_OPACITY);
add_float (nodes, gsk_opacity_node_get_opacity (node));
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_opacity_node_get_child (node),
offset_x, offset_y);
}
@ -585,7 +596,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
const GskRoundedRect *rclip = gsk_rounded_clip_node_peek_clip (node);
add_uint32 (nodes, BROADWAY_NODE_ROUNDED_CLIP);
add_rounded_rect (nodes, rclip, offset_x, offset_y);
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_rounded_clip_node_get_child (node),
rclip->bounds.origin.x,
rclip->bounds.origin.y);
@ -597,7 +608,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
const graphene_rect_t *clip = gsk_clip_node_peek_clip (node);
add_uint32 (nodes, BROADWAY_NODE_CLIP);
add_rect (nodes, clip, offset_x, offset_y);
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_clip_node_get_child (node),
clip->origin.x,
clip->origin.y);
@ -614,13 +625,13 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
add_uint32 (nodes, gsk_container_node_get_n_children (node));
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_container_node_get_child (node, i), offset_x, offset_y);
}
return;
case GSK_DEBUG_NODE:
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
gsk_debug_node_get_child (node), offset_x, offset_y);
return;
@ -666,32 +677,15 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
}
static void
gsk_broadway_renderer_render (GskRenderer *self,
gsk_broadway_renderer_render (GskRenderer *renderer,
GskRenderNode *root,
const cairo_region_t *update_area)
{
GArray *nodes;
GPtrArray *node_textures;
cairo_region_t *whole;
GdkSurface *surface;
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
surface = gsk_renderer_get_surface (self);
whole = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
0, 0,
gdk_surface_get_width (surface),
gdk_surface_get_height (surface)
});
gdk_draw_context_begin_frame (NULL, whole);
cairo_region_destroy (whole);
nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
node_textures = g_ptr_array_new_with_free_func (g_object_unref);
gsk_broadway_renderer_add_node (self, nodes, node_textures, root, 0, 0);
gdk_broadway_surface_set_nodes (surface, nodes, node_textures);
g_array_unref (nodes);
g_ptr_array_unref (node_textures);
gdk_draw_context_end_frame (NULL);
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->draw_context), update_area);
gsk_broadway_renderer_add_node (renderer, self->draw_context->nodes, self->draw_context->node_textures, root, 0, 0);
gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->draw_context));
}
static void