Compare commits
14 Commits
shader-too
...
wip/otte/r
Author | SHA1 | Date | |
---|---|---|---|
|
f2848737a2 | ||
|
8b7261df40 | ||
|
74e00bddf5 | ||
|
2345ffe0e4 | ||
|
67d0fd06b8 | ||
|
9d89e4981b | ||
|
b1278c3666 | ||
|
04f9fb511f | ||
|
f8166f6a4f | ||
|
52d426d08f | ||
|
75510f7123 | ||
|
beb48202fc | ||
|
524c25b727 | ||
|
8cc77194a3 |
@@ -12,6 +12,7 @@ gsk_renderer_unrealize
|
||||
gsk_renderer_begin_draw_frame
|
||||
gsk_renderer_end_draw_frame
|
||||
gsk_renderer_render
|
||||
gsk_renderer_render_texture
|
||||
<SUBSECTION Standard>
|
||||
GSK_IS_RENDERER
|
||||
GSK_RENDERER
|
||||
@@ -32,6 +33,8 @@ gsk_render_node_draw
|
||||
GskScalingFilter
|
||||
gsk_render_node_set_scaling_filters
|
||||
gsk_render_node_set_name
|
||||
gsk_render_node_get_name
|
||||
gsk_render_node_get_bounds
|
||||
gsk_color_node_new
|
||||
gsk_linear_gradient_node_new
|
||||
gsk_repeating_linear_gradient_node_new
|
||||
@@ -68,6 +71,22 @@ gsk_render_node_get_type
|
||||
GSK_TYPE_BLEND_MODE
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>GskTexture</FILE>
|
||||
gsk_texture_ref
|
||||
gsk_texture_unref
|
||||
gsk_texture_new_for_data
|
||||
gsk_texture_new_for_pixbuf
|
||||
gsk_texture_get_width
|
||||
gsk_texture_get_height
|
||||
gsk_texture_download
|
||||
<SUBSECTION Standard>
|
||||
GskTexture
|
||||
gsk_texture_get_type
|
||||
GSK_TYPE_TEXTURE
|
||||
GSK_IS_TEXTURE
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>GskRoundedRect</FILE>
|
||||
GskCorner
|
||||
|
@@ -151,7 +151,7 @@ gdk_cairo_region (cairo_t *cr,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
|
||||
const GdkPixbuf *pixbuf)
|
||||
{
|
||||
@@ -198,7 +198,9 @@ gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
|
||||
q[0] = p[2];
|
||||
q[1] = p[1];
|
||||
q[2] = p[0];
|
||||
q[3] = 0xFF;
|
||||
#else
|
||||
q[0] = 0xFF;
|
||||
q[1] = p[0];
|
||||
q[2] = p[1];
|
||||
q[3] = p[2];
|
||||
|
@@ -343,6 +343,9 @@ void gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
GdkTexturedQuad *quads,
|
||||
gboolean flip_colors);
|
||||
|
||||
void gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
|
||||
const GdkPixbuf *pixbuf);
|
||||
|
||||
void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface,
|
||||
GdkWindow *window);
|
||||
cairo_region_t *gdk_cairo_region_from_clip (cairo_t *cr);
|
||||
|
@@ -18,8 +18,6 @@ struct _GskCairoRenderer
|
||||
{
|
||||
GskRenderer parent_instance;
|
||||
|
||||
graphene_rect_t viewport;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
ProfileTimers profile_timers;
|
||||
#endif
|
||||
@@ -47,44 +45,16 @@ gsk_cairo_renderer_unrealize (GskRenderer *renderer)
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_render (GskRenderer *renderer,
|
||||
GskRenderNode *root)
|
||||
gsk_cairo_renderer_do_render (GskRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
GskRenderNode *root)
|
||||
{
|
||||
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
|
||||
GdkDrawingContext *context = gsk_renderer_get_drawing_context (renderer);
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
|
||||
GskProfiler *profiler;
|
||||
gint64 cpu_time;
|
||||
#endif
|
||||
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gdk_drawing_context_get_cairo_context (context);
|
||||
|
||||
g_return_if_fail (cr != NULL);
|
||||
|
||||
gsk_renderer_get_viewport (renderer, &self->viewport);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
cairo_save (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_rectangle (cr,
|
||||
self->viewport.origin.x,
|
||||
self->viewport.origin.y,
|
||||
self->viewport.size.width,
|
||||
self->viewport.size.height);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0.85, 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
profiler = gsk_renderer_get_profiler (renderer);
|
||||
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
|
||||
@@ -100,6 +70,62 @@ gsk_cairo_renderer_render (GskRenderer *renderer,
|
||||
#endif
|
||||
}
|
||||
|
||||
static GskTexture *
|
||||
gsk_cairo_renderer_render_texture (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
GskTexture *texture;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (viewport->size.width), ceil (viewport->size.height));
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
|
||||
|
||||
gsk_cairo_renderer_do_render (renderer, cr, root);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
texture = gsk_texture_new_for_surface (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_render (GskRenderer *renderer,
|
||||
GskRenderNode *root)
|
||||
{
|
||||
GdkDrawingContext *context = gsk_renderer_get_drawing_context (renderer);
|
||||
graphene_rect_t viewport;
|
||||
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gdk_drawing_context_get_cairo_context (context);
|
||||
|
||||
g_return_if_fail (cr != NULL);
|
||||
|
||||
gsk_renderer_get_viewport (renderer, &viewport);
|
||||
|
||||
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
|
||||
{
|
||||
cairo_save (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_rectangle (cr,
|
||||
viewport.origin.x,
|
||||
viewport.origin.y,
|
||||
viewport.size.width,
|
||||
viewport.size.height);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0.85, 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
gsk_cairo_renderer_do_render (renderer, cr, root);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
|
||||
{
|
||||
@@ -108,6 +134,7 @@ gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
|
||||
renderer_class->realize = gsk_cairo_renderer_realize;
|
||||
renderer_class->unrealize = gsk_cairo_renderer_unrealize;
|
||||
renderer_class->render = gsk_cairo_renderer_render;
|
||||
renderer_class->render_texture = gsk_cairo_renderer_render_texture;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -462,7 +462,7 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
|
||||
if (gsk_texture_set_render_data (texture, driver, t, gsk_gl_driver_release_texture))
|
||||
t->user = texture;
|
||||
|
||||
surface = gsk_texture_download (texture);
|
||||
surface = gsk_texture_download_surface (texture);
|
||||
gsk_gl_driver_bind_source_texture (driver, t->texture_id);
|
||||
gsk_gl_driver_init_texture_with_surface (driver,
|
||||
t->texture_id,
|
||||
|
@@ -113,6 +113,15 @@ gsk_renderer_real_unrealize (GskRenderer *self)
|
||||
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, unrealize);
|
||||
}
|
||||
|
||||
static GskTexture *
|
||||
gsk_renderer_real_render_texture (GskRenderer *self,
|
||||
GskRenderNode *root,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, render_texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkDrawingContext *
|
||||
gsk_renderer_real_begin_draw_frame (GskRenderer *self,
|
||||
const cairo_region_t *region)
|
||||
@@ -259,6 +268,7 @@ gsk_renderer_class_init (GskRendererClass *klass)
|
||||
klass->begin_draw_frame = gsk_renderer_real_begin_draw_frame;
|
||||
klass->end_draw_frame = gsk_renderer_real_end_draw_frame;
|
||||
klass->render = gsk_renderer_real_render;
|
||||
klass->render_texture = gsk_renderer_real_render_texture;
|
||||
klass->create_cairo_surface = gsk_renderer_real_create_cairo_surface;
|
||||
|
||||
gobject_class->constructed = gsk_renderer_constructed;
|
||||
@@ -606,6 +616,75 @@ gsk_renderer_unrealize (GskRenderer *renderer)
|
||||
priv->is_realized = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_render_texture:
|
||||
* @renderer: a realized #GdkRenderer
|
||||
* @root: a #GskRenderNode
|
||||
* @viewport: (allow-none): the section to draw or %NULL to use @root's bounds
|
||||
*
|
||||
* Renders the scene graph, described by a tree of #GskRenderNode instances,
|
||||
* to a #GskTexture.
|
||||
*
|
||||
* The @renderer will acquire a reference on the #GskRenderNode tree while
|
||||
* the rendering is in progress, and will make the tree immutable.
|
||||
*
|
||||
* If you want to apply any transformations to @root, you should put it into a
|
||||
* transform node and pass that node instead.
|
||||
*
|
||||
* Returns: (transfer full): a #GskTexture with the rendered contents of @root.
|
||||
*
|
||||
* Since: 3.90
|
||||
*/
|
||||
GskTexture *
|
||||
gsk_renderer_render_texture (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
||||
graphene_rect_t real_viewport;
|
||||
GskTexture *texture;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
||||
g_return_val_if_fail (priv->is_realized, NULL);
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (root), NULL);
|
||||
g_return_val_if_fail (priv->root_node == NULL, NULL);
|
||||
|
||||
priv->root_node = gsk_render_node_ref (root);
|
||||
|
||||
if (viewport == NULL)
|
||||
{
|
||||
gsk_render_node_get_bounds (root, &real_viewport);
|
||||
viewport = &real_viewport;
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_reset (priv->profiler);
|
||||
#endif
|
||||
|
||||
texture = GSK_RENDERER_GET_CLASS (renderer)->render_texture (renderer, root, viewport);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_DEBUG_CHECK (RENDERER))
|
||||
{
|
||||
GString *buf = g_string_new ("*** Texture stats ***\n\n");
|
||||
|
||||
gsk_profiler_append_counters (priv->profiler, buf);
|
||||
g_string_append_c (buf, '\n');
|
||||
|
||||
gsk_profiler_append_timers (priv->profiler, buf);
|
||||
g_string_append_c (buf, '\n');
|
||||
|
||||
g_print ("%s\n***\n\n", buf->str);
|
||||
|
||||
g_string_free (buf, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_clear_pointer (&priv->root_node, gsk_render_node_unref);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_render:
|
||||
* @renderer: a #GskRenderer
|
||||
|
@@ -53,9 +53,6 @@ void gsk_renderer_set_scale_factor (GskRenderer
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
int gsk_renderer_get_scale_factor (GskRenderer *renderer);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gsk_renderer_set_window (GskRenderer *renderer,
|
||||
GdkWindow *window);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GdkWindow * gsk_renderer_get_window (GskRenderer *renderer);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
@@ -69,9 +66,9 @@ GDK_AVAILABLE_IN_3_90
|
||||
void gsk_renderer_unrealize (GskRenderer *renderer);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderer * gsk_renderer_create_fallback (GskRenderer *renderer,
|
||||
const graphene_rect_t *viewport,
|
||||
cairo_t *cr);
|
||||
GskTexture * gsk_renderer_render_texture (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
const graphene_rect_t *viewport);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GdkDrawingContext * gsk_renderer_begin_draw_frame (GskRenderer *renderer,
|
||||
|
@@ -42,6 +42,9 @@ struct _GskRendererClass
|
||||
GError **error);
|
||||
void (* unrealize) (GskRenderer *renderer);
|
||||
|
||||
GskTexture * (* render_texture) (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
const graphene_rect_t *viewport);
|
||||
GdkDrawingContext * (* begin_draw_frame) (GskRenderer *renderer,
|
||||
const cairo_region_t *region);
|
||||
void (* end_draw_frame) (GskRenderer *renderer,
|
||||
|
@@ -285,4 +285,54 @@ gsk_render_node_draw (GskRenderNode *node,
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
#define GSK_RENDER_NODE_SERIALIZATION_VERSION 0
|
||||
#define GSK_RENDER_NODE_SERIALIZATION_ID "GskRenderNode"
|
||||
|
||||
GBytes *
|
||||
gsk_render_node_serialize (GskRenderNode *node)
|
||||
{
|
||||
GVariant *node_variant, *variant;
|
||||
GBytes *result;
|
||||
|
||||
node_variant = gsk_render_node_serialize_node (node);
|
||||
|
||||
variant = g_variant_new ("(suuv)",
|
||||
GSK_RENDER_NODE_SERIALIZATION_ID,
|
||||
(guint32) GSK_RENDER_NODE_SERIALIZATION_VERSION,
|
||||
(guint32) gsk_render_node_get_node_type (node),
|
||||
node_variant);
|
||||
|
||||
result = g_variant_get_data_as_bytes (variant);
|
||||
g_variant_unref (variant);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
gsk_render_node_deserialize (GBytes *bytes)
|
||||
{
|
||||
char *id_string;
|
||||
guint32 version, node_type;
|
||||
GVariant *variant, *node_variant;
|
||||
GskRenderNode *node = NULL;
|
||||
|
||||
variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("(suuv)"), bytes, FALSE);
|
||||
|
||||
g_variant_get (variant, "(suuv)", &id_string, &version, &node_type, &node_variant);
|
||||
|
||||
if (!g_str_equal (id_string, GSK_RENDER_NODE_SERIALIZATION_ID))
|
||||
goto out;
|
||||
|
||||
if (version != GSK_RENDER_NODE_SERIALIZATION_VERSION)
|
||||
goto out;
|
||||
|
||||
node = gsk_render_node_deserialize_node (node_type, node_variant);
|
||||
|
||||
out:
|
||||
g_free (id_string);
|
||||
g_variant_unref (node_variant);
|
||||
g_variant_unref (variant);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,6 @@ struct _GskShadow
|
||||
GdkRGBA color;
|
||||
float dx;
|
||||
float dy;
|
||||
float spread;
|
||||
float radius;
|
||||
};
|
||||
|
||||
@@ -167,10 +166,19 @@ void gsk_render_node_set_name (GskRenderNode *
|
||||
const char *name);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
const char * gsk_render_node_get_name (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gsk_render_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *frame);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gsk_render_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GBytes * gsk_render_node_serialize (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderNode * gsk_render_node_deserialize (GBytes *bytes);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDER_NODE_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -34,18 +34,22 @@ struct _GskRenderNodeClass
|
||||
void (* finalize) (GskRenderNode *node);
|
||||
void (* draw) (GskRenderNode *node,
|
||||
cairo_t *cr);
|
||||
GVariant * (* serialize) (GskRenderNode *node);
|
||||
GskRenderNode * (* deserialize) (GVariant *variant);
|
||||
};
|
||||
|
||||
GskRenderNode *gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size);
|
||||
|
||||
void gsk_render_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *frame);
|
||||
GVariant * gsk_render_node_serialize_node (GskRenderNode *node);
|
||||
GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType type, GVariant *variant);
|
||||
|
||||
double gsk_opacity_node_get_opacity (GskRenderNode *node);
|
||||
|
||||
const GskRoundedRect * gsk_border_node_peek_outline (GskRenderNode *node);
|
||||
float gsk_border_node_get_width (GskRenderNode *node, guint i);
|
||||
const GdkRGBA * gsk_border_node_peek_color (GskRenderNode *node, guint i);
|
||||
|
||||
GskRenderNode *gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds, cairo_surface_t *surface);
|
||||
cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node);
|
||||
|
||||
GskTexture *gsk_texture_node_get_texture (GskRenderNode *node);
|
||||
|
107
gsk/gsktexture.c
107
gsk/gsktexture.c
@@ -37,6 +37,8 @@
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskrenderer.h"
|
||||
|
||||
#include "gdk/gdkinternals.h"
|
||||
|
||||
/**
|
||||
* GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref)
|
||||
*
|
||||
@@ -135,18 +137,43 @@ gsk_texture_cairo_finalize (GskTexture *texture)
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gsk_texture_cairo_download (GskTexture *texture)
|
||||
gsk_texture_cairo_download_surface (GskTexture *texture)
|
||||
{
|
||||
GskCairoTexture *cairo = (GskCairoTexture *) texture;
|
||||
|
||||
return cairo_surface_reference (cairo->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_cairo_download (GskTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GskCairoTexture *cairo = (GskCairoTexture *) texture;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height,
|
||||
stride);
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_set_source_surface (cr, cairo->surface, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static const GskTextureClass GSK_TEXTURE_CLASS_CAIRO = {
|
||||
"cairo",
|
||||
sizeof (GskCairoTexture),
|
||||
gsk_texture_cairo_finalize,
|
||||
gsk_texture_cairo_download
|
||||
gsk_texture_cairo_download,
|
||||
gsk_texture_cairo_download_surface
|
||||
};
|
||||
|
||||
GskTexture *
|
||||
@@ -208,8 +235,25 @@ gsk_texture_pixbuf_finalize (GskTexture *texture)
|
||||
g_object_unref (pixbuf->pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_pixbuf_download (GskTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GskPixbufTexture *pixbuf = (GskPixbufTexture *) texture;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height,
|
||||
stride);
|
||||
gdk_cairo_surface_paint_pixbuf (surface, pixbuf->pixbuf);
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gsk_texture_pixbuf_download (GskTexture *texture)
|
||||
gsk_texture_pixbuf_download_surface (GskTexture *texture)
|
||||
{
|
||||
GskPixbufTexture *pixbuf = (GskPixbufTexture *) texture;
|
||||
|
||||
@@ -220,7 +264,8 @@ static const GskTextureClass GSK_TEXTURE_CLASS_PIXBUF = {
|
||||
"pixbuf",
|
||||
sizeof (GskPixbufTexture),
|
||||
gsk_texture_pixbuf_finalize,
|
||||
gsk_texture_pixbuf_download
|
||||
gsk_texture_pixbuf_download,
|
||||
gsk_texture_pixbuf_download_surface
|
||||
};
|
||||
|
||||
GskTexture *
|
||||
@@ -276,9 +321,59 @@ gsk_texture_get_height (GskTexture *texture)
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
gsk_texture_download (GskTexture *texture)
|
||||
gsk_texture_download_surface (GskTexture *texture)
|
||||
{
|
||||
return texture->klass->download (texture);
|
||||
cairo_surface_t *surface;
|
||||
|
||||
if (texture->klass->download_surface)
|
||||
return texture->klass->download_surface (texture);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
gsk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_texture_download:
|
||||
* @texture: a #GskTexture
|
||||
* @data: pointer to enough memory to be filled with the
|
||||
* downloaded data of @texture
|
||||
* @stride: rowstride in bytes
|
||||
*
|
||||
* Downloads the @texture into local memory. This may be
|
||||
* an expensive operation, as the actual texture data may
|
||||
* reside on a GPU or on a remote display server.
|
||||
*
|
||||
* The data format of the downloaded data is equivalent to
|
||||
* %CAIRO_FORMAT_ARGB32, so every downloaded pixel requires
|
||||
* 4 bytes of memory.
|
||||
*
|
||||
* Downloading a texture into a Cairo image surface:
|
||||
* |[<!-- language="C" -->
|
||||
* surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
* gsk_texture_get_width (texture),
|
||||
* gsk_texture_get_height (texture));
|
||||
* gsk_texture_download (texture,
|
||||
* cairo_image_surface_get_data (surface),
|
||||
* cairo_image_surface_get_stride (surface));
|
||||
* cairo_surface_mark_dirty (surface);
|
||||
* ]|
|
||||
**/
|
||||
void
|
||||
gsk_texture_download (GskTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gsk_texture_get_width (texture) * 4);
|
||||
|
||||
return texture->klass->download (texture, data, stride);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -52,6 +52,11 @@ int gsk_texture_get_width (GskTexture
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
int gsk_texture_get_height (GskTexture *texture);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gsk_texture_download (GskTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_TEXTURE_H__ */
|
||||
|
@@ -30,14 +30,17 @@ struct _GskTextureClass {
|
||||
gsize size;
|
||||
|
||||
void (* finalize) (GskTexture *texture);
|
||||
cairo_surface_t * (* download) (GskTexture *texture);
|
||||
void (* download) (GskTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
cairo_surface_t * (* download_surface) (GskTexture *texture);
|
||||
};
|
||||
|
||||
gpointer gsk_texture_new (const GskTextureClass *klass,
|
||||
int width,
|
||||
int height);
|
||||
GskTexture * gsk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gsk_texture_download (GskTexture *texture);
|
||||
cairo_surface_t * gsk_texture_download_surface (GskTexture *texture);
|
||||
|
||||
gboolean gsk_texture_set_render_data (GskTexture *self,
|
||||
gpointer key,
|
||||
|
@@ -281,7 +281,7 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
||||
if (data)
|
||||
return g_object_ref (data->image);
|
||||
|
||||
surface = gsk_texture_download (texture);
|
||||
surface = gsk_texture_download_surface (texture);
|
||||
image = gsk_vulkan_image_new_from_data (uploader,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_width (surface),
|
||||
|
@@ -631,7 +631,6 @@ gtk_css_shadow_value_get_shadow (const GtkCssValue *value,
|
||||
shadow->color = *_gtk_css_rgba_value_get_rgba (value->color);
|
||||
shadow->dx = _gtk_css_number_value_get (value->hoffset, 0);
|
||||
shadow->dy = _gtk_css_number_value_get (value->voffset, 0);
|
||||
shadow->spread = _gtk_css_number_value_get (value->spread, 0);
|
||||
shadow->radius = _gtk_css_number_value_get (value->radius, 0);
|
||||
}
|
||||
|
||||
|
@@ -21,8 +21,10 @@
|
||||
#include "recorder.h"
|
||||
|
||||
#include <gtk/gtkbox.h>
|
||||
#include <gtk/gtkfilechooserdialog.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtklistbox.h>
|
||||
#include <gtk/gtkmessagedialog.h>
|
||||
#include <gtk/gtktogglebutton.h>
|
||||
#include <gtk/gtktreeselection.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
@@ -43,6 +45,7 @@ struct _GtkInspectorRecorderPrivate
|
||||
GtkWidget *recordings_list;
|
||||
GtkWidget *render_node_view;
|
||||
GtkWidget *render_node_tree;
|
||||
GtkWidget *render_node_save_button;
|
||||
GtkWidget *node_property_tree;
|
||||
GtkTreeModel *render_node_properties;
|
||||
|
||||
@@ -219,14 +222,92 @@ render_node_list_selection_changed (GtkTreeSelection *selection,
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
return;
|
||||
{
|
||||
gtk_widget_set_sensitive (priv->render_node_save_button, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (priv->render_node_save_button, TRUE);
|
||||
node = gtk_tree_model_render_node_get_node_from_iter (GTK_TREE_MODEL_RENDER_NODE (priv->render_node_model), &iter);
|
||||
gtk_render_node_view_set_render_node (GTK_RENDER_NODE_VIEW (priv->render_node_view), node);
|
||||
|
||||
populate_render_node_properties (GTK_LIST_STORE (priv->render_node_properties), node);
|
||||
}
|
||||
|
||||
static void
|
||||
render_node_save_response (GtkWidget *dialog,
|
||||
gint response,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
gtk_widget_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GBytes *bytes = gsk_render_node_serialize (node);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_file_replace_contents (gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)),
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL,
|
||||
FALSE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
GtkWidget *message_dialog;
|
||||
|
||||
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
_("Saving RenderNode failed"));
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
|
||||
"%s", error->message);
|
||||
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (message_dialog);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
render_node_save (GtkButton *button,
|
||||
GtkInspectorRecorder *recorder)
|
||||
{
|
||||
GtkInspectorRecorderPrivate *priv = gtk_inspector_recorder_get_instance_private (recorder);
|
||||
GskRenderNode *node;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *dialog;
|
||||
char *filename;
|
||||
|
||||
if (!gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->render_node_tree)), NULL, &iter))
|
||||
return;
|
||||
|
||||
node = gtk_tree_model_render_node_get_node_from_iter (GTK_TREE_MODEL_RENDER_NODE (priv->render_node_model), &iter);
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("",
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (recorder))),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Save"), GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
filename = g_strdup_printf ("%s.node", gsk_render_node_get_name (node) ? gsk_render_node_get_name (node)
|
||||
: node_type_name (gsk_render_node_get_node_type (node)));
|
||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
|
||||
g_free (filename);
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (render_node_save_response), node);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
static char *
|
||||
format_timespan (gint64 timespan)
|
||||
{
|
||||
@@ -394,11 +475,13 @@ gtk_inspector_recorder_class_init (GtkInspectorRecorderClass *klass)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, recordings_list);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, render_node_view);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, render_node_tree);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, render_node_save_button);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, node_property_tree);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, recordings_clear_all);
|
||||
gtk_widget_class_bind_template_callback (widget_class, recordings_list_row_selected);
|
||||
gtk_widget_class_bind_template_callback (widget_class, render_node_list_selection_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, render_node_save);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -33,6 +33,18 @@
|
||||
<property name="stack">render_stack</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="render_node_save_button">
|
||||
<property name="visible">1</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="sensitive">0</property>
|
||||
<property name="icon-name">document-save-as-symbolic</property>
|
||||
<signal name="clicked" handler="render_node_save"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
@@ -27,6 +27,7 @@ fontconfig_programs = testfontchooserdialog
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
rendernode \
|
||||
overlayscroll \
|
||||
syncscroll \
|
||||
animated-resizing \
|
||||
@@ -161,6 +162,7 @@ if USE_X11
|
||||
noinst_PROGRAMS += testerrors
|
||||
endif
|
||||
|
||||
rendernode_DEPENDENCIES = $(TEST_DEPS)
|
||||
animated_resizing_DEPENDENCIES = $(TEST_DEPS)
|
||||
animated_revealing_DEPENDENCIES = $(TEST_DEPS)
|
||||
flicker_DEPENDENCIES = $(TEST_DEPS)
|
||||
|
68
tests/rendernode.c
Normal file
68
tests/rendernode.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
graphene_rect_t bounds;
|
||||
cairo_surface_t *surface;
|
||||
GskRenderNode *node;
|
||||
cairo_t *cr;
|
||||
GError *error = NULL;
|
||||
GBytes *bytes;
|
||||
char *contents;
|
||||
gsize len;
|
||||
|
||||
if (!gtk_init_with_args (&argc, &argv, "NODE-FILE PNG-FILE",
|
||||
options, NULL, &error))
|
||||
{
|
||||
g_printerr ("Option parsing failed: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
g_printerr ("Usage: %s [OPTIONS] NODE-FILE PNG-FILE\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!g_file_get_contents (argv[1], &contents, &len, &error))
|
||||
{
|
||||
g_printerr ("Could not open node file: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (contents, len);
|
||||
node = gsk_render_node_deserialize (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
g_printerr ("Invalid node file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (bounds.size.width), ceil (bounds.size.height));
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_translate (cr, - bounds.origin.x, - bounds.origin.y);
|
||||
gsk_render_node_draw (node, cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
if (cairo_surface_write_to_png (surface, argv[2]))
|
||||
{
|
||||
cairo_surface_destroy (surface);
|
||||
g_print ("Failed to save PNG file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user