Compare commits

..

14 Commits

Author SHA1 Message Date
Matthias Clasen 08b786a984 tools: Add more commands to gtk4-path-tool
Add pathops.
2023-09-23 20:15:33 -04:00
Matthias Clasen 54bf63259c gtk-demo: Add a demo for path ops
This demo is called Glyphs, since that is what
it works with.
2023-09-23 20:15:33 -04:00
Matthias Clasen 53b5441e39 Add some tests for pathops 2023-09-23 20:15:33 -04:00
Matthias Clasen 3b2ab7ad1e Add API for boolean operations on paths
The new APIs here are:
gsk_path_union
gsk_path_intersection
gsk_path_difference
gsk_path_symmetric_difference
gsk_path_simplify
2023-09-23 20:15:33 -04:00
Matthias Clasen 42eaacbab4 Implement boolean operations on paths
Implement union, intersection, difference and
symmetric difference of two paths, as well as
simplification of a single path.
2023-09-23 20:15:33 -04:00
Matthias Clasen 6a1660b78e path-tool: Show intersections 2023-09-23 20:14:45 -04:00
Matthias Clasen 821fc35941 path-tool: Allow showing two paths 2023-09-23 20:14:45 -04:00
Matthias Clasen af0492ed0c Add a path intersection demo 2023-09-23 20:14:45 -04:00
Matthias Clasen dcdbb73702 Add some path intersection tests 2023-09-23 20:14:45 -04:00
Matthias Clasen 60b2cf5d4a Add gsk_path_foreach_intersection
This function makes it possible to iterate
through the intersections of two paths.
2023-09-23 20:14:45 -04:00
Matthias Clasen 2fcb20cc4a contour: Add private api to circle contours
Add api to retrieve the parameters of a circle
contour. This will be used in the following
commits.
2023-09-23 15:29:12 -04:00
Matthias Clasen 89567767c5 Add tests for gsk_curve_intersect 2023-09-23 15:29:12 -04:00
Matthias Clasen 6577f386b0 curve: Add gsk_curve_intersect
Add a way to find the intersections of two curves.
We can handle some curve-line intersections directly,
the general case is handled via bisection.
2023-09-23 15:29:12 -04:00
Matthias Clasen 6ce8bd6581 curve: Some refactoring
Move cusp-related code to gskcurveintersect.c.
Add functions to find cusps and inflection points of cubics.
These will be used for intersections and in the stroker.
2023-09-23 15:29:12 -04:00
155 changed files with 9014 additions and 10402 deletions
+5 -12
View File
@@ -217,32 +217,25 @@ macos-x86_64:
MESON_FORCE_BACKTRACKE: 1
TMPDIR: /Users/Shared/work/tmp
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
CCACHE_DIR: /Users/Shared/work/ccache
PIP_CACHE_DIR: /Users/Shared/build/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
EXTRA_MESON_FLAGS: "-Dgobject-introspection:werror=false"
before_script:
# Not using ccache on purpose as it accelerates the build so much that it
# can trigger race conditions in the gobject-introspection subproject.
- bash .gitlab-ci/show-info-osx.sh
- /opt/macports/bin/python3.10 -m venv .venv
- python3 -m venv .venv
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
- ln -s /opt/bison/bin/bison .venv/bin
- ln -s /opt/ccache/ccache .venv/bin
- source .venv/bin/activate
- pip3 install meson==1.2.0
- pip3 install ninja==1.11.1
- pip3 install /Users/Shared/build/pkgs/PyGObject-3.44.0-cp310-cp310-macosx_10_13_x86_64.whl
/Users/Shared/build/pkgs/pycairo-1.23.0-cp310-cp310-macosx_10_13_x86_64.whl
script:
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
- meson setup ${COMMON_MESON_FLAGS}
-Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=enabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
-Dlibjpeg-turbo:simd=disabled
+1 -60
View File
@@ -1,35 +1,4 @@
Overview of Changes in 4.13.3, xx-xx-xxxx
=========================================
Overview of Changes in 4.13.2, 22-10-2023
=========================================
* GtkPrintdialog:
- New async-style api to replace GtkPrintOperation
* GtkEmojiChooser:
- Add more languages: Bengali, Hindi, Japanese, Finnish,
Thai and Norwegian bokmål
* Accessibility:
- Fix some utf8 handling issues
* GDK:
- Add support for dmabuf textures, with GdkDmabufTextureBuilder
- Add a few more supported memory formats for textures
* GSK:
- Add a fast-path for masking color
- Add support for importing dmabuf textures
- Handle GLES better by using some extensions
* Translation updates:
Catalan
Russian
Turkish
Overview of Changes in 4.13.1, 28-09-2023
Overview of Changes in 4.13.1, xx-xx-xxxx
=========================================
* GtkTooltip:
@@ -38,32 +7,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* GtkCenterLayout, GtkEntry, GtkSearchEntry:
- Fix some issues with baseline handling
* GtkColorButton, GtkFontButton:
- Propagate focus-on-click
* GtkFileChooser:
- Make "Visit file" scroll to the file
* GtkSwitch:
- Respect text direction
* GtkWindow:
- Don't assume titlebars are GtkHeaderBars
* Printing:
- Fix some problems with the portal implementation
- Add a new simple print API: GtkPrintDialog
* Paths:
- GskPathMeasure performance has been improved
- Add custom contours for circles, rounded rectangles and rectangles
- Simplify GskPathPoint handling
- gsk_path_point_get_closest_point now returns the distance as well
- Make GskPathBuilder simplify curves
* Input:
- Handle (some) single-key compose sequences
- Fix active state tracking with sensitivity changes and grabs
* GSK:
- Make the repeated gradients match between GL and cairo
@@ -72,13 +29,6 @@ Overview of Changes in 4.13.1, 28-09-2023
- Restrict an optimization to the cases where it is crrect
- Fix rendering of shadows with opacity
- The Vulkan renderer now requires Vulkan 1.2
- GL: Transition gradients unpremultiplied
- GL: Fix clipping of shadows
- GL: Some optimizations
- Broadway: Fix memory leaks in the renderer
* Wayland:
- Make activation more reliable
* macOS:
- Clamp damage regions to the surface size
@@ -93,29 +43,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* Build:
- Fix build problems with C++ compilers
* Deprecations:
- gtk_window_present_with_time
* Translation updates
Brazilian Portuguese
British English
Catalan
Chinese (China)
Czech
Danish
Dutch
Esperanto
Galician
Georgian
Italian
Korean
Latvian
Lithuanian
Persian
Polish
Punjabi
Slovenian
Turkish
Overview of Changes in 4.13.0, 25-08-2023
+6
View File
@@ -295,6 +295,7 @@
<file>gears.c</file>
<file>gestures.c</file>
<file>glarea.c</file>
<file>glyphs.c</file>
<file>gltransition.c</file>
<file>headerbar.c</file>
<file>hypertext.c</file>
@@ -339,6 +340,7 @@
<file>path_fill.c</file>
<file>path_maze.c</file>
<file>path_spinner.c</file>
<file>path_sweep.c</file>
<file>path_walk.c</file>
<file>path_text.c</file>
<file>peg_solitaire.c</file>
@@ -426,6 +428,10 @@
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/path_sweep">
<file>path_sweep.ui</file>
<file compressed="true">path_world.txt</file>
</gresource>
<gresource prefix="/path_walk">
<file>path_walk.ui</file>
<file compressed="true">path_world.txt</file>
+2 -4
View File
@@ -34,7 +34,7 @@ transition (GtkWidget *widget,
{
DemoWidget *self = DEMO_WIDGET (widget);
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
gint64 now = g_get_monotonic_time ();
gtk_widget_queue_allocate (widget);
@@ -66,13 +66,11 @@ clicked (GtkGestureClick *gesture,
gpointer data)
{
DemoWidget *self = data;
GdkFrameClock *frame_clock;
if (self->tick_id != 0)
return;
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
self->start_time = g_get_monotonic_time ();
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
}
File diff suppressed because it is too large Load Diff
+2
View File
@@ -34,6 +34,7 @@ demos = files([
'gestures.c',
'glarea.c',
'gltransition.c',
'glyphs.c',
'headerbar.c',
'hypertext.c',
'iconscroll.c',
@@ -75,6 +76,7 @@ demos = files([
'path_fill.c',
'path_maze.c',
'path_spinner.c',
'path_sweep.c',
'path_walk.c',
'path_text.c',
'peg_solitaire.c',
+1 -98
View File
@@ -2,13 +2,10 @@
*
* This demo shows how to use GskPath to draw shapes that are (a bit)
* more complex than a rounded rectangle.
*
* It also demonstrates printing to a stream with GtkPrintDialog.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <cairo-pdf.h>
#include "paintable.h"
@@ -168,89 +165,6 @@ gtk_logo_paintable_new (void)
return GDK_PAINTABLE (self);
}
static cairo_status_t
write_cairo (void *closure,
const unsigned char *data,
unsigned int length)
{
GOutputStream *stream = closure;
gsize written;
GError *error = NULL;
if (!g_output_stream_write_all (stream, data, length, &written, NULL, &error))
{
g_print ("Error writing pdf stream: %s\n", error->message);
g_error_free (error);
return CAIRO_STATUS_WRITE_ERROR;
}
return CAIRO_STATUS_SUCCESS;
}
static void
print_ready (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GOutputStream *stream;
GtkSnapshot *snapshot;
GdkPaintable *paintable;
GskRenderNode *node;
cairo_surface_t *surface;
cairo_t *cr;
stream = gtk_print_dialog_print_finish (dialog, result, &error);
if (stream == NULL)
{
g_print ("Failed to get output stream: %s\n", error->message);
g_error_free (error);
return;
}
snapshot = gtk_snapshot_new ();
paintable = gtk_picture_get_paintable (GTK_PICTURE (data));
gdk_paintable_snapshot (paintable, snapshot, 100, 100);
node = gtk_snapshot_free_to_node (snapshot);
surface = cairo_pdf_surface_create_for_stream (write_cairo, stream, 100, 100);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
gsk_render_node_unref (node);
if (!g_output_stream_close (stream, NULL, &error))
{
g_print ("Error from close: %s\n", error->message);
g_error_free (error);
}
g_object_unref (stream);
}
static void
print (GtkButton *button,
gpointer data)
{
GtkWidget *picture = data;
GtkPrintDialog *dialog;
dialog = gtk_print_dialog_new ();
gtk_print_dialog_print (dialog,
GTK_WINDOW (gtk_widget_get_root (picture)),
NULL,
NULL,
print_ready,
picture);
g_object_unref (dialog);
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
@@ -258,21 +172,12 @@ do_path_fill (GtkWidget *do_widget)
if (!window)
{
GtkWidget *header, *button, *label;
GtkWidget *picture;
GdkPaintable *paintable;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Fill and Stroke");
header = gtk_header_bar_new ();
button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
label = gtk_label_new ("Fill and Stroke");
gtk_widget_add_css_class (label, "title");
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header), label);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paintable = gtk_logo_paintable_new ();
@@ -281,8 +186,6 @@ do_path_fill (GtkWidget *do_widget)
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
g_signal_connect (button, "clicked", G_CALLBACK (print), picture);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
+319
View File
@@ -0,0 +1,319 @@
/* Path/Sweep
*
* This demo shows how path intersections can be used.
*
* The world map that is used here is a path with 211 lines and 1569 cubic
* Bėzier segments in 121 contours.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_SWEEP (gtk_path_sweep_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathSweep, gtk_path_sweep, GTK, PATH_SWEEP, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_PATH,
N_PROPS
};
struct _GtkPathSweep
{
GtkWidget parent_instance;
GskPath *path;
graphene_rect_t bounds;
float y_pos;
gboolean in;
};
struct _GtkPathSweepClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathSweep, gtk_path_sweep, GTK_TYPE_WIDGET)
static gboolean
intersection_cb (GskPath *path1,
const GskPathPoint *point1,
GskPath *path2,
const GskPathPoint *point2,
GskPathIntersection kind,
gpointer data)
{
GskPathBuilder *builder = data;
graphene_point_t p;
gsk_path_point_get_position (point1, path1, &p);
gsk_path_builder_add_circle (builder, &p, 4);
return TRUE;
}
static GskPath *
get_intersection_path (GskPath *path1,
GskPath *path2)
{
GskPathBuilder *builder = gsk_path_builder_new ();
gsk_path_foreach_intersection (path1, path2, intersection_cb, builder);
return gsk_path_builder_to_path (builder);
}
static void
gtk_path_sweep_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathSweep *self = GTK_PATH_SWEEP (widget);
GskStroke *stroke;
if (self->path == NULL)
return;
gtk_snapshot_save (snapshot);
stroke = gsk_stroke_new (2.0);
gtk_snapshot_append_stroke (snapshot, self->path, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
if (self->in)
{
graphene_rect_t bounds;
GskPathBuilder *builder;
GskPath *line, *isecs;
gsk_path_get_stroke_bounds (self->path, stroke, &bounds);
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, bounds.origin.x, bounds.origin.y + self->y_pos);
gsk_path_builder_line_to (builder, bounds.origin.x + bounds.size.width, bounds.origin.y + self->y_pos);
line = gsk_path_builder_free_to_path (builder);
gtk_snapshot_append_stroke (snapshot, line, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
isecs = get_intersection_path (self->path, line);
gtk_snapshot_append_fill (snapshot, isecs, GSK_FILL_RULE_WINDING, &(GdkRGBA) { 1, 0, 0, 1 });
gtk_snapshot_append_stroke (snapshot, isecs, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
gsk_path_unref (isecs);
gsk_path_unref (line);
}
gsk_stroke_free (stroke);
gtk_snapshot_restore (snapshot);
}
static void
gtk_path_sweep_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkPathSweep *self = GTK_PATH_SWEEP (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = (int) ceilf (self->bounds.size.width);
else
*minimum = *natural = (int) ceilf (self->bounds.size.height);
}
static void
gtk_path_sweep_set_path (GtkPathSweep *self,
GskPath *path)
{
if (self->path == path)
return;
g_clear_pointer (&self->path, gsk_path_unref);
graphene_rect_init (&self->bounds, 0, 0, 0, 0);
if (path)
{
GskStroke *stroke;
self->path = gsk_path_ref (path);
stroke = gsk_stroke_new (2.0);
gsk_path_get_stroke_bounds (path, stroke, &self->bounds);
gsk_stroke_free (stroke);
}
gtk_widget_queue_resize (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PATH]);
}
static void
gtk_path_sweep_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
switch (prop_id)
{
case PROP_PATH:
gtk_path_sweep_set_path (self, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_sweep_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
switch (prop_id)
{
case PROP_PATH:
g_value_set_boxed (value, self->path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_sweep_dispose (GObject *object)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
g_clear_pointer (&self->path, gsk_path_unref);
G_OBJECT_CLASS (gtk_path_sweep_parent_class)->dispose (object);
}
static void
gtk_path_sweep_class_init (GtkPathSweepClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_sweep_dispose;
object_class->set_property = gtk_path_sweep_set_property;
object_class->get_property = gtk_path_sweep_get_property;
widget_class->snapshot = gtk_path_sweep_snapshot;
widget_class->measure = gtk_path_sweep_measure;
properties[PROP_PATH] =
g_param_spec_boxed ("path", NULL, NULL,
GSK_TYPE_PATH,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
motion_cb (GtkEventControllerMotion *controller,
double x,
double y,
gpointer data)
{
GtkPathSweep *self = data;
self->y_pos = y;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
enter_cb (GtkEventControllerMotion *controller,
double x,
double y,
gpointer data)
{
GtkPathSweep *self = data;
self->in = TRUE;
self->y_pos = y;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
leave_cb (GtkEventControllerMotion *controller,
gpointer data)
{
GtkPathSweep *self = data;
self->in = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
gtk_path_sweep_init (GtkPathSweep *self)
{
GtkEventController *controller;
/* Data taken from
* https://commons.wikimedia.org/wiki/Maps_of_the_world#/media/File:Simplified_blank_world_map_without_Antartica_(no_borders).svg
*/
GBytes *data = g_resources_lookup_data ("/path_sweep/path_world.txt", 0, NULL);
GskPath *path = gsk_path_parse (g_bytes_get_data (data, NULL));
g_bytes_unref (data);
gtk_path_sweep_set_path (self, path);
gsk_path_unref (path);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), self);
g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
GtkWidget *
gtk_path_sweep_new (void)
{
GtkPathSweep *self;
self = g_object_new (GTK_TYPE_PATH_SWEEP, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_sweep (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_SWEEP);
builder = gtk_builder_new_from_resource ("/path_sweep/path_sweep.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">World Map</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkPathSweep" id="view">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</property>
</object>
</interface>
+3 -70
View File
@@ -1,9 +1,8 @@
/* Pickers and Launchers
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkPrintDialog, GtkFileLauncher, GtkUriLauncher
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
*
* The dialogs are mainly intended for use in preference dialogs.
* They allow to select colors, fonts and files. There is also a
* print dialog.
* They allow to select colors, fonts and applications.
*
* The launchers let you open files or URIs in applications that
* can handle them.
@@ -12,13 +11,11 @@
#include <gtk/gtk.h>
static GtkWidget *app_picker;
static GtkWidget *print_button;
static void
set_file (GFile *file,
gpointer data)
{
GFileInfo *info;
char *name;
if (!file)
@@ -34,13 +31,6 @@ set_file (GFile *file,
gtk_widget_set_sensitive (app_picker, TRUE);
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
info = g_file_query_info (file, "standard::content-type", 0, NULL, NULL);
if (strcmp (g_file_info_get_content_type (info), "application/pdf") == 0)
{
gtk_widget_set_sensitive (print_button, TRUE);
g_object_set_data_full (G_OBJECT (print_button), "file", g_object_ref (file), g_object_unref);
}
}
static void
@@ -57,10 +47,6 @@ file_opened (GObject *source,
{
g_print ("%s\n", error->message);
g_error_free (error);
gtk_widget_set_sensitive (app_picker, FALSE);
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
gtk_widget_set_sensitive (print_button, FALSE);
g_object_set_data (G_OBJECT (print_button), "file", NULL);
}
set_file (file, data);
@@ -128,53 +114,6 @@ open_app (GtkButton *picker)
g_object_unref (launcher);
}
static void
print_file_done (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GCancellable *cancellable;
unsigned int id;
cancellable = g_task_get_cancellable (G_TASK (result));
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cancellable), "timeout"));
if (id)
g_source_remove (id);
if (!gtk_print_dialog_print_file_finish (dialog, result, &error))
{
g_print ("%s\n", error->message);
g_error_free (error);
}
}
static void
print_file (GtkButton *picker)
{
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
GtkPrintDialog *dialog;
GCancellable *cancellable;
GFile *file;
unsigned int id;
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
dialog = gtk_print_dialog_new ();
cancellable = g_cancellable_new ();
id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
20,
abort_mission, g_object_ref (cancellable), g_object_unref);
g_object_set_data (G_OBJECT (cancellable), "timeout", GUINT_TO_POINTER (id));
gtk_print_dialog_print_file (dialog, parent, NULL, file, cancellable, print_file_done, NULL);
g_object_unref (cancellable);
g_object_unref (dialog);
}
static void
open_uri_done (GObject *source,
GAsyncResult *result,
@@ -295,15 +234,9 @@ do_pickers (GtkWidget *do_widget)
gtk_widget_set_sensitive (app_picker, FALSE);
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
gtk_box_append (GTK_BOX (picker), app_picker);
print_button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_widget_set_tooltip_text (print_button, "Print file");
gtk_widget_set_sensitive (print_button, FALSE);
g_signal_connect (print_button, "clicked", G_CALLBACK (print_file), NULL);
gtk_box_append (GTK_BOX (picker), print_button);
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
label = gtk_label_new ("URI:");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+21
View File
@@ -12,6 +12,11 @@ SYNOPSIS
--------
| **gtk4-path-tool** <COMMAND> [OPTIONS...] <PATH>
|
| **gtk4-path-tool** simplify [OPTIONS...] <PATH>
| **gtk4-path-tool** intersection [OPTIONS...] <PATH> <PATH>
| **gtk4-path-tool** union [OPTIONS...] <PATH> <PATH>
| **gtk4-path-tool** difference [OPTIONS...] <PATH> <PATH>
| **gtk4-path-tool** symmetric-difference [OPTIONS...] <PATH> <PATH>
| **gtk4-path-tool** decompose [OPTIONS...] <PATH>
| **gtk4-path-tool** show [OPTIONS...] <PATH>
| **gtk4-path-tool** render [OPTIONS...] <PATH>
@@ -195,6 +200,7 @@ The interior of the path is filled.
The limit at which to clip miters at line joins. The default value is 4.
<<<<<<< HEAD
``--dashes=VALUE``
The dash pattern to use for this stroke. A dash pattern is specified by
@@ -208,6 +214,21 @@ The interior of the path is filled.
The offset into the dash pattern where dashing should begin.
The default value is 0.
Boolean Operations
^^^^^^^^^^^^^^^^^^
The ``intersection``, ``union``, ``difference`` and ``symmetric-difference`` commands
perform boolean operations on paths. Given two paths, they create a new path which
encircles the area that is the intersection, union, difference or symmetric difference
of the areas encircled by the paths.
Simplification
^^^^^^^^^^^^^^
The ``simplify`` command removes areas of overlap from a path such that the resulting
path encircles the same area, but every edge in the resulting path is a boundary between
the inside and the outside.
Reversing
^^^^^^^^^
+13 -28
View File
@@ -170,41 +170,35 @@ This variable can be set to a list of debug options, which cause GDK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
`misc`
: Miscellaneous information
`events`
: Information about events
`dnd`
: Information about drag-and-drop
`input`
: Information about input (mostly Windows)
`cursor`
: Information about cursor objects (only win32)
`eventloop`
: Information about event loop operation (mostly macOS)
`misc`
: Miscellaneous information
`frames`
: Information about the frame clock
`settings`
: Information about xsettings
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
`selection`
: Information about selections
`clipboard`
: Information about clipboards
`dmabuf`
: Information about dmabuf handling (Linux-only)
`dnd`
: Information about drag-and-drop
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
A number of options affect behavior instead of logging:
@@ -223,9 +217,6 @@ A number of options affect behavior instead of logging:
`gl-fractional`
: Enable fractional scaling for OpenGL. This is experimental
`gl-debug`
: Insert debugging information in OpenGL
`gl-legacy`
: Use a legacy OpenGL context
@@ -253,12 +244,6 @@ A number of options affect behavior instead of logging:
`high-depth`
: Use high bit depth rendering if possible
`no-vsync`
: Repaint instantly (uses 100% CPU with animations)
`dmabuf-disable`
: Disable dmabuf support
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to obtain a list of all supported debug options.
+1 -4
View File
@@ -117,8 +117,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "vulkan", GDK_DEBUG_VULKAN, "Information about Vulkan" },
{ "selection", GDK_DEBUG_SELECTION, "Information about selections" },
{ "clipboard", GDK_DEBUG_CLIPBOARD, "Information about clipboards" },
{ "dmabuf", GDK_DEBUG_DMABUF, "Information about dmabuf buffers" },
{ "nograbs", GDK_DEBUG_NOGRABS, "Disable pointer and keyboard grabs (X11)", TRUE },
{ "portals", GDK_DEBUG_PORTALS, "Force use of portals", TRUE },
{ "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals", TRUE },
@@ -135,7 +133,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible", TRUE },
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)", TRUE },
{ "dmabuf-disable", GDK_DEBUG_DMABUF_DISABLE, "Disable dmabuf support", TRUE },
};
@@ -266,7 +263,7 @@ gdk_parse_debug_var (const char *variable,
if (debug_enabled || keys[i].always_enabled)
fprintf (stderr, " %s%*s%s\n", keys[i].key, (int)(max_width - strlen (keys[i].key)), " ", keys[i].help);
}
fprintf (stderr, " %s%*s%s\n", "all", max_width - 3, " ", "Enable all values. Other given values are subtracted");
fprintf (stderr, " %s%*s%s\n", "all", max_width - 3, " ", "Enable all values");
fprintf (stderr, " %s%*s%s\n", "help", max_width - 4, " ", "Print this help");
fprintf (stderr, "\nMultiple values can be given, separated by : or space.\n");
}
-3
View File
@@ -42,9 +42,6 @@
#include <gdk/gdkdevicetool.h>
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdmabufformats.h>
#include <gdk/gdkdmabuftexture.h>
#include <gdk/gdkdmabuftexturebuilder.h>
#include <gdk/gdkdrag.h>
#include <gdk/gdkdragsurface.h>
#include <gdk/gdkdragsurfacesize.h>
+1 -7
View File
@@ -183,7 +183,7 @@ gdk_array(reserve) (GdkArray *self,
return;
size = gdk_array(get_size) (self);
new_size = ((gsize) 1) << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
#ifdef GDK_ARRAY_PREALLOC
if (self->start == self->preallocated)
@@ -215,11 +215,7 @@ gdk_array(splice) (GdkArray *self,
gsize pos,
gsize removed,
gboolean stolen,
#ifdef GDK_ARRAY_BY_VALUE
const _T_ *additions,
#else
_T_ *additions,
#endif
gsize added)
{
gsize size;
@@ -322,5 +318,3 @@ gdk_array(get) (const GdkArray *self,
#undef GDK_ARRAY_TYPE_NAME
#undef GDK_ARRAY_NO_MEMSET
#endif
G_END_DECLS
+16 -19
View File
@@ -36,26 +36,23 @@ typedef enum {
GDK_DEBUG_VULKAN = 1 << 8,
GDK_DEBUG_SELECTION = 1 << 9,
GDK_DEBUG_CLIPBOARD = 1 << 10,
GDK_DEBUG_DMABUF = 1 << 11,
/* flags below are influencing behavior */
GDK_DEBUG_NOGRABS = 1 << 12,
GDK_DEBUG_PORTALS = 1 << 13,
GDK_DEBUG_NO_PORTALS = 1 << 14,
GDK_DEBUG_GL_DISABLE = 1 << 15,
GDK_DEBUG_GL_FRACTIONAL = 1 << 16,
GDK_DEBUG_GL_LEGACY = 1 << 17,
GDK_DEBUG_GL_GLES = 1 << 18,
GDK_DEBUG_GL_DEBUG = 1 << 19,
GDK_DEBUG_GL_EGL = 1 << 20,
GDK_DEBUG_GL_GLX = 1 << 21,
GDK_DEBUG_GL_WGL = 1 << 22,
GDK_DEBUG_VULKAN_DISABLE = 1 << 23,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 24,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 25,
GDK_DEBUG_HIGH_DEPTH = 1 << 26,
GDK_DEBUG_NO_VSYNC = 1 << 27,
GDK_DEBUG_DMABUF_DISABLE = 1 << 28,
GDK_DEBUG_NOGRABS = 1 << 11,
GDK_DEBUG_PORTALS = 1 << 12,
GDK_DEBUG_NO_PORTALS = 1 << 13,
GDK_DEBUG_GL_DISABLE = 1 << 14,
GDK_DEBUG_GL_FRACTIONAL = 1 << 15,
GDK_DEBUG_GL_LEGACY = 1 << 16,
GDK_DEBUG_GL_GLES = 1 << 17,
GDK_DEBUG_GL_DEBUG = 1 << 18,
GDK_DEBUG_GL_EGL = 1 << 19,
GDK_DEBUG_GL_GLX = 1 << 20,
GDK_DEBUG_GL_WGL = 1 << 21,
GDK_DEBUG_VULKAN_DISABLE = 1 << 22,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 23,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 24,
GDK_DEBUG_HIGH_DEPTH = 1 << 25,
GDK_DEBUG_NO_VSYNC = 1 << 26,
} GdkDebugFlags;
extern guint _gdk_debug_flags;
-108
View File
@@ -31,9 +31,6 @@
#include "gdkclipboardprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdisplaymanagerprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkeventsprivate.h"
#include "gdkframeclockidleprivate.h"
#include "gdkglcontextprivate.h"
@@ -72,7 +69,6 @@ enum
PROP_COMPOSITED,
PROP_RGBA,
PROP_INPUT_SHAPES,
PROP_DMABUF_FORMATS,
LAST_PROP
};
@@ -142,10 +138,6 @@ gdk_display_get_property (GObject *object,
g_value_set_boolean (value, gdk_display_supports_input_shapes (display));
break;
case PROP_DMABUF_FORMATS:
g_value_set_boxed (value, gdk_display_get_dmabuf_formats (display));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -247,11 +239,6 @@ gdk_display_class_init (GdkDisplayClass *class)
TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
props[PROP_DMABUF_FORMATS] =
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
GDK_TYPE_DMABUF_FORMATS,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, props);
/**
@@ -391,9 +378,6 @@ gdk_display_dispose (GObject *object)
g_queue_clear (&display->queued_events);
g_clear_object (&display->egl_gsk_renderer);
g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref);
g_clear_object (&priv->gl_context);
#ifdef HAVE_EGL
g_clear_pointer (&priv->egl_display, eglTerminate);
@@ -420,8 +404,6 @@ gdk_display_finalize (GObject *object)
g_list_free_full (display->seats, g_object_unref);
g_clear_pointer (&display->dmabuf_formats, gdk_dmabuf_formats_unref);
G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
}
@@ -1773,10 +1755,6 @@ gdk_display_init_egl (GdkDisplay *self,
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
self->have_egl_pixel_format_float =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
self->have_egl_dma_buf_import =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_image_dma_buf_import_modifiers");
self->have_egl_dma_buf_export =
epoxy_has_egl_extension (priv->egl_display, "EGL_MESA_image_dma_buf_export");
if (self->have_egl_no_config_context)
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
@@ -1846,92 +1824,6 @@ gdk_display_get_egl_display (GdkDisplay *self)
#endif
}
#ifdef HAVE_DMABUF
static void
gdk_display_add_dmabuf_downloader (GdkDisplay *display,
const GdkDmabufDownloader *downloader,
GdkDmabufFormatsBuilder *builder)
{
gsize i;
if (!downloader->add_formats (downloader, display, builder))
return;
/* dmabuf_downloaders is NULL-terminated */
for (i = 0; i < G_N_ELEMENTS (display->dmabuf_downloaders) - 1; i++)
{
if (display->dmabuf_downloaders[i] == NULL)
break;
}
g_assert (i < G_N_ELEMENTS (display->dmabuf_downloaders));
display->dmabuf_downloaders[i] = downloader;
}
#endif
/* To support a drm format, we must be able to import it into GL
* using the relevant EGL extensions, and download it into a memory
* texture, possibly doing format conversion with shaders (in GSK).
*/
void
gdk_display_init_dmabuf (GdkDisplay *self)
{
GdkDmabufFormatsBuilder *builder;
if (self->dmabuf_formats != NULL)
return;
GDK_DISPLAY_DEBUG (self, DMABUF,
"Beginning initialization of dmabuf support");
builder = gdk_dmabuf_formats_builder_new ();
#ifdef HAVE_DMABUF
if (!GDK_DEBUG_CHECK (DMABUF_DISABLE))
{
gdk_display_prepare_gl (self, NULL);
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_direct_downloader (), builder);
#ifdef HAVE_EGL
if (gdk_display_prepare_gl (self, NULL))
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_egl_downloader (), builder);
#endif
}
#endif
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
GDK_DISPLAY_DEBUG (self, DMABUF,
"Initialized support for %zu dmabuf formats",
gdk_dmabuf_formats_get_n_formats (self->dmabuf_formats));
}
/**
* gdk_display_get_dmabuf_formats:
* @display: a `GdkDisplay`
*
* Returns the dma-buf formats that are supported on this display.
*
* GTK may use OpenGL or Vulkan to support some formats.
* Calling this function will then initialize them if they aren't yet.
*
* The formats returned by this function can be used for negotiating
* buffer formats with producers such as v4l, pipewire or GStreamer.
*
* Returns: (transfer none): a `GdkDmabufFormats` object
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_display_get_dmabuf_formats (GdkDisplay *display)
{
gdk_display_init_dmabuf (display);
return display->dmabuf_formats;
}
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{
-4
View File
@@ -134,10 +134,6 @@ gboolean gdk_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value);
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats *
gdk_display_get_dmabuf_formats (GdkDisplay *display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
G_END_DECLS
-12
View File
@@ -25,7 +25,6 @@
#include "gdksurfaceprivate.h"
#include "gdkkeysprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdmabufprivate.h"
#ifdef GDK_RENDERING_VULKAN
#include <vulkan/vulkan.h>
@@ -114,15 +113,6 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
guint have_egl_dma_buf_import : 1;
guint have_egl_dma_buf_export : 1;
GdkDmabufFormats *dmabuf_formats;
const GdkDmabufDownloader *dmabuf_downloaders[4];
/* Cached data the EGL dmabuf downloader */
gpointer egl_gsk_renderer;
GdkDmabufFormats *egl_external_formats;
};
struct _GdkDisplayClass
@@ -217,8 +207,6 @@ gulong _gdk_display_get_next_serial (GdkDisplay *display
void _gdk_display_pause_events (GdkDisplay *display);
void _gdk_display_unpause_events (GdkDisplay *display);
void gdk_display_init_dmabuf (GdkDisplay *self);
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
GError **error);
-745
View File
@@ -1,745 +0,0 @@
/* gdkdmabuf.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdmabufprivate.h"
#include "gdkdebugprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#ifdef HAVE_DMABUF
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm_fourcc.h>
#include <epoxy/egl.h>
typedef struct _GdkDrmFormatInfo GdkDrmFormatInfo;
struct _GdkDrmFormatInfo
{
guint32 fourcc;
GdkMemoryFormat premultiplied_memory_format;
GdkMemoryFormat unpremultiplied_memory_format;
void (* download) (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES]);
};
static void
download_memcpy (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES])
{
const guchar *src_data;
gsize src_stride;
guint bpp;
bpp = gdk_memory_format_bytes_per_pixel (dst_format);
src_stride = dmabuf->planes[0].stride;
src_data = src_datas[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + (height - 1) * dst_stride + width * bpp);
if (dst_stride == src_stride)
memcpy (dst_data, src_data, (height - 1) * dst_stride + width * bpp);
else
{
gsize i;
for (i = 0; i < height; i++)
memcpy (dst_data + i * dst_stride, src_data + i * src_stride, width * bpp);
}
}
typedef struct _YUVCoefficients YUVCoefficients;
struct _YUVCoefficients
{
int v_to_r;
int u_to_g;
int v_to_g;
int u_to_b;
};
/* multiplied by 65536 */
//static const YUVCoefficients itu601_narrow = { 104597, -25675, -53279, 132201 };
static const YUVCoefficients itu601_wide = { 74711, -25864, -38050, 133176 };
static inline void
get_uv_values (const YUVCoefficients *coeffs,
guint8 u,
guint8 v,
int *out_r,
int *out_g,
int *out_b)
{
int u2 = (int) u - 127;
int v2 = (int) v - 127;
*out_r = coeffs->v_to_r * v2;
*out_g = coeffs->u_to_g * u2 + coeffs->v_to_g * v2;
*out_b = coeffs->u_to_b * u2;
}
static inline void
set_rgb_values (guint8 rgb[3],
guint8 y,
int r,
int g,
int b)
{
int y2 = y * 65536;
rgb[0] = CLAMP ((y2 + r) >> 16, 0, 255);
rgb[1] = CLAMP ((y2 + g) >> 16, 0, 255);
rgb[2] = CLAMP ((y2 + b) >> 16, 0, 255);
}
static void
download_nv12 (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES])
{
const guchar *y_data, *uv_data;
gsize x, y, y_stride, uv_stride;
gsize U, V, X_SUB, Y_SUB;
switch (dmabuf->fourcc)
{
case DRM_FORMAT_NV12:
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_NV21:
U = 1; V = 0; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_NV16:
U = 0; V = 1; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_NV61:
U = 1; V = 0; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_NV24:
U = 0; V = 1; X_SUB = 1; Y_SUB = 1;
break;
case DRM_FORMAT_NV42:
U = 1; V = 0; X_SUB = 1; Y_SUB = 1;
break;
default:
g_assert_not_reached ();
return;
}
y_stride = dmabuf->planes[0].stride;
y_data = src_data[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
uv_stride = dmabuf->planes[1].stride;
uv_data = src_data[1] + dmabuf->planes[1].offset;
g_return_if_fail (sizes[1] >= dmabuf->planes[1].offset + (height + Y_SUB - 1) / Y_SUB * uv_stride);
for (y = 0; y < height; y += Y_SUB)
{
for (x = 0; x < width; x += X_SUB)
{
int r, g, b;
gsize xs, ys;
get_uv_values (&itu601_wide, uv_data[x / X_SUB * 2 + U], uv_data[x / X_SUB * 2 + V], &r, &g, &b);
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
}
dst_data += Y_SUB * dst_stride;
y_data += Y_SUB * y_stride;
uv_data += uv_stride;
}
}
static void
download_yuv_3 (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES])
{
const guchar *y_data, *u_data, *v_data;
gsize x, y, y_stride, u_stride, v_stride;
gsize U, V, X_SUB, Y_SUB;
switch (dmabuf->fourcc)
{
case DRM_FORMAT_YUV410:
U = 1; V = 2; X_SUB = 4; Y_SUB = 4;
break;
case DRM_FORMAT_YVU410:
U = 2; V = 1; X_SUB = 4; Y_SUB = 4;
break;
case DRM_FORMAT_YUV411:
U = 1; V = 2; X_SUB = 4; Y_SUB = 1;
break;
case DRM_FORMAT_YVU411:
U = 2; V = 1; X_SUB = 4; Y_SUB = 1;
break;
case DRM_FORMAT_YUV420:
U = 1; V = 2; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_YVU420:
U = 2; V = 1; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_YUV422:
U = 1; V = 2; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_YVU422:
U = 2; V = 1; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_YUV444:
U = 1; V = 2; X_SUB = 1; Y_SUB = 1;
break;
case DRM_FORMAT_YVU444:
U = 2; V = 1; X_SUB = 1; Y_SUB = 1;
break;
default:
g_assert_not_reached ();
return;
}
y_stride = dmabuf->planes[0].stride;
y_data = src_data[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
u_stride = dmabuf->planes[U].stride;
u_data = src_data[U] + dmabuf->planes[U].offset;
g_return_if_fail (sizes[U] >= dmabuf->planes[U].offset + (height + Y_SUB - 1) / Y_SUB * u_stride);
v_stride = dmabuf->planes[V].stride;
v_data = src_data[V] + dmabuf->planes[V].offset;
g_return_if_fail (sizes[V] >= dmabuf->planes[V].offset + (height + Y_SUB - 1) / Y_SUB * v_stride);
for (y = 0; y < height; y += Y_SUB)
{
for (x = 0; x < width; x += X_SUB)
{
int r, g, b;
gsize xs, ys;
get_uv_values (&itu601_wide, u_data[x / X_SUB], v_data[x / X_SUB], &r, &g, &b);
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
}
dst_data += Y_SUB * dst_stride;
y_data += Y_SUB * y_stride;
u_data += u_stride;
v_data += v_stride;
}
}
static void
download_yuyv (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES])
{
const guchar *src_data;
gsize x, y, src_stride;
gsize Y1, Y2, U, V;
switch (dmabuf->fourcc)
{
case DRM_FORMAT_YUYV:
Y1 = 0; U = 1; Y2 = 2; V = 3;
break;
case DRM_FORMAT_YVYU:
Y1 = 0; V = 1; Y2 = 2; U = 3;
break;
case DRM_FORMAT_UYVY:
U = 0; Y1 = 1; V = 2; Y2 = 3;
break;
case DRM_FORMAT_VYUY:
V = 0; Y1 = 1; U = 2; Y2 = 3;
break;
default:
g_assert_not_reached ();
return;
}
src_stride = dmabuf->planes[0].stride;
src_data = src_datas[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * src_stride);
for (y = 0; y < height; y ++)
{
for (x = 0; x < width; x += 2)
{
int r, g, b;
get_uv_values (&itu601_wide, src_data[2 * x + U], src_data[2 * x + V], &r, &g, &b);
set_rgb_values (&dst_data[3 * x], src_data[2 * x + Y1], r, g, b);
if (x + 1 < width)
set_rgb_values (&dst_data[3 * (x + 1)], src_data[2 * x + Y2], r, g, b);
}
dst_data += dst_stride;
src_data += src_stride;
}
}
static const GdkDrmFormatInfo supported_formats[] = {
{ DRM_FORMAT_BGRA8888, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED, GDK_MEMORY_A8R8G8B8, download_memcpy },
{ DRM_FORMAT_ABGR8888, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, GDK_MEMORY_R8G8B8A8, download_memcpy },
{ DRM_FORMAT_ARGB8888, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED, GDK_MEMORY_B8G8R8A8, download_memcpy },
{ DRM_FORMAT_RGBA8888, GDK_MEMORY_A8B8G8R8_PREMULTIPLIED, GDK_MEMORY_A8B8G8R8, download_memcpy },
{ DRM_FORMAT_BGRX8888, GDK_MEMORY_X8R8G8B8, GDK_MEMORY_X8R8G8B8, download_memcpy },
{ DRM_FORMAT_XBGR8888, GDK_MEMORY_R8G8B8X8, GDK_MEMORY_R8G8B8X8, download_memcpy },
{ DRM_FORMAT_XRGB8888, GDK_MEMORY_B8G8R8X8, GDK_MEMORY_B8G8R8X8, download_memcpy },
{ DRM_FORMAT_RGBX8888, GDK_MEMORY_X8B8G8R8, GDK_MEMORY_X8B8G8R8, download_memcpy },
{ DRM_FORMAT_ABGR16161616F, GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, GDK_MEMORY_R16G16B16A16_FLOAT, download_memcpy },
{ DRM_FORMAT_RGB888, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_memcpy },
{ DRM_FORMAT_BGR888, GDK_MEMORY_B8G8R8, GDK_MEMORY_B8G8R8, download_memcpy },
/* YUV formats */
{ DRM_FORMAT_NV12, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV21, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV16, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV61, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV24, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV42, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_YUYV, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_YVYU, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_VYUY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_UYVY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_YUV410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
};
static const GdkDrmFormatInfo *
get_drm_format_info (guint32 fourcc)
{
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
if (supported_formats[i].fourcc == fourcc)
return &supported_formats[i];
}
return NULL;
}
static gboolean
gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
GDK_DEBUG (DMABUF, "%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
downloader->name,
(char *) &supported_formats[i].fourcc, (guint64) DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_formats_builder_add_format (builder,
supported_formats[i].fourcc,
DRM_FORMAT_MOD_LINEAR);
}
return TRUE;
}
static gboolean
gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error)
{
const GdkDrmFormatInfo *info;
info = get_drm_format_info (dmabuf->fourcc);
if (!info)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format %.4s",
(char *) &dmabuf->fourcc);
return FALSE;
}
if (dmabuf->modifier != DRM_FORMAT_MOD_LINEAR)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf modifier %#lx (only linear buffers are supported)",
dmabuf->modifier);
return FALSE;
}
*out_format = premultiplied ? info->premultiplied_memory_format
: info->unpremultiplied_memory_format;
return TRUE;
}
static void
gdk_dmabuf_direct_downloader_do_download (GdkTexture *texture,
guchar *data,
gsize stride)
{
const GdkDrmFormatInfo *info;
const GdkDmabuf *dmabuf;
const guchar *src_data[GDK_DMABUF_MAX_PLANES];
gsize sizes[GDK_DMABUF_MAX_PLANES];
gsize needs_unmap[GDK_DMABUF_MAX_PLANES] = { FALSE, };
gsize i, j;
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
info = get_drm_format_info (dmabuf->fourcc);
GDK_DEBUG (DMABUF,
"Using mmap() and memcpy() for downloading a dmabuf (format %.4s:%#lx)",
(char *)&dmabuf->fourcc, dmabuf->modifier);
for (i = 0; i < dmabuf->n_planes; i++)
{
for (j = 0; j < i; j++)
{
if (dmabuf->planes[i].fd == dmabuf->planes[j].fd)
break;
}
if (j < i)
{
src_data[i] = src_data[j];
sizes[i] = sizes[j];
continue;
}
sizes[i] = lseek (dmabuf->planes[i].fd, 0, SEEK_END);
if (sizes[i] == (off_t) -1)
{
g_warning ("Failed to seek dmabuf: %s", g_strerror (errno));
goto out;
}
/* be a good citizen and seek back to the start, as the dos recommend */
lseek (dmabuf->planes[i].fd, 0, SEEK_SET);
if (ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
src_data[i] = mmap (NULL, sizes[i], PROT_READ, MAP_SHARED, dmabuf->planes[i].fd, dmabuf->planes[i].offset);
if (src_data[i] == NULL)
{
g_warning ("Failed to mmap dmabuf: %s", g_strerror (errno));
goto out;
}
needs_unmap[i] = TRUE;
}
info->download (data,
stride,
gdk_texture_get_format (texture),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
dmabuf,
src_data,
sizes);
out:
for (i = 0; i < dmabuf->n_planes; i++)
{
if (!needs_unmap[i])
continue;
munmap ((void *)src_data[i], sizes[i]);
if (ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
}
}
static void
gdk_dmabuf_direct_downloader_download (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
if (format == src_format)
gdk_dmabuf_direct_downloader_do_download (texture, data, stride);
else
{
unsigned int width, height;
guchar *src_data;
gsize src_stride;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
src_stride = width * gdk_memory_format_bytes_per_pixel (src_format);
src_data = g_new (guchar, src_stride * height);
gdk_dmabuf_direct_downloader_do_download (texture, src_data, src_stride);
gdk_memory_convert (data, stride, format,
src_data, src_stride, src_format,
width, height);
g_free (src_data);
}
}
const GdkDmabufDownloader *
gdk_dmabuf_get_direct_downloader (void)
{
static const GdkDmabufDownloader downloader = {
"mmap",
gdk_dmabuf_direct_downloader_add_formats,
gdk_dmabuf_direct_downloader_supports,
gdk_dmabuf_direct_downloader_download,
};
return &downloader;
}
/*
* Tries to sanitize the dmabuf to conform to the values expected
* by Vulkan/EGL which should also be the values expected by
* Wayland compositors
*
* We put these sanitized values into the GdkDmabufTexture, by
* sanitizing the input from GdkDmabufTextureBuilder, which are
* controlled by the callers.
*
* Things we do here:
*
* 1. Disallow any dmabuf format that we do not know.
*
* 1. Reject the INVALID modifier, accept the LINEAR one.
*
* 2. Ignore all other modifiers.
*
* 3. Try and fix various inconsistencies between V4L and Mesa, like NV12.
*
* *** WARNING ***
*
* This function is not absolutely perfect, you do not have a
* perfect dmabuf afterwards.
*
* In particular, it doesn't check sizes.
*
* *** WARNING ***
*/
gboolean
gdk_dmabuf_sanitize (GdkDmabuf *dest,
gsize width,
gsize height,
const GdkDmabuf *src,
GError **error)
{
const GdkDrmFormatInfo *info;
if (src->n_planes > GDK_DMABUF_MAX_PLANES)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"GTK only support dmabufs with %u planes, not %u",
GDK_DMABUF_MAX_PLANES, src->n_planes);
return FALSE;
}
if (src->modifier == DRM_FORMAT_MOD_INVALID)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"GTK does not support the INVALID modifier.");
return FALSE;
}
info = get_drm_format_info (src->fourcc);
if (info == NULL)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format %.4s",
(char *) &src->fourcc);
return FALSE;
}
*dest = *src;
if (src->modifier)
return TRUE;
switch (dest->fourcc)
{
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
if (dest->n_planes == 1)
{
dest->n_planes = 2;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = dest->planes[0].stride;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
}
break;
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV42:
if (dest->n_planes == 1)
{
dest->n_planes = 2;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = dest->planes[0].stride * 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
}
break;
case DRM_FORMAT_YUV410:
case DRM_FORMAT_YVU410:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 3) / 4);
}
break;
case DRM_FORMAT_YUV411:
case DRM_FORMAT_YVU411:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 1) / 2);
}
break;
case DRM_FORMAT_YUV422:
case DRM_FORMAT_YVU422:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
case DRM_FORMAT_YUV444:
case DRM_FORMAT_YVU444:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = dest->planes[0].stride;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
default:
break;
}
return TRUE;
}
/*
* gdk_dmabuf_is_disjoint:
* @dmabuf: a sanitized GdkDmabuf
*
* A dmabuf is considered disjoint if it uses more than
* 1 file descriptor.
*
* Returns: %TRUE if the dmabuf is disjoint
**/
gboolean
gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf)
{
unsigned i;
for (i = 1; i < dmabuf->n_planes; i++)
{
if (dmabuf->planes[0].fd != dmabuf->planes[i].fd)
return TRUE;
}
return FALSE;
}
#endif /* HAVE_DMABUF */
-413
View File
@@ -1,413 +0,0 @@
/* gdkdmabufegl.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
#include "gdkdmabufprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdebugprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkglcontextprivate.h"
#include "gdktexturedownloader.h"
#include <graphene.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm_fourcc.h>
#include <epoxy/egl.h>
/* A dmabuf downloader implementation that downloads buffers via
* gsk_renderer_render_texture + GL texture download.
*/
static gboolean
gdk_dmabuf_egl_downloader_add_formats (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder)
{
GdkGLContext *context = gdk_display_get_gl_context (display);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
GdkDmabufFormatsBuilder *external;
gboolean retval = FALSE;
g_assert (display->egl_external_formats == NULL);
external = gdk_dmabuf_formats_builder_new ();
gdk_gl_context_make_current (context);
if (egl_display != EGL_NO_DISPLAY &&
display->have_egl_dma_buf_import &&
gdk_gl_context_has_image_storage (context))
{
int num_fourccs;
int *fourccs;
guint64 *modifiers;
unsigned int *external_only;
int n_mods;
eglQueryDmaBufFormatsEXT (egl_display, 0, NULL, &num_fourccs);
fourccs = g_new (int, num_fourccs);
eglQueryDmaBufFormatsEXT (egl_display, num_fourccs, fourccs, &num_fourccs);
n_mods = 80;
modifiers = g_new (guint64, n_mods);
external_only = g_new (unsigned int, n_mods);
for (int i = 0; i < num_fourccs; i++)
{
int num_modifiers;
eglQueryDmaBufModifiersEXT (egl_display,
fourccs[i],
0,
NULL,
NULL,
&num_modifiers);
if (num_modifiers > n_mods)
{
n_mods = num_modifiers;
modifiers = g_renew (guint64, modifiers, n_mods);
external_only = g_renew (unsigned int, external_only, n_mods);
}
eglQueryDmaBufModifiersEXT (egl_display,
fourccs[i],
num_modifiers,
modifiers,
external_only,
&num_modifiers);
for (int j = 0; j < num_modifiers; j++)
{
/* All linear formats we support are already added my the mmap downloader.
* We don't add external formats, unless we can use them (via GLES)
*/
if (modifiers[j] != DRM_FORMAT_MOD_LINEAR &&
(!external_only[j] || gdk_gl_context_get_use_es (context)))
{
GDK_DEBUG (DMABUF, "%s%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
external_only[j] ? "external " : "",
downloader->name,
(char *) &fourccs[i],
modifiers[j]);
gdk_dmabuf_formats_builder_add_format (builder, fourccs[i], modifiers[j]);
}
if (external_only[j])
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], modifiers[j]);
}
}
g_free (modifiers);
g_free (external_only);
g_free (fourccs);
retval = TRUE;
}
display->egl_external_formats = gdk_dmabuf_formats_builder_free_to_formats (external);
return retval;
}
static GdkMemoryFormat
get_memory_format (guint32 fourcc,
gboolean premultiplied)
{
switch (fourcc)
{
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB8888_A8:
case DRM_FORMAT_XBGR8888_A8:
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_RGBX8888_A8:
return premultiplied ? GDK_MEMORY_R8G8B8A8_PREMULTIPLIED : GDK_MEMORY_R8G8B8A8;
case DRM_FORMAT_BGRA8888:
return premultiplied ? GDK_MEMORY_B8G8R8A8_PREMULTIPLIED : GDK_MEMORY_B8G8R8A8;
case DRM_FORMAT_RGB888:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_BGRX8888:
return GDK_MEMORY_R8G8B8;
case DRM_FORMAT_BGR888:
return GDK_MEMORY_B8G8R8;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_RGBX1010102:
case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_XRGB16161616:
case DRM_FORMAT_XBGR16161616:
return GDK_MEMORY_R16G16B16;
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_ARGB16161616:
case DRM_FORMAT_ABGR16161616:
return premultiplied ? GDK_MEMORY_R16G16B16A16_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16;
case DRM_FORMAT_ARGB16161616F:
case DRM_FORMAT_ABGR16161616F:
return premultiplied ? GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16_FLOAT;
case DRM_FORMAT_XRGB16161616F:
case DRM_FORMAT_XBGR16161616F:
return GDK_MEMORY_R16G16B16_FLOAT;
case DRM_FORMAT_YUYV:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_XYUV8888:
#ifdef DRM_FORMAT_XVUY8888
case DRM_FORMAT_XVUY8888:
#endif
case DRM_FORMAT_VUY888:
return GDK_MEMORY_R8G8B8;
/* Add more formats here */
default:
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
}
}
static gboolean
gdk_dmabuf_egl_downloader_supports (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error)
{
EGLDisplay egl_display;
GdkGLContext *context;
int num_modifiers;
guint64 *modifiers;
unsigned int *external_only;
egl_display = gdk_display_get_egl_display (display);
if (egl_display == EGL_NO_DISPLAY)
{
g_set_error_literal (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"EGL not available");
return FALSE;
}
context = gdk_display_get_gl_context (display);
gdk_gl_context_make_current (context);
eglQueryDmaBufModifiersEXT (egl_display,
dmabuf->fourcc,
0,
NULL,
NULL,
&num_modifiers);
modifiers = g_newa (uint64_t, num_modifiers);
external_only = g_newa (unsigned int, num_modifiers);
eglQueryDmaBufModifiersEXT (egl_display,
dmabuf->fourcc,
num_modifiers,
modifiers,
external_only,
&num_modifiers);
for (int i = 0; i < num_modifiers; i++)
{
if (modifiers[i] == dmabuf->modifier)
{
*out_format = get_memory_format (dmabuf->fourcc, premultiplied);
return TRUE;
}
}
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format: %.4s:%#" G_GINT64_MODIFIER "x",
(char *) &dmabuf->fourcc, dmabuf->modifier);
return FALSE;
}
/* Hack. We don't include gsk/gsk.h here to avoid a build order problem
* with the generated header gskenumtypes.h, so we need to hack around
* a bit to access the gsk api we need.
*/
typedef gpointer GskRenderer;
extern GskRenderer * gsk_gl_renderer_new (void);
extern gboolean gsk_renderer_realize (GskRenderer *renderer,
GdkSurface *surface,
GError **error);
extern GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
GdkTexture *texture);
typedef void (* InvokeFunc) (gpointer data);
typedef struct _InvokeData
{
volatile int spinlock;
InvokeFunc func;
gpointer data;
} InvokeData;
static gboolean
gdk_dmabuf_egl_downloader_invoke_callback (gpointer data)
{
InvokeData *invoke = data;
GdkGLContext *previous;
previous = gdk_gl_context_get_current ();
invoke->func (invoke->data);
if (previous)
gdk_gl_context_make_current (previous);
else
gdk_gl_context_clear_current ();
g_atomic_int_set (&invoke->spinlock, 1);
return FALSE;
}
/* Run func in the main thread, taking care not to disturb
* the current GL context of the caller.
*/
static void
gdk_dmabuf_egl_downloader_run (InvokeFunc func,
gpointer data)
{
InvokeData invoke = { 0, func, data };
g_main_context_invoke (NULL, gdk_dmabuf_egl_downloader_invoke_callback, &invoke);
while (g_atomic_int_get (&invoke.spinlock) == 0) ;
}
typedef struct _Download Download;
struct _Download
{
GdkDmabufTexture *texture;
GdkMemoryFormat format;
guchar *data;
gsize stride;
};
static GskRenderer *
get_gsk_renderer (GdkDisplay *display)
{
if (!display->egl_gsk_renderer)
{
GskRenderer *renderer;
GError *error = NULL;
renderer = gsk_gl_renderer_new ();
if (!gsk_renderer_realize (renderer, NULL, &error))
{
g_warning ("Failed to realize GL renderer: %s", error->message);
g_error_free (error);
g_object_unref (renderer);
return NULL;
}
display->egl_gsk_renderer = renderer;
}
return display->egl_gsk_renderer;
}
static void
gdk_dmabuf_egl_downloader_do_download (gpointer data)
{
Download *download = data;
GdkDisplay *display;
GskRenderer *renderer;
GdkTexture *native;
GdkTextureDownloader *downloader;
display = gdk_dmabuf_texture_get_display (download->texture);
renderer = get_gsk_renderer (display);
native = gsk_renderer_convert_texture (renderer, GDK_TEXTURE (download->texture));
downloader = gdk_texture_downloader_new (native);
gdk_texture_downloader_set_format (downloader, download->format);
gdk_texture_downloader_download_into (downloader, download->data, download->stride);
gdk_texture_downloader_free (downloader);
g_object_unref (native);
}
static void
gdk_dmabuf_egl_downloader_download (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
Download download;
GDK_DEBUG (DMABUF, "Using %s for downloading a dmabuf", downloader->name);
download.texture = GDK_DMABUF_TEXTURE (texture);
download.format = format;
download.data = data;
download.stride = stride;
gdk_dmabuf_egl_downloader_run (gdk_dmabuf_egl_downloader_do_download, &download);
}
const GdkDmabufDownloader *
gdk_dmabuf_get_egl_downloader (void)
{
static const GdkDmabufDownloader downloader = {
"egl",
gdk_dmabuf_egl_downloader_add_formats,
gdk_dmabuf_egl_downloader_supports,
gdk_dmabuf_egl_downloader_download,
};
return &downloader;
}
#endif /* HAVE_DMABUF && HAVE_EGL */
-215
View File
@@ -1,215 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <glib-object.h>
#include "gdkdmabufformatsprivate.h"
/**
* GdkDmabufFormats:
*
* The `GdkDmabufFormats struct provides information about
* supported DMA buffer formats.
*
* You can query whether a given format is supported with
* [method@Gdk.DmabufFormats.contains] and you can iterate
* over the list of all supported formats with
* [method@Gdk.DmabufFormats.get_n_formats] and
* [method@Gdk.DmabufFormats.get_format].
*
* The list of supported formats is sorted by preference,
* with the best formats coming first.
*
* See [class@Gdk.DmabufTextureBuilder] for more information
* about DMA buffers.
*
* Note that DMA buffers only exist on Linux.
*
* Since: 4.14
*/
struct _GdkDmabufFormats
{
int ref_count;
gsize n_formats;
GdkDmabufFormat *formats;
};
G_DEFINE_BOXED_TYPE (GdkDmabufFormats, gdk_dmabuf_formats, gdk_dmabuf_formats_ref, gdk_dmabuf_formats_unref)
/**
* gdk_dmabuf_formats_ref:
* @formats: a `GdkDmabufFormats`
*
* Increases the reference count of @formats.
*
* Returns: the passed-in object
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_ref (GdkDmabufFormats *formats)
{
formats->ref_count++;
return formats;
}
/**
* gdk_dmabuf_formats_unref:
* @formats: a `GdkDmabufFormats`
*
* Decreases the reference count of @formats.
*
* When the reference count reaches zero,
* the object is freed.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_unref (GdkDmabufFormats *formats)
{
formats->ref_count--;
if (formats->ref_count > 0)
return;
g_free (formats->formats);
g_free (formats);
}
/**
* gdk_dmabuf_formats_get_n_formats:
* @formats: a `GdkDmabufFormats`
*
* Returns the number of formats that the @formats object
* contains.
*
* Note that DMA buffers are a Linux concept, so on other
* platforms, [method@Gdk.DmabufFormats.get_n_formats] will
* always return zero.
*
* Returns: the number of formats
*
* Since: 4.14
*/
gsize
gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats)
{
return formats->n_formats;
}
/**
* gdk_dmabuf_formats_get_format:
* @formats: a `GdkDmabufFormats`
* @idx: the index of the format to return
* @fourcc: (out): return location for the format code
* @modifier: (out): return location for the format modifier
*
* Gets the fourcc code and modifier for a format
* that is contained in @formats.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier)
{
GdkDmabufFormat *format;
g_return_if_fail (idx < formats->n_formats);
g_return_if_fail (fourcc != NULL);
g_return_if_fail (modifier != NULL);
format = &formats->formats[idx];
*fourcc = format->fourcc;
*modifier = format->modifier;
}
/**
* gdk_dmabuf_format_contains:
* @formats: a `GdkDmabufFormats`
* @fourcc: a format code
* @modfier: a format modifier
*
* Returns whether a given format is contained in @formats.
*
* Returns: `TRUE` if the format specified by the arguments
* is part of @formats
*
* Since: 4.14
*/
gboolean
gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier)
{
for (gsize i = 0; i < formats->n_formats; i++)
{
GdkDmabufFormat *format = &formats->formats[i];
if (format->fourcc == fourcc && format->modifier == modifier)
return TRUE;
}
return FALSE;
}
/*< private >
* gdk_dmabuf_formats_new:
* @formats: the formats
* @n_formats: the length of @formats
*
* Creates a new `GdkDmabufFormats struct for
* the given formats.
*
* The @formats array is expected to be sorted
* by preference.
*
* Returns: (transfer full): the new `GdkDmabufFormats`
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats)
{
GdkDmabufFormats *self;
self = g_new0 (GdkDmabufFormats, 1);
self->ref_count = 1;
self->n_formats = n_formats;
self->formats = g_new (GdkDmabufFormat, n_formats);
memcpy (self->formats, formats, n_formats * sizeof (GdkDmabufFormat));
return self;
}
const GdkDmabufFormat *
gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self)
{
return self->formats;
}
-54
View File
@@ -1,54 +0,0 @@
/* gdkdmabufformats.h
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_FORMATS (gdk_dmabuf_formats_get_type ())
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_formats_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats * gdk_dmabuf_formats_ref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_unref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
gsize gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier) G_GNUC_PURE;
G_END_DECLS
-143
View File
@@ -1,143 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#ifdef HAVE_DMABUF
#include <drm_fourcc.h>
#endif
#define GDK_ARRAY_NAME gdk_dmabuf_formats_builder
#define GDK_ARRAY_TYPE_NAME GdkDmabufFormatsBuilder
#define GDK_ARRAY_ELEMENT_TYPE GdkDmabufFormat
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 1024
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
/* NB: We keep duplicates in the list for ease of use. Only when creating the final
* GdkDmabufFormats do we actually remove duplicates.
*/
GdkDmabufFormatsBuilder *
gdk_dmabuf_formats_builder_new (void)
{
GdkDmabufFormatsBuilder *result = g_new (GdkDmabufFormatsBuilder, 1);
gdk_dmabuf_formats_builder_init (result);
return result;
}
static int
gdk_dmabuf_format_compare (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
if (a->fourcc == b->fourcc)
return (a->modifier - b->modifier) >> 8 * (sizeof (gint64) - sizeof (gint));
else
return a->fourcc - b->fourcc;
}
static gboolean
gdk_dmabuf_format_equal (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
return a->fourcc == b->fourcc &&
a->modifier == b->modifier;
}
static void
gdk_dmabuf_formats_builder_sort (GdkDmabufFormatsBuilder *self)
{
qsort (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self),
sizeof (GdkDmabufFormat),
gdk_dmabuf_format_compare);
}
/* list must be sorted */
static void
gdk_dmabuf_formats_builder_remove_duplicates (GdkDmabufFormatsBuilder *self)
{
gsize i, j;
for (i = 1, j = 0; i < gdk_dmabuf_formats_builder_get_size (self); i++)
{
if (gdk_dmabuf_format_equal (gdk_dmabuf_formats_builder_get (self, i),
gdk_dmabuf_formats_builder_get (self, j)))
continue;
j++;
if (i != j)
*gdk_dmabuf_formats_builder_index (self, j) = *gdk_dmabuf_formats_builder_index (self, i);
}
}
GdkDmabufFormats *
gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self)
{
GdkDmabufFormats *formats;
gdk_dmabuf_formats_builder_sort (self);
gdk_dmabuf_formats_builder_remove_duplicates (self);
formats = gdk_dmabuf_formats_new (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self));
gdk_dmabuf_formats_builder_clear (self);
g_free (self);
return formats;
}
void
gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier)
{
#ifdef HAVE_DMABUF
g_return_if_fail (modifier != DRM_FORMAT_MOD_INVALID);
#else
g_return_if_reached ();
#endif
gdk_dmabuf_formats_builder_append (self, &(GdkDmabufFormat) { fourcc, modifier });
}
void
gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats)
{
gdk_dmabuf_formats_builder_splice (self,
gdk_dmabuf_formats_builder_get_size (self),
0,
FALSE,
gdk_dmabuf_formats_peek_formats (formats),
gdk_dmabuf_formats_get_n_formats (formats));
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct GdkDmabufFormatsBuilder GdkDmabufFormatsBuilder;
GdkDmabufFormatsBuilder * gdk_dmabuf_formats_builder_new (void);
GdkDmabufFormats * gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self);
void gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier);
void gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats);
-15
View File
@@ -1,15 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct _GdkDmabufFormat GdkDmabufFormat;
struct _GdkDmabufFormat
{
guint32 fourcc;
guint64 modifier;
};
GdkDmabufFormats * gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats);
const GdkDmabufFormat * gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self);
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include "gdkdmabufformatsbuilderprivate.h"
#define GDK_DMABUF_MAX_PLANES 4
typedef struct _GdkDmabuf GdkDmabuf;
typedef struct _GdkDmabufDownloader GdkDmabufDownloader;
struct _GdkDmabuf
{
guint32 fourcc;
guint64 modifier;
unsigned int n_planes;
struct {
int fd;
unsigned int stride;
unsigned int offset;
} planes[GDK_DMABUF_MAX_PLANES];
};
struct _GdkDmabufDownloader
{
const char *name;
gboolean (* add_formats) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder);
gboolean (* supports) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error);
void (* download) (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride);
};
#ifdef HAVE_DMABUF
const GdkDmabufDownloader * gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
const GdkDmabufDownloader * gdk_dmabuf_get_egl_downloader (void) G_GNUC_CONST;
gboolean gdk_dmabuf_sanitize (GdkDmabuf *dest,
gsize width,
gsize height,
const GdkDmabuf *src,
GError **error);
gboolean gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf);
#endif
-219
View File
@@ -1,219 +0,0 @@
/* gdkdmabuftexture.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufprivate.h"
#include "gdktextureprivate.h"
#include <gdk/gdkglcontext.h>
#include <gdk/gdkgltexturebuilder.h>
#include <gdk/gdktexturedownloader.h>
#ifdef HAVE_DMABUF
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm_fourcc.h>
#include <epoxy/egl.h>
#endif
/**
* GdkDmabufTexture:
*
* A `GdkTexture` representing a dma-buf object.
*
* To create a `GdkDmabufTexture`, use the auxiliary
* [class@Gdk.DmabufTextureBuilder] object.
*
* Dma-buf textures can only be created on Linux.
*/
struct _GdkDmabufTexture
{
GdkTexture parent_instance;
GdkDisplay *display;
const GdkDmabufDownloader *downloader;
GdkDmabuf dmabuf;
GDestroyNotify destroy;
gpointer data;
};
struct _GdkDmabufTextureClass
{
GdkTextureClass parent_class;
};
G_DEFINE_QUARK (gdk-dmabuf-error-quark, gdk_dmabuf_error)
G_DEFINE_TYPE (GdkDmabufTexture, gdk_dmabuf_texture, GDK_TYPE_TEXTURE)
static void
gdk_dmabuf_texture_init (GdkDmabufTexture *self)
{
}
static void
gdk_dmabuf_texture_dispose (GObject *object)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (object);
if (self->destroy)
self->destroy (self->data);
G_OBJECT_CLASS (gdk_dmabuf_texture_parent_class)->dispose (object);
}
static void
gdk_dmabuf_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
self->downloader->download (self->downloader,
texture,
format,
data,
stride);
}
static void
gdk_dmabuf_texture_class_init (GdkDmabufTextureClass *klass)
{
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
texture_class->download = gdk_dmabuf_texture_download;
gobject_class->dispose = gdk_dmabuf_texture_dispose;
}
GdkDisplay *
gdk_dmabuf_texture_get_display (GdkDmabufTexture *self)
{
return self->display;
}
const GdkDmabuf *
gdk_dmabuf_texture_get_dmabuf (GdkDmabufTexture *self)
{
return &self->dmabuf;
}
GdkTexture *
gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data,
GError **error)
{
#ifdef HAVE_DMABUF
GdkDmabufTexture *self;
GdkTexture *update_texture;
GdkDisplay *display;
GdkDmabuf dmabuf;
GdkMemoryFormat format;
GError *local_error = NULL;
int width, height;
gsize i;
display = gdk_dmabuf_texture_builder_get_display (builder);
width = gdk_dmabuf_texture_builder_get_width (builder);
height = gdk_dmabuf_texture_builder_get_height (builder);
if (!gdk_dmabuf_sanitize (&dmabuf,
width,
height,
gdk_dmabuf_texture_builder_get_dmabuf (builder),
error))
return NULL;
gdk_display_init_dmabuf (display);
for (i = 0; display->dmabuf_downloaders[i] != NULL; i++)
{
if (local_error && g_error_matches (local_error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT))
g_clear_error (&local_error);
if (display->dmabuf_downloaders[i]->supports (display->dmabuf_downloaders[i],
display,
&dmabuf,
gdk_dmabuf_texture_builder_get_premultiplied (builder),
&format,
local_error ? NULL : &local_error))
break;
}
if (display->dmabuf_downloaders[i] == NULL)
{
g_propagate_error (error, local_error);
return NULL;
}
GDK_DEBUG (DMABUF,
"Dmabuf texture, format %.4s:%#lx, %s%u planes, memory format %u, downloader %s",
(char *) &dmabuf.fourcc, dmabuf.modifier,
gdk_dmabuf_texture_builder_get_premultiplied (builder) ? " premultiplied, " : "",
dmabuf.n_planes,
format,
display->dmabuf_downloaders[i]->name);
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
"width", width,
"height", height,
NULL);
GDK_TEXTURE (self)->format = format;
g_set_object (&self->display, display);
self->downloader = display->dmabuf_downloaders[i];
self->dmabuf = dmabuf;
self->destroy = destroy;
self->data = data;
update_texture = gdk_dmabuf_texture_builder_get_update_texture (builder);
if (update_texture)
{
cairo_region_t *update_region = gdk_dmabuf_texture_builder_get_update_region (builder);
if (update_region)
{
update_region = cairo_region_copy (update_region);
cairo_region_intersect_rectangle (update_region,
&(cairo_rectangle_int_t) {
0, 0,
update_texture->width, update_texture->height
});
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
}
}
return GDK_TEXTURE (self);
#else /* !HAVE_DMABUF */
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
"dmabuf support disabled at compile-time.");
return NULL;
#endif
}
-48
View File
@@ -1,48 +0,0 @@
/* gdkdmabuftexture.h
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
#include <gdk/gdktexture.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE (gdk_dmabuf_texture_get_type ())
#define GDK_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DMABUF_TEXTURE, GdkDmabufTexture))
#define GDK_IS_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DMABUF_TEXTURE))
#define GDK_DMABUF_ERROR (gdk_dmabuf_error_quark ())
typedef struct _GdkDmabufTexture GdkDmabufTexture;
typedef struct _GdkDmabufTextureClass GdkDmabufTextureClass;
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_texture_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GQuark gdk_dmabuf_error_quark (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDmabufTexture, g_object_unref)
G_END_DECLS
File diff suppressed because it is too large Load Diff
-122
View File
@@ -1,122 +0,0 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE_BUILDER (gdk_dmabuf_texture_builder_get_type ())
GDK_AVAILABLE_IN_4_14
GDK_DECLARE_INTERNAL_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, GDK, DMABUF_TEXTURE_BUILDER, GObject)
GDK_AVAILABLE_IN_4_14
GdkDmabufTextureBuilder *gdk_dmabuf_texture_builder_new (void);
GDK_AVAILABLE_IN_4_14
GdkDisplay * gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
GdkDisplay *display);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
unsigned int width);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
unsigned int height);
GDK_AVAILABLE_IN_4_14
guint32 gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
guint32 fourcc);
GDK_AVAILABLE_IN_4_14
guint64 gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_texture_builder_get_premultiplied (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_premultiplied (GdkDmabufTextureBuilder *self,
gboolean premultiplied);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
unsigned int n_planes);
GDK_AVAILABLE_IN_4_14
int gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
unsigned int plane,
int fd);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int stride);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int offset);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_14
cairo_region_t * gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
cairo_region_t *region);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
GDestroyNotify destroy,
gpointer data,
GError **error);
G_END_DECLS
-21
View File
@@ -1,21 +0,0 @@
#pragma once
#include "gdkdmabuftexture.h"
#include "gdkdmabuftexturebuilder.h"
#include "gdkdmabufprivate.h"
G_BEGIN_DECLS
const GdkDmabuf * gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *builder);
GdkTexture * gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data,
GError **error);
GdkDisplay * gdk_dmabuf_texture_get_display (GdkDmabufTexture *self);
const GdkDmabuf * gdk_dmabuf_texture_get_dmabuf (GdkDmabufTexture *self);
G_END_DECLS
+1 -1
View File
@@ -684,7 +684,7 @@ gdk_drop_read_async (GdkDrop *self,
* gdk_drop_read_finish:
* @self: a `GdkDrop`
* @result: a `GAsyncResult`
* @out_mime_type: (out) (type utf8) (transfer none): return location for the used mime type
* @out_mime_type: (out) (type utf8): return location for the used mime type
* @error: (nullable): location to store error information on failure
*
* Finishes an async drop read operation.
-27
View File
@@ -142,22 +142,6 @@ typedef enum
GDK_BUTTON4_MASK|GDK_BUTTON5_MASK)
/**
* GdkDmabufError:
* @GDK_DMABUF_ERROR_NOT_AVAILABLE: Dmabuf support is not available, because the OS
* is not Linux, or it was explicitly disabled at compile- or runtime
* @GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT: The requested format is not supported
* @GDK_DMABUF_ERROR_CREATION_FAILED: GTK failed to create the resource for other
* reasons
*
* Error enumeration for `GdkDmabufTexture`.
*/
typedef enum {
GDK_DMABUF_ERROR_NOT_AVAILABLE,
GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
GDK_DMABUF_ERROR_CREATION_FAILED,
} GdkDmabufError;
/**
* GdkGLError:
* @GDK_GL_ERROR_NOT_AVAILABLE: OpenGL support is not available
@@ -298,16 +282,10 @@ typedef enum
* The color values are premultiplied with the alpha value.
* @GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: 4 bytes; for red, green, blue, alpha
* The color values are premultiplied with the alpha value.
* @GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: 4 bytes; for alpha, blue, green, red,
* The color values are premultiplied with the alpha value. Since 4.14
* @GDK_MEMORY_B8G8R8A8: 4 bytes; for blue, green, red, alpha.
* @GDK_MEMORY_A8R8G8B8: 4 bytes; for alpha, red, green, blue.
* @GDK_MEMORY_R8G8B8A8: 4 bytes; for red, green, blue, alpha.
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
* @GDK_MEMORY_B8G8R8X8: 4 bytes; for blue, green, red, unused. Since 4.14
* @GDK_MEMORY_X8R8G8B8: 4 bytes; for unused, red, green, blue. Since 4.14
* @GDK_MEMORY_R8G8B8X8: 4 bytes; for red, green, blue, unused. Since 4.14
* @GDK_MEMORY_X8B8G8R8: 4 bytes; for unused, blue, green, red. Since 4.14
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since: 4.6
@@ -388,11 +366,6 @@ typedef enum {
GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A16_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A32_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A8B8G8R8_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_B8G8R8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_X8R8G8B8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_R8G8B8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_X8B8G8R8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
-301
View File
@@ -83,7 +83,6 @@
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdkglversionprivate.h"
#include "gdkdmabufformatsprivate.h"
#include "gdkprivate.h"
@@ -96,10 +95,6 @@
#include <epoxy/egl.h>
#endif
#ifdef HAVE_DMABUF
#include <drm_fourcc.h>
#endif
#include <math.h>
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
@@ -114,8 +109,6 @@ typedef struct {
guint has_sync : 1;
guint has_unpack_subimage : 1;
guint has_debug_output : 1;
guint has_bgra : 1;
guint has_image_storage : 1;
guint extensions_checked : 1;
guint debug_enabled : 1;
guint forward_compatible : 1;
@@ -1538,13 +1531,11 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
priv->has_unpack_subimage = gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888");
}
else
{
priv->has_unpack_subimage = TRUE;
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = TRUE;
/* We asked for a core profile, but we didn't get one, so we're in legacy mode */
if (!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
@@ -1564,8 +1555,6 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync");
priv->has_image_storage = epoxy_has_gl_extension ("GL_EXT_EGL_image_storage");
#ifdef G_ENABLE_DEBUG
{
int max_texture_size;
@@ -1577,8 +1566,6 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
"* Extensions checked:\n"
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s\n"
" - GL_EXT_texture_format_BGRA8888: %s\n"
" - GL_EXT_EGL_image_storage: %s\n"
" - half float: %s\n"
" - sync: %s",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
@@ -1588,8 +1575,6 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
max_texture_size,
priv->has_khr_debug ? "yes" : "no",
priv->has_unpack_subimage ? "yes" : "no",
priv->has_bgra ? "yes" : "no",
priv->has_image_storage ? "yes" : "no",
priv->has_half_float ? "yes" : "no",
priv->has_sync ? "yes" : "no");
}
@@ -1730,56 +1715,6 @@ gdk_gl_context_get_version (GdkGLContext *context,
*minor = gdk_gl_version_get_minor (&priv->gl_version);
}
const char *
gdk_gl_context_get_glsl_version_string (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
if (priv->api == GDK_GL_API_GL)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 6)))
return "#version 460";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 5)))
return "#version 450";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 4)))
return "#version 440";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 3)))
return "#version 430";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 2)))
return "#version 420";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 1)))
return "#version 410";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 0)))
return "#version 400";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 3)))
return "#version 330";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 150";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 140";
else
return "#version 130";
}
else if (priv->api == GDK_GL_API_GLES)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 320 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 310 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else
return "#version 100";
}
else
{
/* must be realized to be called */
g_assert_not_reached ();
}
}
/**
* gdk_gl_context_clear_current:
*
@@ -1877,44 +1812,6 @@ gdk_gl_context_has_sync (GdkGLContext *self)
return priv->has_sync;
}
/* Return if GL_BGRA works with glTexImage2D */
gboolean
gdk_gl_context_has_bgra (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_bgra;
}
/* Return if glGenVertexArrays, glBindVertexArray and glDeleteVertexArrays
* can be used
*/
gboolean
gdk_gl_context_has_vertex_arrays (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
switch (priv->api)
{
case GDK_GL_API_GL:
return TRUE;
case GDK_GL_API_GLES:
return gdk_gl_version_get_major (&priv->gl_version) >= 3;
default:
g_return_val_if_reached (FALSE);
}
}
gboolean
gdk_gl_context_has_image_storage (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_image_storage;
}
/* This is currently private! */
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
gboolean
@@ -1995,201 +1892,3 @@ gdk_gl_backend_use (GdkGLBackend backend_type)
g_assert (the_gl_backend_type == backend_type);
}
guint
gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int target)
{
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
GdkDisplay *display = gdk_gl_context_get_display (self);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
EGLint attribs[64];
int i;
EGLImage image;
guint texture_id;
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), 0);
g_return_val_if_fail (width > 0, 0);
g_return_val_if_fail (height > 0, 0);
g_return_val_if_fail (1 <= dmabuf->n_planes && dmabuf->n_planes <= 4, 0);
g_return_val_if_fail (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES, 0);
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_import)
return 0;
GDK_DEBUG (DMABUF,
"Importing dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %u) into GL",
(char *) &dmabuf->fourcc, dmabuf->modifier, dmabuf->n_planes);
i = 0;
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
attribs[i++] = EGL_TRUE;
attribs[i++] = EGL_WIDTH;
attribs[i++] = width;
attribs[i++] = EGL_HEIGHT;
attribs[i++] = height;
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = dmabuf->fourcc;
#define ADD_PLANE(plane) \
{ \
if (dmabuf->modifier != DRM_FORMAT_MOD_INVALID) \
{ \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_MODIFIER_LO_EXT; \
attribs[i++] = dmabuf->modifier & 0xFFFFFFFF; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ## _MODIFIER_HI_EXT; \
attribs[i++] = dmabuf->modifier >> 32; \
} \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_FD_EXT; \
attribs[i++] = dmabuf->planes[plane].fd; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_PITCH_EXT; \
attribs[i++] = dmabuf->planes[plane].stride; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_OFFSET_EXT; \
attribs[i++] = dmabuf->planes[plane].offset; \
}
ADD_PLANE (0);
if (dmabuf->n_planes > 1) ADD_PLANE (1);
if (dmabuf->n_planes > 2) ADD_PLANE (2);
if (dmabuf->n_planes > 3) ADD_PLANE (3);
attribs[i++] = EGL_NONE;
image = eglCreateImageKHR (egl_display,
EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT,
(EGLClientBuffer)NULL,
attribs);
if (image == EGL_NO_IMAGE)
{
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
return 0;
}
glGenTextures (1, &texture_id);
glBindTexture (target, texture_id);
glEGLImageTargetTexture2DOES (target, image);
glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
eglDestroyImageKHR (egl_display, image);
return texture_id;
#else
return 0;
#endif
}
gboolean
gdk_gl_context_export_dmabuf (GdkGLContext *self,
unsigned int texture_id,
GdkDmabuf *dmabuf)
{
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
GdkDisplay *display = gdk_gl_context_get_display (self);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
EGLContext egl_context = priv->egl_context;
EGLint attribs[10];
EGLImage image;
gboolean result = FALSE;
int i;
int fourcc;
int n_planes;
guint64 modifier;
int fds[GDK_DMABUF_MAX_PLANES];
int strides[GDK_DMABUF_MAX_PLANES];
int offsets[GDK_DMABUF_MAX_PLANES];
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
g_return_val_if_fail (texture_id > 0, FALSE);
g_return_val_if_fail (dmabuf != NULL, FALSE);
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_export)
return 0;
GDK_DEBUG (DMABUF, "Exporting GL texture to dmabuf");
i = 0;
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
attribs[i++] = EGL_TRUE;
attribs[i++] = EGL_NONE;
image = eglCreateImageKHR (egl_display,
egl_context,
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)GUINT_TO_POINTER (texture_id),
attribs);
if (image == EGL_NO_IMAGE)
{
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
return FALSE;
}
if (!eglExportDMABUFImageQueryMESA (egl_display,
image,
&fourcc,
&n_planes,
&modifier))
{
GDK_DEBUG (DMABUF, "eglExportDMABUFImageQueryMESA failed: %#x", eglGetError ());
goto out;
}
if (n_planes < 1 || n_planes > GDK_DMABUF_MAX_PLANES)
{
GDK_DEBUG (DMABUF, "dmabufs with %d planes are not supported", n_planes);
goto out;
}
if (!eglExportDMABUFImageMESA (egl_display,
image,
fds,
strides,
offsets))
{
g_warning ("eglExportDMABUFImage failed: %#x", eglGetError ());
goto out;
}
for (i = 0; i < n_planes; i++)
{
if (fds[i] == -1)
{
g_warning ("dmabuf plane %d has no file descriptor", i);
goto out;
}
}
dmabuf->fourcc = (guint32)fourcc;
dmabuf->modifier = modifier;
dmabuf->n_planes = n_planes;
for (i = 0; i < n_planes; i++)
{
dmabuf->planes[i].fd = fds[i];
dmabuf->planes[i].stride = (int) strides[i];
dmabuf->planes[i].offset = (int) offsets[i];
}
GDK_DEBUG (DMABUF,
"Exported GL texture to dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %d)",
(char *)&fourcc, modifier, n_planes);
result = TRUE;
out:
eglDestroyImageKHR (egl_display, image);
return result;
#else
return FALSE;
#endif
}
+1 -19
View File
@@ -23,7 +23,6 @@
#include "gdkglcontext.h"
#include "gdkdrawcontextprivate.h"
#include "gdkglversionprivate.h"
#include "gdkdmabufprivate.h"
G_BEGIN_DECLS
@@ -148,8 +147,6 @@ void gdk_gl_context_label_object_printf (GdkGLContext
const char *format,
...) G_GNUC_PRINTF (4, 5);
const char * gdk_gl_context_get_glsl_version_string (GdkGLContext *self);
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
@@ -158,22 +155,7 @@ gboolean gdk_gl_context_has_vertex_half_float (GdkGLContext
gboolean gdk_gl_context_has_sync (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_bgra (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_vertex_arrays (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_image_storage (GdkGLContext *self) G_GNUC_PURE;
double gdk_gl_context_get_scale (GdkGLContext *self);
guint gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int target);
gboolean gdk_gl_context_export_dmabuf (GdkGLContext *self,
unsigned int texture_id,
GdkDmabuf *dmabuf);
G_END_DECLS
+9 -4
View File
@@ -141,7 +141,9 @@ struct _Download
};
static gboolean
gdk_gl_texture_find_format (GdkGLContext *context,
gdk_gl_texture_find_format (gboolean use_es,
guint gl_major,
guint gl_minor,
GdkMemoryAlpha alpha,
GLint gl_format,
GLint gl_type,
@@ -157,7 +159,7 @@ gdk_gl_texture_find_format (GdkGLContext *context,
if (gdk_memory_format_alpha (format) != alpha)
continue;
if (!gdk_memory_format_gl_format (format, context, &q_internal_format, &q_format, &q_type, q_swizzle))
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, q_swizzle))
continue;
if (q_format != gl_format || q_type != gl_type)
@@ -181,13 +183,16 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
Download *download = download_;
GLenum gl_internal_format, gl_format, gl_type;
GLint gl_swizzle[4];
int major, minor;
format = gdk_texture_get_format (texture),
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
gdk_gl_context_get_version (context, &major, &minor);
if (!gdk_gl_context_get_use_es (context) &&
gdk_memory_format_gl_format (format,
context,
FALSE,
major, minor,
&gl_internal_format,
&gl_format, &gl_type, gl_swizzle))
{
@@ -238,7 +243,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
{
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
if (!gdk_gl_texture_find_format (context, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
if (!gdk_gl_texture_find_format (TRUE, major, minor, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
{
gl_read_format = GL_RGBA;
gl_read_type = GL_UNSIGNED_BYTE;
+6 -72
View File
@@ -20,7 +20,6 @@
#include "config.h"
#include "gdkmemoryformatprivate.h"
#include "gdkglcontextprivate.h"
#include "gsk/gl/fp16private.h"
@@ -94,17 +93,10 @@ name ## _from_float (guchar *dest_data, \
TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
TYPED_FUNCS (a8b8g8r8_premultiplied, guchar, 3, 2, 1, 0, 4, 255)
TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
TYPED_FUNCS (r8g8b8x8, guchar, 0, 1, 2, -1, 4, 255)
TYPED_FUNCS (x8r8g8b8, guchar, 1, 2, 3, -1, 4, 255)
TYPED_FUNCS (b8g8r8x8, guchar, 2, 1, 0, -1, 4, 255)
TYPED_FUNCS (x8b8g8r8, guchar, 3, 2, 1, -1, 4, 255)
TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
@@ -360,7 +352,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, 0, 0 },
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_premultiplied_to_float,
b8g8r8a8_premultiplied_from_float,
@@ -385,22 +377,12 @@ static const GdkMemoryFormatDescription memory_formats[] = {
r8g8b8a8_premultiplied_to_float,
r8g8b8a8_premultiplied_from_float,
},
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
a8b8g8r8_premultiplied_to_float,
a8b8g8r8_premultiplied_from_float,
},
[GDK_MEMORY_B8G8R8A8] = {
GDK_MEMORY_ALPHA_STRAIGHT,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, 0, 0 },
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_to_float,
b8g8r8a8_from_float,
@@ -435,46 +417,6 @@ static const GdkMemoryFormatDescription memory_formats[] = {
a8b8g8r8_to_float,
a8b8g8r8_from_float,
},
[GDK_MEMORY_B8G8R8X8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
b8g8r8x8_to_float,
b8g8r8x8_from_float,
},
[GDK_MEMORY_X8R8G8B8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
x8r8g8b8_to_float,
x8r8g8b8_from_float,
},
[GDK_MEMORY_R8G8B8X8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r8g8b8x8_to_float,
r8g8b8x8_from_float,
},
[GDK_MEMORY_X8B8G8R8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ G_MAXUINT, G_MAXUINT, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
x8b8g8r8_to_float,
x8b8g8r8_from_float,
},
[GDK_MEMORY_R8G8B8] = {
GDK_MEMORY_ALPHA_OPAQUE,
3,
@@ -569,7 +511,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
16,
G_ALIGNOF (float),
GDK_MEMORY_FLOAT32,
TRUE,
{ 0, 0, 3, 0 },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r32g32b32a32_float_to_float,
@@ -791,19 +733,14 @@ gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth)
gboolean
gdk_memory_format_gl_format (GdkMemoryFormat format,
GdkGLContext *context,
gboolean gles,
guint gl_major,
guint gl_minor,
guint *out_internal_format,
guint *out_format,
guint *out_type,
GLint out_swizzle[4])
{
int gl_major;
int gl_minor;
gboolean gles;
gdk_gl_context_get_version (context, &gl_major, &gl_minor);
gles = gdk_gl_context_get_use_es (context);
*out_internal_format = memory_formats[format].gl.internal_format;
*out_format = memory_formats[format].gl.format;
*out_type = memory_formats[format].gl.type;
@@ -815,9 +752,6 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
(memory_formats[format].min_gl_version.gles_major == gl_major &&
memory_formats[format].min_gl_version.gles_minor > gl_minor))
return FALSE;
if (*out_format == GL_BGRA && !gdk_gl_context_has_bgra (context))
return FALSE;
}
else
{
+3 -2
View File
@@ -20,7 +20,6 @@
#pragma once
#include "gdkenums.h"
#include "gdktypes.h"
#include <epoxy/gl.h>
@@ -47,7 +46,9 @@ GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth
GdkMemoryDepth depth2) G_GNUC_CONST;
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
GdkGLContext *context,
gboolean gles,
guint gl_major,
guint gl_minor,
guint *out_internal_format,
guint *out_format,
guint *out_type,
+2 -5
View File
@@ -24,16 +24,13 @@
#include "gdksnapshotprivate.h"
#include "gdkprivate.h"
#include <graphene.h>
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
GdkSnapshot * gtk_snapshot_new (void);
void gtk_snapshot_push_debug (GdkSnapshot *snapshot,
const char *message,
...) G_GNUC_PRINTF (2, 3);
void gtk_snapshot_pop (GdkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot,
const graphene_size_t *size);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot);
/**
* GdkPaintable:
@@ -121,7 +118,7 @@ gdk_paintable_default_get_current_image (GdkPaintable *paintable)
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
return gtk_snapshot_free_to_paintable (snapshot, NULL);
return gtk_snapshot_free_to_paintable (snapshot);
}
static GdkPaintableFlags
+1 -1
View File
@@ -40,7 +40,7 @@ struct _GdkIOPipe
GCond cond;
guchar *buffer;
gsize size;
guint state : 2; /* GdkIOPipeState */
GdkIOPipeState state : 2;
guint input_closed : 1;
guint output_closed : 1;
};
+1 -45
View File
@@ -254,7 +254,7 @@ maybe_flip_position (int bounds_pos,
*flipped = TRUE;
secondary = rect_pos + (1 - rect_sign) * rect_size / 2 - offset - (1 - surface_sign) * surface_size / 2;
if ((secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size) || primary > bounds_pos + bounds_size)
if (secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size)
return secondary;
*flipped = FALSE;
@@ -493,12 +493,6 @@ gdk_surface_real_get_scale (GdkSurface *surface)
return 1.0;
}
static GdkSubsurface *
gdk_surface_real_create_subsurface (GdkSurface *surface)
{
return NULL;
}
static void
gdk_surface_constructed (GObject *object)
{
@@ -521,7 +515,6 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
klass->beep = gdk_surface_real_beep;
klass->get_scale = gdk_surface_real_get_scale;
klass->create_subsurface = gdk_surface_real_create_subsurface;
/**
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
@@ -3061,40 +3054,3 @@ gdk_surface_leave_monitor (GdkSurface *surface,
{
g_signal_emit (surface, signals[LEAVE_MONITOR], 0, monitor);
}
GdkSubsurface *
gdk_surface_create_subsurface (GdkSurface *surface)
{
return GDK_SURFACE_GET_CLASS (surface)->create_subsurface (surface);
}
void
gdk_subsurface_destroy (GdkSubsurface *subsurface)
{
subsurface->class->destroy (subsurface);
}
void
gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds)
{
subsurface->class->attach (subsurface, texture, bounds);
}
/* If sibling is NULL, place the subsurface above its parent */
void
gdk_subsurface_place_above (GdkSubsurface *subsurface,
GdkSubsurface *sibling)
{
subsurface->class->place_above (subsurface, sibling);
}
/* If sibling is NULL, place the subsurface below its parent */
void
gdk_subsurface_place_below (GdkSubsurface *subsurface,
GdkSubsurface *sibling)
{
subsurface->class->place_below (subsurface, sibling);
}
-35
View File
@@ -23,14 +23,9 @@
#include "gdkenumtypes.h"
#include "gdksurface.h"
#include "gdktoplevel.h"
#include <graphene.h>
G_BEGIN_DECLS
typedef struct _GdkSubsurface GdkSubsurface;
typedef struct _GskRenderNode GskRenderNode;
struct _GdkSurface
{
GObject parent_instance;
@@ -151,9 +146,6 @@ struct _GdkSurfaceClass
cairo_region_t *region);
void (* request_layout) (GdkSurface *surface);
gboolean (* compute_size) (GdkSurface *surface);
GdkSubsurface *
(* create_subsurface) (GdkSurface *surface);
};
#define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
@@ -342,34 +334,7 @@ void gdk_surface_request_motion (GdkSurface *surface);
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
GdkSubsurface * gdk_surface_create_subsurface (GdkSurface *surface);
typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass;
struct _GdkSubsurfaceClass
{
void (* destroy) (GdkSubsurface *subsurface);
void (* attach) (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds);
void (* place_above) (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
void (* place_below) (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
};
struct _GdkSubsurface
{
const GdkSubsurfaceClass *class;
};
void gdk_subsurface_destroy (GdkSubsurface *subsurface);
void gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds);
void gdk_subsurface_place_above (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
void gdk_subsurface_place_below (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
G_END_DECLS
+3 -5
View File
@@ -345,9 +345,7 @@ gdk_texture_init (GdkTexture *self)
*
* Creates a new texture object representing the surface.
*
* The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* The newly created texture will acquire a reference on the @surface.
* @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* Returns: a new `GdkTexture`
*/
@@ -366,7 +364,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
@@ -821,7 +819,7 @@ gdk_texture_set_render_data (GdkTexture *self,
GDestroyNotify notify)
{
g_return_val_if_fail (data != NULL, FALSE);
if (self->render_key != NULL)
return FALSE;
-2
View File
@@ -96,8 +96,6 @@ typedef struct _GdkCairoContext GdkCairoContext;
typedef struct _GdkGLContext GdkGLContext;
typedef struct _GdkVulkanContext GdkVulkanContext;
typedef struct _GdkDmabufFormats GdkDmabufFormats;
/*
* GDK_DECLARE_INTERNAL_TYPE:
* @ModuleObjName: The name of the new type, in camel case (like GtkWidget)
-7
View File
@@ -1475,13 +1475,6 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
gboolean validate = FALSE, have_debug_report = FALSE;
VkResult res;
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_DISABLE)
{
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
_("Vulkan support disabled via GDK_DEBUG"));
return FALSE;
}
if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
{
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
-5
View File
@@ -329,7 +329,6 @@ gdk_save_png (GdkTexture *texture)
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
@@ -341,10 +340,6 @@ gdk_save_png (GdkTexture *texture)
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8B8G8R8:
format = GDK_MEMORY_R8G8B8;
png_format = PNG_COLOR_TYPE_RGB;
depth = 8;
-5
View File
@@ -236,17 +236,12 @@ static const FormatData format_data[] = {
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8R8G8B8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8B8G8R8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_X8R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_X8B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16] = { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16A16] = { GDK_MEMORY_R16G16B16A16, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
-10
View File
@@ -17,12 +17,6 @@ gdk_public_sources = files([
'gdkdevicetool.c',
'gdkdisplay.c',
'gdkdisplaymanager.c',
'gdkdmabuf.c',
'gdkdmabufegl.c',
'gdkdmabufformats.c',
'gdkdmabufformatsbuilder.c',
'gdkdmabuftexture.c',
'gdkdmabuftexturebuilder.c',
'gdkdrag.c',
'gdkdragsurface.c',
'gdkdragsurfacesize.c',
@@ -85,9 +79,6 @@ gdk_public_headers = files([
'gdkdisplay.h',
'gdkdisplaymanager.h',
'gdkdrag.h',
'gdkdmabufformats.h',
'gdkdmabuftexture.h',
'gdkdmabuftexturebuilder.h',
'gdkdragsurfacesize.h',
'gdkdrawcontext.h',
'gdkdrop.h',
@@ -217,7 +208,6 @@ gdk_deps = [
platform_gio_dep,
pangocairo_dep,
vulkan_dep,
dmabuf_dep,
png_dep,
tiff_dep,
jpeg_dep,
+28 -104
View File
@@ -24,7 +24,6 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/sysmacros.h>
#ifdef HAVE_LINUX_MEMFD_H
#include <linux/memfd.h>
@@ -57,7 +56,6 @@
#include <wayland/xdg-foreign-unstable-v1-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include <wayland/server-decoration-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "wm-button-layout-translation.h"
@@ -269,105 +267,45 @@ postpone_on_globals_closure (GdkWaylandDisplay *display_wayland,
g_list_append (display_wayland->on_has_globals_closures, closure);
}
#ifdef G_ENABLE_DEBUG
static const char *
get_format_name (uint32_t format,
char name[10])
{
if (format == 0)
g_strlcpy (name, "ARGB8888", 10);
else if (format == 1)
g_strlcpy (name, "XRGB8888", 10);
else
g_snprintf (name, 10, "4cc %c%c%c%c",
(char) (format & 0xff),
(char) ((format >> 8) & 0xff),
(char) ((format >> 16) & 0xff),
(char) ((format >> 24) & 0xff));
return name;
}
#endif
static void
wl_shm_format (void *data,
struct wl_shm *wl_shm,
uint32_t format)
{
GDK_DEBUG (MISC, "supported shm pixel format %.4s (0x%X)", (char *) &format, format);
#ifdef G_ENABLE_DEBUG
char buf[10];
#endif
GDK_DEBUG (MISC, "supported pixel format %s (0x%X)",
get_format_name (format, buf), (guint) format);
}
static const struct wl_shm_listener wl_shm_listener = {
wl_shm_format
};
static void
linux_dmabuf_done (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
{
GDK_DEBUG (MISC, "dmabuf feedback done");
}
static void
linux_dmabuf_format_table (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
int32_t fd,
uint32_t size)
{
GdkWaylandDisplay *display_wayland = data;
display_wayland->linux_dmabuf_n_formats = size / 16;
display_wayland->linux_dmabuf_formats = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
GDK_DEBUG (MISC, "got dmabuf format table (%lu entries)", display_wayland->linux_dmabuf_n_formats);
}
static void
linux_dmabuf_main_device (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *device)
{
dev_t dev = *(dev_t *)device->data;
GDK_DEBUG (MISC, "got dmabuf main device: %u %u", major (dev), minor (dev));
}
static void
linux_dmabuf_tranche_done (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
{
GDK_DEBUG (MISC, "dmabuf feedback tranche done");
}
static void
linux_dmabuf_tranche_target_device (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *device)
{
dev_t dev = *(dev_t *)device->data;
GDK_DEBUG (MISC, "got dmabuf tranche target device: %u %u", major (dev), minor (dev));
}
static void
linux_dmabuf_tranche_formats (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *indices)
{
GdkWaylandDisplay *display_wayland = data;
GDK_DEBUG (MISC, "got dmabuf tranche formats (%lu entries):", indices->size / sizeof (guint16));
guint16 *pos;
wl_array_for_each (pos, indices)
{
LinuxDmabufFormat *fmt = &display_wayland->linux_dmabuf_formats[*pos];
uint32_t f = fmt->fourcc;
uint64_t m = fmt->modifier;
GDK_DEBUG (MISC, " %.4s:%#" G_GINT64_MODIFIER "x", (char *) &f, m);
}
}
static void
linux_dmabuf_tranche_flags (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
uint32_t flags)
{
GDK_DEBUG (MISC,
"got dmabuf tranche flags: %s",
flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT ? "scanout" : "");
}
static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_feedback_listener = {
linux_dmabuf_done,
linux_dmabuf_format_table,
linux_dmabuf_main_device,
linux_dmabuf_tranche_done,
linux_dmabuf_tranche_target_device,
linux_dmabuf_tranche_formats,
linux_dmabuf_tranche_flags,
};
static void
server_decoration_manager_default_mode (void *data,
struct org_kde_kwin_server_decoration_manager *manager,
@@ -444,16 +382,6 @@ gdk_registry_handle_global (void *data,
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
}
else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4)
{
display_wayland->linux_dmabuf =
wl_registry_bind (display_wayland->wl_registry, id, &zwp_linux_dmabuf_v1_interface, version);
display_wayland->linux_dmabuf_feedback =
zwp_linux_dmabuf_v1_get_default_feedback (display_wayland->linux_dmabuf);
zwp_linux_dmabuf_feedback_v1_add_listener (display_wayland->linux_dmabuf_feedback,
&linux_dmabuf_feedback_listener, display_wayland);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp (interface, "xdg_wm_base") == 0)
{
display_wayland->xdg_wm_base_id = id;
@@ -798,10 +726,6 @@ gdk_wayland_display_dispose (GObject *object)
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf_feedback, zwp_linux_dmabuf_feedback_v1_destroy);
if (display_wayland->linux_dmabuf_formats)
munmap (display_wayland->linux_dmabuf_formats, display_wayland->linux_dmabuf_n_formats * 16);
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
-11
View File
@@ -71,13 +71,6 @@ typedef enum _GdkWaylandShellVariant
GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6
} GdkWaylandShellVariant;
typedef struct
{
uint32_t fourcc;
uint32_t padding;
uint64_t modifier;
} LinuxDmabufFormat;
struct _GdkWaylandDisplay
{
GdkDisplay parent_instance;
@@ -102,10 +95,6 @@ struct _GdkWaylandDisplay
struct wl_registry *wl_registry;
struct wl_compositor *compositor;
struct wl_shm *shm;
struct zwp_linux_dmabuf_v1 *linux_dmabuf;
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback;
gsize linux_dmabuf_n_formats;
LinuxDmabufFormat *linux_dmabuf_formats;
struct xdg_wm_base *xdg_wm_base;
struct zxdg_shell_v6 *zxdg_shell_v6;
struct gtk_shell1 *gtk_shell;
+1 -1
View File
@@ -75,7 +75,7 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
/* We should do this when setting up the EGLSurface, but we don't make_current then */
/* We should do ths when setting up the EGLSurface, but we don't make_current then */
eglSwapInterval (gdk_display_get_egl_display (gdk_draw_context_get_display (draw_context)), 0);
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
+1 -1
View File
@@ -35,7 +35,6 @@
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/gdkseat-wayland.h>
#include <gsk/gsk.h>
#include <xkbcommon/xkbcommon.h>
@@ -223,3 +222,4 @@ void gdk_wayland_surface_update_scale (GdkSurface *surface);
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
guint32 mods);
-2
View File
@@ -86,8 +86,6 @@ struct _GdkWaylandSurface
uint32_t last_configure_serial;
int state_freeze_count;
GPtrArray *subsurfaces;
};
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
+1 -256
View File
@@ -33,11 +33,9 @@
#include "gdksurfaceprivate.h"
#include "gdktoplevelprivate.h"
#include "gdkdevice-wayland-private.h"
#include "gdkdmabuftextureprivate.h"
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include <stdlib.h>
#include <stdio.h>
@@ -50,7 +48,6 @@
#include "gdksurface-wayland-private.h"
#include "gdktoplevel-wayland-private.h"
/**
* GdkWaylandSurface:
*
@@ -155,17 +152,13 @@ wl_region_from_cairo_region (GdkWaylandDisplay *display,
}
/* }}} */
/* {{{ Surface implementation */
static void gdk_wayland_subsurface_destroy (GdkSubsurface *sub);
/* {{{ Surface implementation */
static void
gdk_wayland_surface_init (GdkWaylandSurface *impl)
{
impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (1);
impl->viewport_dirty = TRUE;
impl->subsurfaces = g_ptr_array_new ();
}
void
@@ -559,7 +552,6 @@ gdk_wayland_surface_finalize (GObject *object)
g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
g_clear_pointer (&impl->input_region, cairo_region_destroy);
g_clear_pointer (&impl->subsurfaces, g_ptr_array_unref);
G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
}
@@ -1143,17 +1135,6 @@ gdk_wayland_surface_set_input_region (GdkSurface *surface,
impl->input_region_dirty = TRUE;
}
static void
gdk_wayland_surface_destroy_subsurfaces (GdkWaylandSurface *impl)
{
for (gsize i = 0; i < impl->subsurfaces->len; i++)
{
GdkSubsurface *sub = g_ptr_array_index (impl->subsurfaces, i);
gdk_subsurface_destroy (sub);
}
g_ptr_array_set_size (impl->subsurfaces, 0);
}
static void
gdk_wayland_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy)
@@ -1170,7 +1151,6 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
if (GDK_IS_TOPLEVEL (surface))
gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface));
gdk_wayland_surface_destroy_subsurfaces (GDK_WAYLAND_SURFACE (surface));
gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface));
frame_clock = gdk_surface_get_frame_clock (surface);
@@ -1227,8 +1207,6 @@ gdk_wayland_surface_default_hide_surface (GdkWaylandSurface *surface)
{
}
static GdkSubsurface *gdk_wayland_surface_create_subsurface (GdkSurface *surface);
static void
gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
{
@@ -1252,7 +1230,6 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
surface_class->get_scale = gdk_wayland_surface_get_scale;
surface_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
surface_class->request_layout = gdk_wayland_surface_request_layout;
surface_class->create_subsurface = gdk_wayland_surface_create_subsurface;
klass->handle_configure = gdk_wayland_surface_default_handle_configure;
klass->handle_frame = gdk_wayland_surface_default_handle_frame;
@@ -1328,236 +1305,4 @@ gdk_wayland_surface_get_wl_surface (GdkSurface *surface)
}
/* }}}} */
/* {{{ Subsurface */
typedef struct {
GdkSubsurface subsurface;
GdkWaylandSurface *parent;
struct wl_surface *wl_surface;
struct wl_subsurface *wl_subsurface;
struct wp_viewport *wp_viewport;
} GdkWaylandSubsurface;
static void
dmabuf_buffer_release (void *data,
struct wl_buffer *wl_buffer)
{
GdkTexture *texture = data;
g_object_unref (texture);
wl_buffer_destroy (wl_buffer);
}
static const struct wl_buffer_listener dmabuf_buffer_listener = {
dmabuf_buffer_release,
};
static struct wl_buffer *
get_dmabuf_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
const GdkDmabuf *dmabuf;
struct zwp_linux_buffer_params_v1 *params;
struct wl_buffer *wl_buffer;
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
params = zwp_linux_dmabuf_v1_create_params (display->linux_dmabuf);
for (gsize i = 0; i < dmabuf->n_planes; i++)
zwp_linux_buffer_params_v1_add (params,
dmabuf->planes[i].fd,
i,
dmabuf->planes[i].offset,
dmabuf->planes[i].stride,
dmabuf->modifier >> 32,
dmabuf->modifier & 0xffffffff);
wl_buffer = zwp_linux_buffer_params_v1_create_immed (params,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
dmabuf->fourcc,
0);
wl_buffer_add_listener (wl_buffer, &dmabuf_buffer_listener, g_object_ref (texture));
return wl_buffer;
}
static void
shm_buffer_release (void *data,
struct wl_buffer *wl_buffer)
{
cairo_surface_t *surface = data;
/* Note: the wl_buffer is destroyed as cairo user data */
cairo_surface_destroy (surface);
}
static const struct wl_buffer_listener shm_buffer_listener = {
shm_buffer_release,
};
static struct wl_buffer *
get_shm_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
int width, height;
cairo_surface_t *surface;
GdkTextureDownloader *downloader;
struct wl_buffer *wl_buffer;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
surface = gdk_wayland_display_create_shm_surface (display, width, height, &GDK_FRACTIONAL_SCALE_INIT_INT (1));
downloader = gdk_texture_downloader_new (texture);
gdk_texture_downloader_download_into (downloader,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_stride (surface));
gdk_texture_downloader_free (downloader);
wl_buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
wl_buffer_add_listener (wl_buffer, &shm_buffer_listener, surface);
return wl_buffer;
}
static struct wl_buffer *
get_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
if (GDK_IS_DMABUF_TEXTURE (texture))
return get_dmabuf_wl_buffer (self, texture);
else
return get_shm_wl_buffer (self, texture);
}
static void
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
GdkTexture *texture,
const graphene_rect_t *rect)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GDK_DEBUG (DMABUF,
"Attaching texture %p at %f %f %f %f",
texture,
rect->origin.x, rect->origin.y, rect->size.width, rect->size.height);
if (rect)
{
wl_subsurface_set_position (self->wl_subsurface,
floorf (rect->origin.x),
floorf (rect->origin.y));
wp_viewport_set_destination (self->wp_viewport,
ceilf (rect->origin.x + rect->size.width) - floorf (rect->origin.x),
ceilf (rect->origin.y + rect->size.height) - floorf (rect->origin.y));
}
if (texture)
{
wl_surface_attach (self->wl_surface, get_wl_buffer (self, texture), 0, 0);
wl_surface_damage_buffer (self->wl_surface,
0, 0,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
else
{
wl_surface_attach (self->wl_surface, NULL, 0, 0);
}
wl_surface_commit (self->wl_surface);
}
static void
gdk_wayland_subsurface_destroy (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
g_clear_pointer (&self->wp_viewport, wp_viewport_destroy);
g_clear_pointer (&self->wl_subsurface, wl_subsurface_destroy);
g_clear_pointer (&self->wl_surface, wl_surface_destroy);
g_ptr_array_remove (self->parent->subsurfaces, self);
g_free (self);
}
static void
gdk_wayland_subsurface_place_above (GdkSubsurface *sub,
GdkSubsurface *sibling)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
g_return_if_fail (sib == NULL || self->parent == sib->parent);
wl_subsurface_place_above (self->wl_subsurface,
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
}
static void
gdk_wayland_subsurface_place_below (GdkSubsurface *sub,
GdkSubsurface *sibling)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
g_return_if_fail (sib == NULL || self->parent == sib->parent);
wl_subsurface_place_below (self->wl_subsurface,
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
}
static const GdkSubsurfaceClass subsurface_class = {
gdk_wayland_subsurface_destroy,
gdk_wayland_subsurface_attach,
gdk_wayland_subsurface_place_above,
gdk_wayland_subsurface_place_below,
};
static GdkSubsurface *
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSubsurface *sub;
struct wl_region *wl_region;
if (display->viewporter == NULL)
{
GDK_DEBUG (DMABUF, "Can't use subsurfaces without viewporter");
return NULL;
}
sub = g_new0 (GdkWaylandSubsurface, 1);
sub->subsurface.class = &subsurface_class;
sub->parent = impl;
g_ptr_array_add (sub->parent->subsurfaces, sub);
sub->wl_surface = wl_compositor_create_surface (display->compositor);
wl_region = wl_compositor_create_region (display->compositor);
wl_surface_set_input_region (sub->wl_surface, wl_region);
wl_region_destroy (wl_region);
sub->wl_subsurface = wl_subcompositor_get_subsurface (display->subcompositor,
sub->wl_surface,
impl->display_server.wl_surface);
sub->wp_viewport = wp_viewporter_get_viewport (display->viewporter, sub->wl_surface);
GDK_DEBUG (DMABUF, "Subsurface created");
return (GdkSubsurface *) sub;
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
-1
View File
@@ -67,7 +67,6 @@ proto_sources = [
['idle-inhibit', 'unstable', 'v1', ],
['xdg-activation', 'staging', 'v1', ],
['fractional-scale', 'staging', 'v1', ],
['linux-dmabuf', 'unstable', 'v1', ],
]
gdk_wayland_gen_headers = []
-4
View File
@@ -4442,10 +4442,6 @@ _gdk_win32_surface_request_layout (GdkSurface *surface)
{
_gdk_win32_get_window_rect (surface, &rect);
/* Keep current position if rect is invalid (i.e. queried in bad context) */
if (rect.right == rect.left || rect.bottom == rect.top)
return;
impl->next_layout.configured_width = (rect.right - rect.left + scale - 1) / scale;
impl->next_layout.configured_height = (rect.bottom - rect.top + scale - 1) / scale;
+2 -7
View File
@@ -453,7 +453,7 @@ get_colorized_texture (GdkTexture *texture,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset)
{
cairo_surface_t *surface;
cairo_surface_t *surface = gdk_texture_download_surface (texture);
cairo_surface_t *image_surface;
graphene_vec4_t pixel;
guint32* pixel_data;
@@ -475,7 +475,6 @@ get_colorized_texture (GdkTexture *texture,
return g_object_ref (colorized->texture);
}
surface = gdk_texture_download_surface (texture);
image_surface = cairo_surface_map_to_image (surface, NULL);
data = cairo_image_surface_get_data (image_surface);
width = cairo_image_surface_get_width (image_surface);
@@ -537,8 +536,6 @@ get_colorized_texture (GdkTexture *texture,
colorized_list, (GDestroyNotify)colorized_texture_free_list);
}
cairo_surface_destroy (surface);
return colorized_texture;
}
@@ -614,7 +611,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
}
texture = gdk_texture_new_for_surface (image_surface);
g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */
g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
texture_id = gdk_broadway_display_ensure_texture (display, texture);
add_rect (nodes, &node->bounds, offset_x, offset_y);
@@ -905,8 +902,6 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
add_float (nodes, width);
add_float (nodes, height);
add_uint32 (nodes, texture_id);
cairo_surface_destroy (surface);
}
}
+1 -2
View File
@@ -76,8 +76,7 @@ gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
g_assert (self != NULL);
g_assert (target == GL_TEXTURE_1D ||
target == GL_TEXTURE_2D ||
target == GL_TEXTURE_3D ||
target == GL_TEXTURE_EXTERNAL_OES);
target == GL_TEXTURE_3D);
g_assert (texture >= GL_TEXTURE0 && texture <= GL_TEXTURE16);
g_assert (texture - GL_TEXTURE0 < G_N_ELEMENTS (self->textures));
-3
View File
@@ -29,9 +29,6 @@ typedef struct _GskGLBindFramebuffer GskGLBindFramebuffer;
typedef struct _GskGLBindTexture GskGLBindTexture;
#define GSK_GL_N_FILTERS 3
#define SAMPLER_EXTERNAL 9
G_STATIC_ASSERT (SAMPLER_EXTERNAL >= GSK_GL_N_FILTERS * GSK_GL_N_FILTERS);
static inline guint
filter_index (GLint filter)
+44 -43
View File
@@ -282,10 +282,7 @@ snapshot_attachments (const GskGLAttachmentState *state,
{
bind[count].id = state->textures[i].id;
bind[count].texture = state->textures[i].texture;
if (state->textures[i].target == GL_TEXTURE_EXTERNAL_OES)
bind[count].sampler = SAMPLER_EXTERNAL;
else
bind[count].sampler = state->textures[i].sampler;
bind[count].sampler = state->textures[i].sampler;
count++;
}
}
@@ -1073,7 +1070,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation (GL_FUNC_ADD);
if (gdk_gl_context_has_vertex_arrays (self->context))
if (!gdk_gl_context_get_use_es (self->context))
{
glGenVertexArrays (1, &vao_id);
glBindVertexArray (vao_id);
@@ -1193,23 +1190,12 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
s->sync = NULL;
}
if (bind->sampler == SAMPLER_EXTERNAL)
glBindTexture (GL_TEXTURE_EXTERNAL_OES, bind->id);
else
glBindTexture (GL_TEXTURE_2D, bind->id);
glBindTexture (GL_TEXTURE_2D, bind->id);
textures[bind->texture] = bind->id;
if (!self->has_samplers)
{
if (bind->sampler == SAMPLER_EXTERNAL)
{
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
}
@@ -1219,16 +1205,8 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
glBindSampler (bind->texture, self->samplers[bind->sampler]);
else
{
if (bind->sampler == SAMPLER_EXTERNAL)
{
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
samplers[bind->texture] = bind->sampler;
}
@@ -1279,7 +1257,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
}
glDeleteBuffers (1, &vbo_id);
if (gdk_gl_context_has_vertex_arrays (self->context))
if (!gdk_gl_context_get_use_es (self->context))
glDeleteVertexArrays (1, &vao_id);
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
@@ -1346,7 +1324,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
if (self->attachments->textures[i].id != 0)
{
glActiveTexture (GL_TEXTURE0 + i);
glBindTexture (self->attachments->textures[i].target, 0);
glBindTexture (GL_TEXTURE_2D, 0);
self->attachments->textures[i].id = 0;
self->attachments->textures[i].changed = FALSE;
@@ -1423,7 +1401,7 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_id);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1451,9 +1429,8 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
}
/* Restore the previous texture if it was set */
if (self->attachments->textures[0].id != 0 &&
self->attachments->textures[0].target == GL_TEXTURE_2D)
glBindTexture (self->attachments->textures[0].target, self->attachments->textures[0].id);
if (self->attachments->textures[0].id != 0)
glBindTexture (GL_TEXTURE_2D, self->attachments->textures[0].id);
return (int)texture_id;
}
@@ -1473,7 +1450,9 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
static GdkMemoryFormat
memory_format_gl_format (GdkMemoryFormat data_format,
GdkGLContext *context,
gboolean use_es,
guint major,
guint minor,
guint *gl_internalformat,
guint *gl_format,
guint *gl_type,
@@ -1483,7 +1462,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
/* First, try the format itself */
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1499,7 +1480,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
case GDK_MEMORY_FLOAT16:
data_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1510,7 +1493,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
case GDK_MEMORY_U16:
data_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1532,7 +1517,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
{
data_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1543,7 +1530,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
/* If all else fails, pick the one format that's always supported */
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
if (!gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1572,13 +1561,19 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
GLenum gl_type;
GLint gl_swizzle[4];
gsize bpp;
gboolean use_es;
int major, minor;
use_es = gdk_gl_context_get_use_es (self->context);
gdk_gl_context_get_version (self->context, &major, &minor);
data_format = gdk_texture_get_format (texture);
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
data_format = memory_format_gl_format (data_format,
self->context,
use_es,
major,
minor,
&gl_internalformat,
&gl_format,
&gl_type,
@@ -1643,7 +1638,9 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
GLenum gl_format;
GLenum gl_type;
GLint gl_swizzle[4];
gboolean use_es;
int texture_id;
int major, minor;
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
@@ -1676,9 +1673,13 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
glBindTexture (GL_TEXTURE_2D, texture_id);
/* Initialize the texture */
use_es = gdk_gl_context_get_use_es (self->context);
gdk_gl_context_get_version (self->context, &major, &minor);
data_format = gdk_texture_get_format (chunks[0].texture);
data_format = memory_format_gl_format (data_format,
self->context,
use_es,
major,
minor,
&gl_internalformat,
&gl_format,
&gl_type,
-6
View File
@@ -54,7 +54,6 @@ typedef struct _GskGLCommandBind
*/
guint texture : 4;
/* the sampler to use. We set sampler to 15 to indicate external textures */
guint sampler : 4;
/* The identifier for the texture created with glGenTextures(). */
@@ -235,13 +234,8 @@ struct _GskGLCommandQueue
/* Array of samplers that we use for mag/min filter handling. It is indexed
* by the sampler_index() function.
*
* Note that when samplers are not supported (hello GLES), we fall back to
* setting the texture filter, but that needs to be done for every texture.
*
* Also note that we don't use all of these samplers since some combinations
* are invalid. An index of SAMPLER_EXTERNAL is used to indicate an external
* texture, which needs special sampler treatment.
*/
GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];
+7 -15
View File
@@ -54,7 +54,6 @@ struct _GskGLCompiler
guint gl3 : 1;
guint gles : 1;
guint gles3 : 1;
guint legacy : 1;
guint debug_shaders : 1;
};
@@ -135,10 +134,7 @@ gsk_gl_compiler_new (GskGLDriver *driver,
gdk_gl_context_get_version (context, &maj, &min);
if (maj >= 3)
{
self->glsl_version = SHADER_VERSION_GLES3;
self->gles3 = TRUE;
}
self->glsl_version = SHADER_VERSION_GLES3;
else
{
self->glsl_version = SHADER_VERSION_GLES;
@@ -547,7 +543,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
const char *legacy = "";
const char *gl3 = "";
const char *gles = "";
const char *gles3 = "";
int program_id;
int vertex_id;
int fragment_id;
@@ -574,17 +569,15 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
if (self->gles)
gles = "#define GSK_GLES 1\n";
if (self->gles3)
gles3 = "#define GSK_GLES3 1\n";
if (self->gl3)
gl3 = "#define GSK_GL3 1\n";
vertex_id = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vertex_id,
11,
10,
(const char *[]) {
version, debug, legacy, gl3, gles, gles3, clip,
version, debug, legacy, gl3, gles,
clip,
get_shader_string (self->all_preamble),
get_shader_string (self->vertex_preamble),
get_shader_string (self->vertex_source),
@@ -596,7 +589,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
strlen (legacy),
strlen (gl3),
strlen (gles),
strlen (gles3),
strlen (clip),
g_bytes_get_size (self->all_preamble),
g_bytes_get_size (self->vertex_preamble),
@@ -615,9 +607,10 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fragment_id,
11,
10,
(const char *[]) {
version, debug, legacy, gl3, gles, gles3, clip,
version, debug, legacy, gl3, gles,
clip,
get_shader_string (self->all_preamble),
get_shader_string (self->fragment_preamble),
get_shader_string (self->fragment_source),
@@ -629,7 +622,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
strlen (legacy),
strlen (gl3),
strlen (gles),
strlen (gles3),
strlen (clip),
g_bytes_get_size (self->all_preamble),
g_bytes_get_size (self->fragment_preamble),
+34 -236
View File
@@ -44,8 +44,6 @@
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
@@ -226,8 +224,6 @@ gsk_gl_driver_dispose (GObject *object)
GSK_GL_DELETE_PROGRAM(name); \
GSK_GL_DELETE_PROGRAM(name ## _no_clip); \
GSK_GL_DELETE_PROGRAM(name ## _rect_clip);
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
GSK_GL_DELETE_PROGRAM(name);
#define GSK_GL_DELETE_PROGRAM(name) \
G_STMT_START { \
if (self->name) \
@@ -242,7 +238,6 @@ gsk_gl_driver_dispose (GObject *object)
#undef GSK_GL_SHADER_JOINED
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
if (self->shader_cache != NULL)
{
@@ -378,11 +373,6 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name, uniforms, "");
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, sources, uniforms) \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \
sources \
GSK_GL_COMPILE_PROGRAM(name, uniforms, "#define NO_CLIP 1\n");
#define GSK_GL_COMPILE_PROGRAM(name, uniforms, clip) \
G_STMT_START { \
GskGLProgram *program; \
@@ -409,8 +399,8 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
g_steal_pointer (&program); \
} G_STMT_END;
# include "gskglprograms.defs"
#undef GSK_GL_DEFINE_PROGRAM_CLIP
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_SHADER_SINGLE
#undef GSK_GL_SHADER_JOINED
@@ -713,180 +703,6 @@ gsk_gl_driver_cache_texture (GskGLDriver *self,
}
}
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
static void
set_viewport_for_size (GskGLDriver *self,
GskGLProgram *program,
float width,
float height)
{
float viewport[4] = { 0, 0, width, height };
gsk_gl_uniform_state_set4fv (program->uniforms,
program->program_info,
UNIFORM_SHARED_VIEWPORT, 0,
1,
(const float *)&viewport);
self->stamps[UNIFORM_SHARED_VIEWPORT]++;
}
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
static void
set_projection_for_size (GskGLDriver *self,
GskGLProgram *program,
float width,
float height)
{
graphene_matrix_t projection;
graphene_matrix_init_ortho (&projection, 0, width, 0, height, ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
graphene_matrix_scale (&projection, 1, -1, 1);
gsk_gl_uniform_state_set_matrix (program->uniforms,
program->program_info,
UNIFORM_SHARED_PROJECTION, 0,
&projection);
self->stamps[UNIFORM_SHARED_PROJECTION]++;
}
static void
reset_modelview (GskGLDriver *self,
GskGLProgram *program)
{
graphene_matrix_t modelview;
graphene_matrix_init_identity (&modelview);
gsk_gl_uniform_state_set_matrix (program->uniforms,
program->program_info,
UNIFORM_SHARED_MODELVIEW, 0,
&modelview);
self->stamps[UNIFORM_SHARED_MODELVIEW]++;
}
static void
draw_rect (GskGLCommandQueue *command_queue,
float min_x,
float min_y,
float max_x,
float max_y)
{
GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (command_queue);
float min_u = 0;
float max_u = 1;
float min_v = 1;
float max_v = 0;
guint16 c = FP16_ZERO;
vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { min_u, min_v }, .color = { c, c, c, c } };
vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { max_u, max_v }, .color = { c, c, c, c } };
vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
}
static unsigned int release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture,
gboolean cache_texture);
static guint
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GdkDmabufTexture *texture)
{
GdkGLContext *context = self->command_queue->context;
GdkDisplay *display = gdk_gl_context_get_display (context);
int max_texture_size = self->command_queue->max_texture_size;
const GdkDmabuf *dmabuf;
guint texture_id;
int width, height;
GskGLProgram *program;
GskGLRenderTarget *render_target;
guint prev_fbo;
gdk_gl_context_make_current (context);
width = gdk_texture_get_width (GDK_TEXTURE (texture));
height = gdk_texture_get_height (GDK_TEXTURE (texture));
if (width > max_texture_size || height > max_texture_size)
{
GDK_DEBUG (DMABUF, "Can't import dmabuf bigger than MAX_TEXTURE_SIZE (%d)", max_texture_size);
return 0;
}
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
GDK_DEBUG (DMABUF, "DMA-buf Format %.4s:%#lx", (char *) &dmabuf->fourcc, dmabuf->modifier);
gdk_display_init_dmabuf (display);
if (!gdk_dmabuf_formats_contains (display->egl_external_formats, dmabuf->fourcc, dmabuf->modifier))
{
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_2D texture");
return gdk_gl_context_import_dmabuf (context, width, height,
dmabuf,
GL_TEXTURE_2D);
}
if (!gdk_gl_context_get_use_es (context))
{
GDK_DEBUG (DMABUF, "Can't import external_only dmabuf outside of GLES");
return 0;
}
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_EXTERNAL_OES texture");
texture_id = gdk_gl_context_import_dmabuf (context, width, height,
dmabuf,
GL_TEXTURE_EXTERNAL_OES);
if (texture_id == 0)
return 0;
gsk_gl_driver_autorelease_texture (self, texture_id);
program = self->external;
gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target);
prev_fbo = gsk_gl_command_queue_bind_framebuffer (self->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (self->command_queue, 0, &GRAPHENE_RECT_INIT (0, 0, width, height));
if (gsk_gl_command_queue_begin_draw (self->command_queue, program->program_info, width, height))
{
set_projection_for_size (self, program, width, height);
set_viewport_for_size (self, program, width, height);
reset_modelview (self, program);
gsk_gl_program_set_uniform_texture (program,
UNIFORM_EXTERNAL_SOURCE, 0,
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id);
draw_rect (self->command_queue, 0, 0, width, height);
gsk_gl_command_queue_end_draw (self->command_queue);
}
gsk_gl_command_queue_bind_framebuffer (self->command_queue, prev_fbo);
return release_render_target (self, render_target, FALSE, FALSE);
}
#else
static guint
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GdkDmabufTexture *texture)
{
return 0;
}
#endif /* HAVE_DMABUF && HAVE_EGL */
/**
* gsk_gl_driver_load_texture:
* @self: a `GdkTexture`
@@ -943,11 +759,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
return t->texture_id;
}
if (GDK_IS_DMABUF_TEXTURE (texture))
{
texture_id = gsk_gl_driver_import_dmabuf_texture (self, GDK_DMABUF_TEXTURE (texture));
}
else if (GDK_IS_GL_TEXTURE (texture))
if (GDK_IS_GL_TEXTURE (texture))
{
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
@@ -1150,47 +962,6 @@ gsk_gl_driver_create_render_target (GskGLDriver *self,
return FALSE;
}
static unsigned int
release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture,
gboolean cache_texture)
{
guint texture_id;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (render_target != NULL, 0);
if (release_texture)
{
texture_id = 0;
g_ptr_array_add (self->render_targets, render_target);
}
else
{
texture_id = render_target->texture_id;
if (cache_texture)
{
GskGLTexture *texture;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
g_steal_pointer (&texture));
}
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
g_free (render_target);
}
return texture_id;
}
/**
* gsk_gl_driver_release_render_target:
* @self: a `GskGLDriver`
@@ -1216,7 +987,36 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture)
{
return release_render_target (self, render_target, release_texture, TRUE);
guint texture_id;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (render_target != NULL, 0);
if (release_texture)
{
texture_id = 0;
g_ptr_array_add (self->render_targets, render_target);
}
else
{
GskGLTexture *texture;
texture_id = render_target->texture_id;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
g_steal_pointer (&texture));
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
g_free (render_target);
}
return texture_id;
}
/**
@@ -1801,9 +1601,8 @@ create_texture_from_texture_destroy (gpointer data)
}
GdkTexture *
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id,
GdkMemoryFormat format)
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id)
{
GskGLTextureState *state;
GdkGLTextureBuilder *builder;
@@ -1831,7 +1630,6 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
builder = gdk_gl_texture_builder_new ();
gdk_gl_texture_builder_set_context (builder, self->command_queue->context);
gdk_gl_texture_builder_set_id (builder, texture_id);
gdk_gl_texture_builder_set_format (builder, format);
gdk_gl_texture_builder_set_width (builder, texture->width);
gdk_gl_texture_builder_set_height (builder, texture->height);
gdk_gl_texture_builder_set_sync (builder, state->sync);
+1 -7
View File
@@ -69,9 +69,7 @@ typedef struct {
#define CONCAT_EXPANDED2(a,b) a##b
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos,
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms };
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) enum { uniforms };
# include "gskglprograms.defs"
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_NO_UNIFORMS
@@ -118,13 +116,10 @@ struct _GskGLDriver
GskGLProgram *name ## _no_clip; \
GskGLProgram *name ## _rect_clip; \
GskGLProgram *name;
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
GskGLProgram *name;
# include "gskglprograms.defs"
#undef GSK_GL_NO_UNIFORMS
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
gint64 current_frame_id;
@@ -154,8 +149,7 @@ void gsk_gl_driver_begin_frame (GskGLDriver *s
void gsk_gl_driver_end_frame (GskGLDriver *self);
void gsk_gl_driver_after_frame (GskGLDriver *self);
GdkTexture * gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id,
GdkMemoryFormat format);
guint texture_id);
void gsk_gl_driver_cache_texture (GskGLDriver *self,
const GskTextureKey *key,
guint texture_id);
+5 -8
View File
@@ -119,11 +119,7 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
memset (pixel_data, 255, sizeof pixel_data);
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
#if G_BYTE_ORDER == G_BIG_ENDIAN
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
#endif
)
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
@@ -131,8 +127,9 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
else
{
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
glTexSubImage2D (GL_TEXTURE_2D, 0,
@@ -280,7 +277,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
g_assert (texture_id > 0);
if (G_UNLIKELY (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())))
if G_UNLIKELY (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
@@ -297,7 +294,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
{
pixel_data = cairo_image_surface_get_data (surface);
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / 4);
+2 -6
View File
@@ -111,11 +111,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
"Uploading texture");
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
#if G_BYTE_ORDER == G_BIG_ENDIAN
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
#endif
)
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
@@ -129,7 +125,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
{
pixel_data = surface_data;
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
-10
View File
@@ -87,13 +87,3 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
/* Texture conversion shaders.
*
* Note: If you add new formats here, they need to be added
* to the list of supported formats in gdk/gdkdmabuftexture.c.
*/
GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")),
GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source))
+3 -10
View File
@@ -332,7 +332,6 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
GskGLRenderJob *job;
GdkTexture *texture;
guint texture_id;
GdkMemoryFormat gdk_format;
int width, height, max_size;
int format;
@@ -376,15 +375,9 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
if (gsk_render_node_get_preferred_depth (root) != GDK_MEMORY_U8 &&
gdk_gl_context_check_version (self->context, "3.0", "3.0"))
{
gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
format = GL_RGBA32F;
}
format = GL_RGBA32F;
else
{
format = GL_RGBA8;
gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
}
format = GL_RGBA8;
gdk_gl_context_make_current (self->context);
@@ -401,7 +394,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
#endif
gsk_gl_render_job_render_flipped (job, root);
texture_id = gsk_gl_driver_release_render_target (self->driver, render_target, FALSE);
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id, gdk_format);
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id);
gsk_gl_driver_end_frame (self->driver);
gsk_gl_render_job_free (job);
+78 -145
View File
@@ -30,7 +30,6 @@
#include <gsk/gskglshaderprivate.h>
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkmemorytextureprivate.h>
#include <gdk/gdkdmabuftexture.h>
#include <gsk/gsktransformprivate.h>
#include <gsk/gskroundedrectprivate.h>
#include <gsk/gskrectprivate.h>
@@ -48,7 +47,6 @@
#include "ninesliceprivate.h"
#include "fp16private.h"
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
#define MAX_GRADIENT_STOPS 6
@@ -67,14 +65,6 @@ typedef struct _GskGLRenderClip
guint is_fully_contained : 1;
} GskGLRenderClip;
#define GDK_ARRAY_NAME clips
#define GDK_ARRAY_TYPE_NAME Clips
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderClip
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
typedef struct _GskGLRenderModelview
{
GskTransform *transform;
@@ -87,14 +77,6 @@ typedef struct _GskGLRenderModelview
graphene_matrix_t matrix;
} GskGLRenderModelview;
#define GDK_ARRAY_NAME modelviews
#define GDK_ARRAY_TYPE_NAME Modelviews
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderModelview
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
struct _GskGLRenderJob
{
/* The context containing the framebuffer we are drawing to. Generally this
@@ -135,12 +117,12 @@ struct _GskGLRenderJob
/* An array of GskGLRenderModelview updated as nodes are processed. The
* current modelview is the last element.
*/
Modelviews modelview;
GArray *modelview;
/* An array of GskGLRenderClip updated as nodes are processed. The
* current clip is the last element.
*/
Clips clip;
GArray *clip;
/* Our current alpha state as we process nodes */
float alpha;
@@ -210,26 +192,6 @@ static void gsk_gl_render_job_visit_node (GskGLRenderJob
static gboolean gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
const GskRenderNode *node,
GskGLRenderOffscreen *offscreen);
static void gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen);
static inline GskGLRenderClip *
clips_grow_one (Clips *clips)
{
guint len = clips_get_size (clips);
clips_set_size (clips, len + 1);
return clips_get (clips, len);
}
static inline GskGLRenderModelview *
modelviews_grow_one (Modelviews *modelviews)
{
guint len = modelviews_get_size (modelviews);
modelviews_set_size (modelviews, len + 1);
return modelviews_get (modelviews, len);
}
static inline int
get_target_format (GskGLRenderJob *job,
@@ -276,7 +238,7 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
static inline gboolean G_GNUC_PURE
node_supports_2d_transform (const GskRenderNode *node)
{
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -338,7 +300,7 @@ node_supports_transform (const GskRenderNode *node)
* opacity or color matrix.
*/
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -504,10 +466,15 @@ gsk_gl_render_job_set_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
modelview->transform = transform;
@@ -532,17 +499,26 @@ gsk_gl_render_job_push_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
g_assert (transform != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
if G_LIKELY (modelviews_get_size (&job->modelview) > 1)
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
if G_LIKELY (job->modelview->len > 1)
{
GskGLRenderModelview *last = job->modelview.end - 2;
GskGLRenderModelview *last;
GskTransform *t = NULL;
last = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 2);
/* Multiply given matrix with our previous modelview */
t = gsk_transform_translate (gsk_transform_ref (last->transform),
&(graphene_point_t) {
@@ -576,7 +552,8 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
const GskGLRenderModelview *head;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview);
g_assert (job->modelview->len > 0);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
@@ -587,11 +564,11 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
gsk_transform_unref (head->transform);
job->modelview.end--;
job->modelview->len--;
if (modelviews_get_size (&job->modelview) >= 1)
if (job->modelview->len >= 1)
{
head = job->modelview.end - 1;
head = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len - 1);
job->scale_x = head->scale_x;
job->scale_y = head->scale_y;
@@ -611,12 +588,14 @@ gsk_gl_render_job_push_clip (GskGLRenderJob *job,
GskGLRenderClip *clip;
g_assert (job != NULL);
g_assert (job->clip != NULL);
g_assert (rect != NULL);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect, rect, sizeof *rect);
clip->is_rectilinear = gsk_rounded_rect_is_rectilinear (rect);
clip->is_fully_contained = FALSE;
@@ -631,13 +610,16 @@ gsk_gl_render_job_push_contained_clip (GskGLRenderJob *job)
GskGLRenderClip *old_clip;
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
old_clip = clips_get (&job->clip, clips_get_size (&job->clip) - 2);
old_clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect.bounds, &old_clip->rect.bounds, sizeof (graphene_rect_t));
memset (clip->rect.corner, 0, sizeof clip->rect.corner);
clip->is_rectilinear = TRUE;
@@ -650,11 +632,12 @@ static void
gsk_gl_render_job_pop_clip (GskGLRenderJob *job)
{
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
job->current_clip--;
job->clip.end--;
job->clip->len--;
}
static inline void
@@ -736,7 +719,7 @@ gsk_gl_render_job_transform_bounds (GskGLRenderJob *job,
GskTransformCategory category;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview->len > 0);
g_assert (rect != NULL);
g_assert (out_rect != NULL);
@@ -1231,12 +1214,12 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
cairo_move_to (cr, 0, 0);
cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 0.25);
else
cairo_set_source_rgba (cr, 1, 0, 0, 0.25);
cairo_fill_preserve (cr);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 1);
else
cairo_set_source_rgba (cr, 1, 0, 0, 1);
@@ -1529,7 +1512,7 @@ gsk_gl_render_job_visit_linear_gradient_node (GskGLRenderJob *job,
const graphene_point_t *start = gsk_linear_gradient_node_get_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_get_end (node);
int n_color_stops = gsk_linear_gradient_node_get_n_color_stops (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
float x1 = job->offset_x + start->x;
float x2 = job->offset_x + end->x;
float y1 = job->offset_y + start->y;
@@ -1602,7 +1585,7 @@ gsk_gl_render_job_visit_radial_gradient_node (GskGLRenderJob *job,
float end = gsk_radial_gradient_node_get_end (node);
float hradius = gsk_radial_gradient_node_get_hradius (node);
float vradius = gsk_radial_gradient_node_get_vradius (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
float scale = 1.0f / (end - start);
float bias = -start * scale;
@@ -1747,7 +1730,7 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
* which both have rounded corners.
*/
if (clips_get_size (&job->clip) <= 1)
if (job->clip->len <= 1)
need_offscreen = FALSE;
else if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
need_offscreen = FALSE;
@@ -2816,8 +2799,8 @@ static inline gboolean G_GNUC_PURE
equal_texture_nodes (const GskRenderNode *node1,
const GskRenderNode *node2)
{
if (GSK_RENDER_NODE_TYPE (node1) != GSK_TEXTURE_NODE ||
GSK_RENDER_NODE_TYPE (node2) != GSK_TEXTURE_NODE)
if (gsk_render_node_get_node_type (node1) != GSK_TEXTURE_NODE ||
gsk_render_node_get_node_type (node2) != GSK_TEXTURE_NODE)
return FALSE;
if (gsk_texture_node_get_texture (node1) !=
@@ -3120,7 +3103,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
/* Shadow nodes recolor every pixel of the source texture, but leave the alpha in tact.
* If the child is a color matrix node that doesn't touch the alpha, we can throw that away. */
if (GSK_RENDER_NODE_TYPE (shadow_child) == GSK_COLOR_MATRIX_NODE &&
if (gsk_render_node_get_node_type (shadow_child) == GSK_COLOR_MATRIX_NODE &&
!color_matrix_modifies_alpha (shadow_child))
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
@@ -3140,7 +3123,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
continue;
if (shadow->radius == 0 &&
GSK_RENDER_NODE_TYPE (shadow_child) == GSK_TEXT_NODE)
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
{
if (dx != 0 || dy != 0)
{
@@ -3334,53 +3317,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
}
}
static gboolean
gsk_gl_render_job_texture_mask_for_color (GskGLRenderJob *job,
const GskRenderNode *mask,
const GskRenderNode *color,
const graphene_rect_t *bounds)
{
int max_texture_size = job->command_queue->max_texture_size;
GdkTexture *texture = gsk_texture_node_get_texture (mask);
const GdkRGBA *rgba;
rgba = gsk_color_node_get_color (color);
if (RGBA_IS_CLEAR (rgba))
return TRUE;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size &&
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)))
{
GskGLRenderOffscreen offscreen = {0};
float scale_x = mask->bounds.size.width / texture->width;
float scale_y = mask->bounds.size.height / texture->height;
gboolean use_mipmap;
guint16 cc[4];
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
rgba_to_half (rgba, cc);
gsk_gl_render_job_upload_texture (job, texture, use_mipmap, &offscreen);
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
GL_TEXTURE0,
offscreen.texture_id,
offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR,
GL_LINEAR,
offscreen.sync);
job->source_is_glyph_atlas = FALSE;
gsk_gl_render_job_draw_offscreen_with_color (job, bounds, &offscreen, cc);
gsk_gl_render_job_end_draw (job);
return TRUE;
}
return FALSE;
}
static inline void
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
const GskRenderNode *node)
@@ -3390,17 +3326,6 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
GskGLRenderOffscreen source_offscreen = {0};
GskGLRenderOffscreen mask_offscreen = {0};
/* If the mask is a texture and the source is a color node
* then we can take a shortcut and avoid offscreens.
*/
if (GSK_RENDER_NODE_TYPE (mask) == GSK_TEXTURE_NODE &&
GSK_RENDER_NODE_TYPE (source) == GSK_COLOR_NODE &&
gsk_mask_node_get_mask_mode (node) == GSK_MASK_MODE_ALPHA)
{
if (gsk_gl_render_job_texture_mask_for_color (job, mask, source, &node->bounds))
return;
}
source_offscreen.bounds = &node->bounds;
source_offscreen.force_offscreen = TRUE;
source_offscreen.reset_clip = TRUE;
@@ -3632,12 +3557,16 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen)
{
/* Don't put GL or dmabuf textures into icon caches, they are already on the GPU side */
GdkGLTexture *gl_texture = NULL;
if (GDK_IS_GL_TEXTURE (texture))
gl_texture = GDK_GL_TEXTURE (texture);
if (!ensure_mipmap &&
gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
texture->width,
texture->height) &&
!(GDK_IS_GL_TEXTURE (texture) || GDK_IS_DMABUF_TEXTURE (texture)))
!gl_texture)
{
const GskGLIconData *icon_data;
@@ -3651,18 +3580,16 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
/* Only generate a mipmap if it does not make use reupload
* a GL texture which we could otherwise use directly.
*/
if (GDK_IS_GL_TEXTURE (texture) &&
gdk_gl_context_is_shared (gdk_gl_texture_get_context (GDK_GL_TEXTURE (texture)),
job->command_queue->context))
ensure_mipmap = gdk_gl_texture_has_mipmap (GDK_GL_TEXTURE (texture));
if (gl_texture &&
gdk_gl_context_is_shared (gdk_gl_texture_get_context (gl_texture), job->command_queue->context))
ensure_mipmap = gdk_gl_texture_has_mipmap (gl_texture);
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
init_full_texture_region (offscreen);
offscreen->has_mipmap = ensure_mipmap;
if (GDK_IS_GL_TEXTURE (texture) &&
offscreen->texture_id == gdk_gl_texture_get_id (GDK_GL_TEXTURE (texture)))
offscreen->sync = gdk_gl_texture_get_sync (GDK_GL_TEXTURE (texture));
if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture))
offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
}
}
@@ -3784,6 +3711,12 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
GskTextureKey key;
guint texture_id;
if (filter == GSK_SCALING_FILTER_LINEAR)
{
gsk_gl_render_job_visit_texture (job, texture, bounds);
return;
}
gsk_gl_render_job_untransform_bounds (job, &job->current_clip->rect.bounds, &clip_rect);
if (!graphene_rect_intersection (bounds, &clip_rect, &clip_rect))
@@ -4013,7 +3946,7 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_update_clip (job, &node->bounds, &has_clip))
return;
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_BLEND_NODE:
gsk_gl_render_job_visit_blend_node (job, node);
@@ -4066,12 +3999,12 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (i + 1 < n_children &&
job->current_clip->is_fully_contained &&
GSK_RENDER_NODE_TYPE (child) == GSK_ROUNDED_CLIP_NODE)
gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE)
{
const GskRenderNode *grandchild = gsk_rounded_clip_node_get_child (child);
const GskRenderNode *child2 = children[i + 1];
if (GSK_RENDER_NODE_TYPE (grandchild) == GSK_COLOR_NODE &&
GSK_RENDER_NODE_TYPE (child2) == GSK_BORDER_NODE &&
if (gsk_render_node_get_node_type (grandchild) == GSK_COLOR_NODE &&
gsk_render_node_get_node_type (child2) == GSK_BORDER_NODE &&
gsk_border_node_get_uniform_color (child2) &&
rounded_rect_equal (gsk_rounded_clip_node_get_clip (child),
gsk_border_node_get_outline (child2)))
@@ -4225,7 +4158,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
return FALSE;
}
if (GSK_RENDER_NODE_TYPE (node) == GSK_TEXTURE_NODE &&
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
!offscreen->force_offscreen)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
@@ -4598,8 +4531,8 @@ gsk_gl_render_job_new (GskGLDriver *driver,
job = g_new0 (GskGLRenderJob, 1);
job->driver = g_object_ref (driver);
job->command_queue = job->driver->command_queue;
clips_init (&job->clip);
modelviews_init (&job->modelview);
job->clip = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderClip), 16);
job->modelview = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderModelview), 16);
job->framebuffer = framebuffer;
job->clear_framebuffer = !!clear_framebuffer;
job->default_framebuffer = default_framebuffer;
@@ -4649,16 +4582,16 @@ gsk_gl_render_job_free (GskGLRenderJob *job)
job->current_modelview = NULL;
job->current_clip = NULL;
while (job->modelview.end > job->modelview.start)
while (job->modelview->len > 0)
{
GskGLRenderModelview *modelview = job->modelview.end-1;
GskGLRenderModelview *modelview = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len-1);
g_clear_pointer (&modelview->transform, gsk_transform_unref);
job->modelview.end--;
job->modelview->len--;
}
g_clear_object (&job->driver);
g_clear_pointer (&job->region, cairo_region_destroy);
modelviews_clear (&job->modelview);
clips_clear (&job->clip);
g_clear_pointer (&job->modelview, g_array_unref);
g_clear_pointer (&job->clip, g_array_unref);
g_free (job);
}
-28
View File
@@ -1,28 +0,0 @@
// VERTEX_SHADER:
// external.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// external.glsl
#if defined(GSK_GLES) || defined(GSK_GLES3)
uniform samplerExternalOES u_external_source;
#else
/* Just to make this compile, we won't use it without GLES */
uniform sampler2D u_external_source;
#endif
void main() {
/* Open-code this here, since GskTexture() expects a sampler2D */
#if defined(GSK_GLES) || defined(GSK_LEGACY)
vec4 color = texture2D(u_external_source, vUv);
#else
vec4 color = texture(u_external_source, vUv);
#endif
gskSetOutputColor(color);
}
-6
View File
@@ -1,9 +1,3 @@
#if defined(GSK_GLES3)
#extension GL_OES_EGL_image_external_essl3 : require
#elif defined (GSK_GLES)
#extension GL_OES_EGL_image_external : require
#endif
#ifndef GSK_LEGACY
precision highp float;
#endif
+16 -12
View File
@@ -19,10 +19,8 @@
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
@@ -65,6 +63,9 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
@@ -83,7 +84,11 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
@@ -155,13 +160,6 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
@@ -225,7 +223,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y + height < c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
@@ -325,7 +323,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
static int rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
@@ -336,13 +334,19 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
static int rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
+5 -13
View File
@@ -1,15 +1,9 @@
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// stb_rect_pack.h - v0.99 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
@@ -37,12 +31,9 @@
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
@@ -81,10 +72,11 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
+13
View File
@@ -1749,6 +1749,19 @@ gsk_circle_contour_new (const graphene_point_t *center,
return (GskContour *) self;
}
void
gsk_circle_contour_get_params (const GskContour *contour,
graphene_point_t *center,
float *radius,
gboolean *ccw)
{
const GskCircleContour *self = (const GskCircleContour *) contour;
*center = self->center;
*radius = self->radius;
*ccw = self->ccw;
}
/* }}} */
/* {{{ Rectangle */
+4
View File
@@ -36,6 +36,10 @@ GskContour * gsk_standard_contour_new (GskPathFlags
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
float radius);
void gsk_circle_contour_get_params (const GskContour *contour,
graphene_point_t *center,
float *radius,
gboolean *ccw);
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
GskContour * gsk_rounded_rect_contour_new (const GskRoundedRect *rounded_rect);
+24 -181
View File
@@ -2330,6 +2330,30 @@ gsk_curve_get_crossing (const GskCurve *curve,
return get_class (curve->op)->get_crossing (curve, point);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
/* }}} */
/* {{{ Closest point */
static gboolean
project_point_onto_line (const GskCurve *curve,
const graphene_point_t *point,
@@ -2451,187 +2475,6 @@ gsk_curve_get_closest_point (const GskCurve *curve,
return find_closest_point (curve, point, threshold, 0, 1, out_dist, out_t);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
/* Compute the inverse of the arclength using bisection,
* to a given precision
*/
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
static inline void
_sincosf (float angle,
float *out_s,
float *out_c)
{
#ifdef HAVE_SINCOSF
sincosf (angle, out_s, out_c);
#else
*out_s = sinf (angle);
*out_c = cosf (angle);
#endif
}
static void
align_points (const graphene_point_t *p,
const graphene_point_t *a,
const graphene_point_t *b,
graphene_point_t *q,
int n)
{
graphene_vec2_t n1;
float angle;
float s, c;
get_tangent (a, b, &n1);
angle = - atan2f (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
_sincosf (angle, &s, &c);
for (int i = 0; i < n; i++)
{
q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
}
}
static int
filter_allowable (float t[3],
int n)
{
float g[3];
int j = 0;
for (int i = 0; i < n; i++)
if (0 < t[i] && t[i] < 1)
g[j++] = t[i];
for (int i = 0; i < j; i++)
t[i] = g[i];
return j;
}
/* find solutions for at^2 + bt + c = 0 */
static int
solve_quadratic (float a, float b, float c, float t[2])
{
float d;
int n = 0;
if (fabsf (a) > 0.0001)
{
if (b*b > 4*a*c)
{
d = sqrtf (b*b - 4*a*c);
t[n++] = (-b + d)/(2*a);
t[n++] = (-b - d)/(2*a);
}
else
{
t[n++] = -b / (2*a);
}
}
else if (fabsf (b) > 0.0001)
{
t[n++] = -c / b;
}
return n;
}
int
gsk_curve_get_curvature_points (const GskCurve *curve,
float t[3])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[4];
float a, b, c, d;
float x, y, z;
int n;
if (curve->op != GSK_PATH_CUBIC)
return 0; /* FIXME */
align_points (pts, &pts[0], &pts[3], p, 4);
a = p[2].x * p[1].y;
b = p[3].x * p[1].y;
c = p[1].x * p[2].y;
d = p[3].x * p[2].y;
x = - 3*a + 2*b + 3*c - d;
y = 3*a - b - 3*c;
z = c - a;
n = solve_quadratic (x, y, z, t);
return filter_allowable (t, n);
}
/* Find cusps inside the open interval from 0 to 1.
*
* According to Stone & deRose, A Geometric Characterization
* of Parametric Cubic curves, a necessary and sufficient
* condition is that the first derivative vanishes.
*/
int
gsk_curve_get_cusps (const GskCurve *curve,
float t[2])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[3];
float ax, bx, cx;
float ay, by, cy;
float tx[3];
int nx;
int n = 0;
if (curve->op != GSK_PATH_CUBIC)
return 0;
p[0].x = 3 * (pts[1].x - pts[0].x);
p[0].y = 3 * (pts[1].y - pts[0].y);
p[1].x = 3 * (pts[2].x - pts[1].x);
p[1].y = 3 * (pts[2].y - pts[1].y);
p[2].x = 3 * (pts[3].x - pts[2].x);
p[2].y = 3 * (pts[3].y - pts[2].y);
ax = p[0].x - 2 * p[1].x + p[2].x;
bx = - 2 * p[0].x + 2 * p[1].x;
cx = p[0].x;
nx = solve_quadratic (ax, bx, cx, tx);
nx = filter_allowable (tx, nx);
ay = p[0].y - 2 * p[1].y + p[2].y;
by = - 2 * p[0].y + 2 * p[1].y;
cy = p[0].y;
for (int i = 0; i < nx; i++)
{
float ti = tx[i];
if (0 < ti && ti < 1 &&
fabsf (ay * ti * ti + by * ti + cy) < 0.001)
t[n++] = ti;
}
return n;
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
File diff suppressed because it is too large Load Diff
+13
View File
@@ -187,6 +187,19 @@ int gsk_curve_get_curvature_points (const GskCurve
int gsk_curve_get_cusps (const GskCurve *curve,
float t[2]);
int gsk_curve_intersect (const GskCurve *curve1,
const GskCurve *curve2,
float *t1,
float *t2,
graphene_point_t *p,
GskPathIntersection *kind,
int n);
int gsk_curve_self_intersect (const GskCurve *curve,
float *t1,
graphene_point_t *p,
int n);
G_END_DECLS
+73
View File
@@ -144,6 +144,79 @@ gboolean gsk_path_foreach (GskPath
GskPathForeachFunc func,
gpointer user_data);
/**
* GskPathIntersection:
* @GSK_PATH_INTERSECTION_NONE: No intersection
* @GSK_PATH_INTERSECTION_NORMAL: A normal intersection, where the two paths
* cross each other
* @GSK_PATH_INTERSECTION_START: The start of a segment where the two paths coincide
* @GSK_PATH_INTERSECTION_END: The end of a segment where the two paths coincide
*
* The values of this enumeration classify intersections
* between paths.
*/
typedef enum
{
GSK_PATH_INTERSECTION_NONE,
GSK_PATH_INTERSECTION_NORMAL,
GSK_PATH_INTERSECTION_START,
GSK_PATH_INTERSECTION_END,
} GskPathIntersection;
/**
* GskPathIntersectionFunc:
* @path1: the first path
* @point1: the intersection as point on @path1
* @path2: the second path
* @point2: the intersection as point on @path2
* @kind: specify the nature of the intersection
* @user_data: user data
*
* Prototype of the callback to iterate through the
* intersections of two paths.
*
* Returns: %TRUE to continue iterating, %FALSE to
* immediately abort and not call the function again
*
* Since: 4.14
*/
typedef gboolean (* GskPathIntersectionFunc) (GskPath *path1,
const GskPathPoint *point1,
GskPath *path2,
const GskPathPoint *point2,
GskPathIntersection kind,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_foreach_intersection (GskPath *path1,
GskPath *path2,
GskPathIntersectionFunc func,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_union (GskPath *first,
GskPath *second,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_intersection (GskPath *first,
GskPath *second,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_difference (GskPath *first,
GskPath *second,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_symmetric_difference (GskPath *first,
GskPath *second,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_simplify (GskPath *self,
GskFillRule fill_rule);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPath, gsk_path_unref)
G_END_DECLS
+705
View File
@@ -0,0 +1,705 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gskpathprivate.h"
#include "gskcurveprivate.h"
#include "gskpathbuilder.h"
#include "gskpathpoint.h"
#include "gskcontourprivate.h"
typedef struct
{
gsize count;
gboolean closed;
gboolean z_is_empty;
} CountCurveData;
static gboolean
count_cb (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
CountCurveData *ccd = data;
(ccd->count)++;
if (op ==GSK_PATH_CLOSE)
{
ccd->closed = TRUE;
ccd->z_is_empty = graphene_point_equal (&pts[0], &pts[1]);
}
return TRUE;
}
static gsize
count_curves (const GskContour *contour,
gboolean *closed,
gboolean *z_is_empty)
{
CountCurveData data;
data.count = 0;
data.closed = FALSE;
data.z_is_empty = FALSE;
gsk_contour_foreach (contour, count_cb, &data);
*closed = data.closed;
*z_is_empty = data.z_is_empty;
return data.count;
}
typedef struct
{
GskPathPoint point1;
GskPathPoint point2;
GskPathIntersection kind;
} Intersection;
typedef struct
{
GskPath *path1;
GskPath *path2;
GskPathIntersectionFunc func;
gpointer data;
gsize contour1;
gsize contour2;
gsize idx1;
gsize idx2;
const GskContour *c1;
const GskContour *c2;
GskCurve curve1;
GskCurve curve2;
gboolean c1_closed;
gboolean c2_closed;
gboolean c1_z_is_empty;
gboolean c2_z_is_empty;
gsize c1_count;
gsize c2_count;
GArray *points;
GArray *all_points;
} PathIntersectData;
static gboolean
intersect_curve2 (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
PathIntersectData *pd = data;
float t1[10], t2[10];
graphene_point_t p[10];
GskPathIntersection kind[10];
int n;
if (op == GSK_PATH_MOVE)
{
if (gsk_contour_get_n_ops (pd->c2) == 1)
{
float dist, tt;
if (gsk_curve_get_closest_point (&pd->curve1, &pts[0], 1, &dist, &tt) && dist == 0)
{
Intersection is;
is.kind = GSK_PATH_INTERSECTION_NORMAL;
is.point1.contour = pd->contour1;
is.point1.idx = pd->idx1;
is.point1.t = tt;
is.point2.contour = pd->contour2;
is.point2.idx = 0;
is.point2.t = 1;
g_array_append_val (pd->points, is);
}
}
return TRUE;
}
if (op == GSK_PATH_CLOSE)
{
if (graphene_point_equal (&pts[0], &pts[1]))
return TRUE;
}
pd->idx2++;
gsk_curve_init_foreach (&pd->curve2, op, pts, n_pts, weight);
n = gsk_curve_intersect (&pd->curve1, &pd->curve2, t1, t2, p, kind, 19);
for (int i = 0; i < n; i++)
{
Intersection is;
is.point1.contour = pd->contour1;
is.point2.contour = pd->contour2;
is.point1.idx = pd->idx1;
is.point2.idx = pd->idx2;
is.point1.t = t1[i];
is.point2.t = t2[i];
is.kind = kind[i];
#if 0
g_print ("append p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is.point1.contour, is.point1.idx, is.point1.t,
is.point2.contour, is.point2.idx, is.point2.t,
kn[is.kind]);
#endif
g_array_append_val (pd->points, is);
}
return TRUE;
}
static gboolean
intersect_curve (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
PathIntersectData *pd = data;
GskBoundingBox b1, b2;
if (op == GSK_PATH_MOVE)
{
if (gsk_contour_get_n_ops (pd->c1) == 1)
{
GskPathPoint point;
float dist;
if (gsk_contour_get_closest_point (pd->c2, &pts[0], 1, &point, &dist) && dist == 0)
{
Intersection is;
is.kind = GSK_PATH_INTERSECTION_NORMAL;
is.point1.contour = pd->contour1;
is.point1.idx = 0;
is.point1.t = 1;
is.point2.contour = pd->contour2;
is.point2.idx = point.idx;
is.point2.t = point.t;
g_array_append_val (pd->points, is);
}
}
return TRUE;
}
if (op == GSK_PATH_CLOSE)
{
if (graphene_point_equal (&pts[0], &pts[1]))
return TRUE;
}
pd->idx1++;
gsk_curve_init_foreach (&pd->curve1, op, pts, n_pts, weight);
gsk_curve_get_bounds (&pd->curve1, &b1);
gsk_contour_get_bounds (pd->c2, &b2);
if (gsk_bounding_box_intersection (&b1, &b2, NULL))
{
pd->idx2 = 0;
if (!gsk_contour_foreach (pd->c2, intersect_curve2, pd))
return FALSE;
}
return TRUE;
}
static gboolean
gsk_path_point_near (const GskPathPoint *p1,
const GskPathPoint *p2,
gboolean closed,
gsize count,
gboolean z_is_empty,
float epsilon)
{
if (p1->idx == p2->idx && fabsf (p1->t - p2->t) < epsilon)
return TRUE;
if (p1->idx + 1 == p2->idx && (1 - p1->t + p2->t < epsilon))
return TRUE;
if (p2->idx + 1 == p1->idx && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (closed)
{
if (p1->idx == 1 && p2->idx == count - 1 && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (p2->idx == 1 && p1->idx == count - 1 && (1 - p1->t + p2->t < epsilon))
return TRUE;
}
if (closed && z_is_empty)
{
if (p1->idx == 1 && p2->idx == count - 2 && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (p2->idx == 1 && p1->idx == count - 2 && (1 - p1->t + p2->t < epsilon))
return TRUE;
}
return FALSE;
}
static int cmp_path1 (gconstpointer p1, gconstpointer p2);
static void
default_contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
pd->idx1 = 0;
g_array_set_size (pd->points, 0);
gsk_contour_foreach (contour1, intersect_curve, pd);
g_array_sort (pd->points, cmp_path1);
#if 0
g_print ("after sorting\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is1 = &g_array_index (pd->points, Intersection, i);
for (gsize j = i + 1; j < pd->points->len; j++)
{
Intersection *is2 = &g_array_index (pd->points, Intersection, j);
if (!gsk_path_point_near (&is1->point1, &is2->point1,
pd->c1_closed, pd->c1_count, pd->c1_z_is_empty,
0.001))
continue;
if (!gsk_path_point_near (&is1->point2, &is2->point2,
pd->c2_closed, pd->c2_count, pd->c2_z_is_empty,
0.001))
continue;
if (is1->kind == GSK_PATH_INTERSECTION_NORMAL && is2->kind != GSK_PATH_INTERSECTION_NONE)
is1->kind = GSK_PATH_INTERSECTION_NONE;
else if (is2->kind == GSK_PATH_INTERSECTION_NORMAL && is1->kind != GSK_PATH_INTERSECTION_NONE)
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
}
#if 0
g_print ("after collapsing\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is1 = &g_array_index (pd->points, Intersection, i);
for (gsize j = i + 1; j < pd->points->len; j++)
{
Intersection *is2 = &g_array_index (pd->points, Intersection, j);
if (!gsk_path_point_near (&is1->point1, &is2->point1, FALSE, 0, FALSE, 0.001))
break;
if (!gsk_path_point_near (&is1->point2, &is2->point2,
pd->c2_closed, pd->c2_count, pd->c2_z_is_empty,
0.001))
break;
if ((is1->kind == GSK_PATH_INTERSECTION_END &&
is2->kind == GSK_PATH_INTERSECTION_START) ||
(is1->kind == GSK_PATH_INTERSECTION_START &&
is2->kind == GSK_PATH_INTERSECTION_END))
{
is1->kind = GSK_PATH_INTERSECTION_NONE;
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
}
}
#if 0
g_print ("after merging segments\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize j = 0; j < pd->points->len; j++)
{
Intersection *is = &g_array_index (pd->points, Intersection, j);
if (is->kind != GSK_PATH_INTERSECTION_NONE)
g_array_append_val (pd->all_points, *is);
}
}
static int
circle_intersect (const graphene_point_t *center1,
float radius1,
const graphene_point_t *center2,
float radius2,
graphene_point_t points[2])
{
float d;
float a, h;
graphene_point_t m;
graphene_vec2_t n;
g_assert (radius1 >= 0);
g_assert (radius2 >= 0);
d = graphene_point_distance (center1, center2, NULL, NULL);
if (d < fabsf (radius1 - radius2))
return 0;
if (d > radius1 + radius2)
return 0;
if (d == radius1 + radius2)
{
graphene_point_interpolate (center1, center2, radius1 / (radius1 + radius2), &points[0]);
return 1;
}
a = (radius1*radius1 - radius2*radius2 + d*d)/(2*d);
h = sqrtf (radius1*radius1 - a*a);
graphene_point_interpolate (center1, center2, a/d, &m);
graphene_vec2_init (&n, center2->y - center1->y, center1->x - center2->x);
graphene_vec2_normalize (&n, &n);
graphene_point_init (&points[0], m.x + graphene_vec2_get_x (&n) * h,
m.y + graphene_vec2_get_y (&n) * h);
graphene_point_init (&points[1], m.x - graphene_vec2_get_x (&n) * h,
m.y - graphene_vec2_get_y (&n) * h);
return 2;
}
static void
circle_contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
graphene_point_t center1, center2;
float radius1, radius2;
gboolean ccw1, ccw2;
graphene_point_t p[2];
int n;
Intersection is[2];
gsk_circle_contour_get_params (contour1, &center1, &radius1, &ccw1);
gsk_circle_contour_get_params (contour2, &center2, &radius2, &ccw2);
if (graphene_point_equal (&center1, &center2) && radius1 == radius2)
{
is[0].kind = GSK_PATH_INTERSECTION_START;
is[0].point1.contour = pd->contour1;
is[0].point1.idx = 1;
is[0].point1.t = 0;
is[0].point2.contour = pd->contour2;
is[0].point2.idx = 1;
is[0].point2.t = 0;
is[1].kind = GSK_PATH_INTERSECTION_END;
is[1].point1.contour = pd->contour1;
is[1].point1.idx = 1;
is[1].point1.t = 1;
is[1].point2.contour = pd->contour2;
is[1].point2.idx = 1;
is[1].point2.t = 1;
if (ccw1 != ccw2)
{
is[0].point2.t = 1;
is[1].point2.t = 0;
}
g_array_append_val (pd->all_points, is[0]);
g_array_append_val (pd->all_points, is[1]);
return;
}
n = circle_intersect (&center1, radius1, &center2, radius2, p);
for (int i = 0; i < n; i++)
{
float d;
is[i].kind = GSK_PATH_INTERSECTION_NORMAL;
is[i].point1.contour = pd->contour1;
is[i].point2.contour = pd->contour2;
gsk_contour_get_closest_point (contour1, &p[i], 1, &is[i].point1, &d);
gsk_contour_get_closest_point (contour2, &p[i], 1, &is[i].point2, &d);
}
if (n == 1)
{
g_array_append_val (pd->all_points, is[0]);
}
else if (n == 2)
{
if (gsk_path_point_compare (&is[0].point1, &is[1].point1) < 0)
{
g_array_append_val (pd->all_points, is[0]);
g_array_append_val (pd->all_points, is[1]);
}
else
{
g_array_append_val (pd->all_points, is[1]);
g_array_append_val (pd->all_points, is[0]);
}
}
}
static void
contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
if (strcmp (gsk_contour_get_type_name (contour1), "GskCircleContour") == 0 &&
strcmp (gsk_contour_get_type_name (contour2), "GskCircleContour") == 0)
circle_contour_collect_intersections (contour1, contour2, pd);
else
default_contour_collect_intersections (contour1, contour2, pd);
}
static int
cmp_path1 (gconstpointer p1,
gconstpointer p2)
{
const Intersection *i1 = p1;
const Intersection *i2 = p2;
int i;
i = gsk_path_point_compare (&i1->point1, &i2->point1);
if (i != 0)
return i;
return gsk_path_point_compare (&i1->point2, &i2->point2);
}
static gboolean
contour_foreach_intersection (const GskContour *contour1,
PathIntersectData *pd)
{
GskBoundingBox b1, b2;
gsk_contour_get_bounds (contour1, &b1);
g_array_set_size (pd->all_points, 0);
for (gsize i = 0; i < gsk_path_get_n_contours (pd->path2); i++)
{
const GskContour *contour2 = gsk_path_get_contour (pd->path2, i);
gsk_contour_get_bounds (contour1, &b2);
if (gsk_bounding_box_intersection (&b1, &b2, NULL))
{
pd->contour2 = i;
pd->c2 = contour2;
pd->c2_count = count_curves (contour2, &pd->c2_closed, &pd->c2_z_is_empty);
contour_collect_intersections (contour1, contour2, pd);
}
}
g_array_sort (pd->all_points, cmp_path1);
#if 0
g_print ("after sorting\n");
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
for (gsize i = 0; i + 1 < pd->all_points->len; i++)
{
Intersection *is1 = &g_array_index (pd->all_points, Intersection, i);
Intersection *is2 = &g_array_index (pd->all_points, Intersection, i + 1);
if (gsk_path_point_equal (&is1->point1, &is2->point1) &&
gsk_path_point_equal (&is1->point2, &is2->point2))
{
if (is1->kind == GSK_PATH_INTERSECTION_END &&
is2->kind == GSK_PATH_INTERSECTION_START)
{
is1->kind = GSK_PATH_INTERSECTION_NONE;
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
else
{
is2->kind = MAX (is1->kind, is2->kind);
is1->kind = GSK_PATH_INTERSECTION_NONE;
}
}
}
g_print ("emitting\n");
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
if (is->kind != GSK_PATH_INTERSECTION_NONE)
{
if (!pd->func (pd->path1, &is->point1, pd->path2, &is->point2, is->kind, pd->data))
return FALSE;
}
}
return TRUE;
}
/**
* gsk_path_foreach_intersection:
* @path1: the first path
* @path2: the second path
* @func: (scope call) (closure user_data): the function to call for intersections
* @user_data: (nullable): user data passed to @func
*
* Finds intersections between two paths.
*
* This function finds intersections between @path1 and @path2,
* and calls @func for each of them, in increasing order for @path1.
*
* When segments of the paths coincide, the callback is called once
* for the start of the segment, with @GSK_PATH_INTERSECTION_START, and
* once for the end of the segment, with @GSK_PATH_INTERSECTION_END.
* Note that other intersections may occur between the start and end
* of such a segment.
*
* If @func returns `FALSE`, the iteration is stopped.
*
* Returns: `FALSE` if @func returned FALSE`, `TRUE` otherwise.
*
* Since: 4.14
*/
gboolean
gsk_path_foreach_intersection (GskPath *path1,
GskPath *path2,
GskPathIntersectionFunc func,
gpointer data)
{
PathIntersectData pd = {
.path1 = path1,
.path2 = path2,
.func = func,
.data = data,
};
gboolean ret;
pd.points = g_array_new (FALSE, FALSE, sizeof (Intersection));
pd.all_points = g_array_new (FALSE, FALSE, sizeof (Intersection));
ret = TRUE;
for (gsize i = 0; i < gsk_path_get_n_contours (path1); i++)
{
const GskContour *contour1 = gsk_path_get_contour (path1, i);
pd.contour1 = i;
pd.c1 = contour1;
pd.c1_count = count_curves (contour1, &pd.c1_closed, &pd.c1_z_is_empty);
pd.idx1 = 0;
if (!contour_foreach_intersection (contour1, &pd))
{
ret = FALSE;
break;
}
}
g_array_unref (pd.points);
g_array_unref (pd.all_points);
return ret;
}
/* vim:set foldmethod=marker expandtab: */
+1818
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -56,5 +56,19 @@ gboolean gsk_path_foreach_with_tolerance (GskPath
void gsk_path_builder_add_contour (GskPathBuilder *builder,
GskContour *contour);
typedef enum
{
GSK_PATH_OP_SIMPLIFY,
GSK_PATH_OP_UNION,
GSK_PATH_OP_INTERSECTION,
GSK_PATH_OP_DIFFERENCE,
GSK_PATH_OP_XOR
} GskPathOp;
GskPath * gsk_path_op (GskPathOp operation,
GskFillRule fill_rule,
GskPath *first,
GskPath *second);
G_END_DECLS
-19
View File
@@ -684,22 +684,3 @@ gsk_renderer_set_debug_flags (GskRenderer *renderer,
priv->debug_flags = flags;
}
/* Feed a texture through a renderer and return the resulting 'native' texture. */
GdkTexture *
gsk_renderer_convert_texture (GskRenderer *self,
GdkTexture *texture)
{
int width, height;
GskRenderNode *node;
GdkTexture *result;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
node = gsk_texture_node_new (texture, &GRAPHENE_RECT_INIT (0, 0, width, height));
result = gsk_renderer_render_texture (self, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_render_node_unref (node);
return result;
}
-3
View File
@@ -56,8 +56,5 @@ GskDebugFlags gsk_renderer_get_debug_flags (GskRenderer
void gsk_renderer_set_debug_flags (GskRenderer *renderer,
GskDebugFlags flags);
GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
GdkTexture *texture);
G_END_DECLS
+6 -11
View File
@@ -287,21 +287,15 @@ gsk_render_node_alloc (GskRenderNodeType node_type)
* Returns: (transfer full): the `GskRenderNode` with an additional reference
*/
GskRenderNode *
(gsk_render_node_ref) (GskRenderNode *node)
gsk_render_node_ref (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
return _gsk_render_node_ref (node);
}
g_atomic_ref_count_inc (&node->ref_count);
void
_gsk_render_node_unref (GskRenderNode *node)
{
if G_UNLIKELY (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
return node;
}
/**
* gsk_render_node_unref:
* @node: (transfer full): a `GskRenderNode`
@@ -312,11 +306,12 @@ _gsk_render_node_unref (GskRenderNode *node)
* freed.
*/
void
(gsk_render_node_unref) (GskRenderNode *node)
gsk_render_node_unref (GskRenderNode *node)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
_gsk_render_node_unref (node);
if (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
}
+30 -6
View File
@@ -33,7 +33,6 @@
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkmemoryformatprivate.h"
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssdataurlprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
@@ -3170,20 +3169,45 @@ append_texture_param (Printer *p,
g_hash_table_insert (p->named_textures, texture, new_name);
}
switch (gdk_memory_format_get_depth (gdk_texture_get_format (texture)))
switch (gdk_texture_get_format (texture))
{
case GDK_MEMORY_U8:
case GDK_MEMORY_U16:
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16:
case GDK_MEMORY_G8A8_PREMULTIPLIED:
case GDK_MEMORY_G8A8:
case GDK_MEMORY_G8:
case GDK_MEMORY_G16A16_PREMULTIPLIED:
case GDK_MEMORY_G16A16:
case GDK_MEMORY_G16:
case GDK_MEMORY_A8:
case GDK_MEMORY_A16:
bytes = gdk_texture_save_to_png_bytes (texture);
g_string_append (p->str, "url(\"data:image/png;base64,");
break;
case GDK_MEMORY_FLOAT16:
case GDK_MEMORY_FLOAT32:
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_FLOAT:
case GDK_MEMORY_A16_FLOAT:
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT:
case GDK_MEMORY_A32_FLOAT:
bytes = gdk_texture_save_to_tiff_bytes (texture);
g_string_append (p->str, "url(\"data:image/tiff;base64,");
break;
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
}
-14
View File
@@ -21,9 +21,6 @@ extern GType gsk_render_node_types[];
#define GSK_IS_RENDER_NODE_TYPE(node,type) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type == (type))
#define GSK_RENDER_NODE_TYPE(node) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type)
struct _GskRenderNode
{
GTypeInstance parent_instance;
@@ -60,8 +57,6 @@ GType gsk_render_node_type_register_static (const char
gpointer gsk_render_node_alloc (GskRenderNodeType node_type);
void _gsk_render_node_unref (GskRenderNode *node);
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
@@ -92,15 +87,6 @@ gboolean gsk_container_node_is_disjoint (const GskRenderNode
gboolean gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
#define gsk_render_node_ref(node) _gsk_render_node_ref(node)
#define gsk_render_node_unref(node) _gsk_render_node_unref(node)
static inline GskRenderNode *
_gsk_render_node_ref (GskRenderNode *node)
{
g_atomic_ref_count_inc (&node->ref_count);
return node;
}
G_END_DECLS
+3 -1
View File
@@ -20,7 +20,6 @@ gsk_private_gl_shaders = [
'gl/resources/custom.glsl',
'gl/resources/filled_border.glsl',
'gl/resources/mask.glsl',
'gl/resources/external.glsl',
]
gsk_public_sources = files([
@@ -29,7 +28,9 @@ gsk_public_sources = files([
'gskglshader.c',
'gskpath.c',
'gskpathbuilder.c',
'gskpathintersect.c',
'gskpathmeasure.c',
'gskpathops.c',
'gskpathparser.c',
'gskpathpoint.c',
'gskrenderer.c',
@@ -46,6 +47,7 @@ gsk_private_sources = files([
'gskcairoblur.c',
'gskcontour.c',
'gskcurve.c',
'gskcurveintersect.c',
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
-25
View File
@@ -80,15 +80,6 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
return info;
}
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8A8:
{
static const GskMemoryFormatInfo info[] = {
@@ -126,17 +117,6 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
return info;
}
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
@@ -344,7 +324,6 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
@@ -352,10 +331,6 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
case GDK_MEMORY_R8G8B8:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
case GDK_MEMORY_B8G8R8:
return GDK_MEMORY_R8G8B8;
+1 -3
View File
@@ -714,9 +714,7 @@ emit_text_changed (GtkAtSpiContext *self,
"org.a11y.atspi.Event.Object",
"TextChanged",
g_variant_new ("(siiva{sv})",
kind, start, end,
g_variant_new_string (text),
NULL),
kind, start, end, g_variant_new_string (text), NULL),
NULL);
}
+3 -12
View File
@@ -1614,10 +1614,7 @@ insert_text_cb (GtkEditable *editable,
return;
length = g_utf8_strlen (new_text, new_text_length);
char *inserted_text = g_utf8_substring (new_text, 0, length);
changed->text_changed (changed->data, "insert", *position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", *position - length, length, new_text);
}
static void
@@ -1632,10 +1629,6 @@ delete_text_cb (GtkEditable *editable,
return;
text = gtk_editable_get_chars (editable, start, end);
if (end < 0)
end = g_utf8_strlen(text, -1);
changed->text_changed (changed->data, "delete", start, end - start, text);
g_free (text);
}
@@ -1714,9 +1707,7 @@ insert_range_cb (GtkTextBuffer *buffer,
position = gtk_text_iter_get_offset (iter);
length = g_utf8_strlen (text, len);
char *inserted_text = g_utf8_substring (text, 0, length);
changed->text_changed (changed->data, "insert", position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", position - length, length, text);
update_cursor (buffer, changed);
}
@@ -1793,7 +1784,7 @@ buffer_changed (GtkWidget *widget,
if (changed->buffer)
{
g_object_ref (changed->buffer);
g_signal_connect_after (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "delete-range", G_CALLBACK (delete_range_cb), changed);
g_signal_connect_after (changed->buffer, "delete-range", G_CALLBACK (delete_range_after_cb), changed);
g_signal_connect_after (changed->buffer, "mark-set", G_CALLBACK (mark_set_cb), changed);
-3
View File
@@ -171,9 +171,6 @@ gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
case GTK_ACCESSIBLE_ROLE_OPTION:
return ATSPI_ROLE_OPTION_PANE;
case GTK_ACCESSIBLE_ROLE_PARAGRAPH:
return ATSPI_ROLE_PARAGRAPH;
case GTK_ACCESSIBLE_ROLE_PRESENTATION:
return ATSPI_ROLE_INVALID;
+2 -4
View File
@@ -454,8 +454,7 @@ gtk_dialog_constructed (GObject *object)
}
g_list_free (children);
if (GTK_IS_HEADER_BAR (priv->headerbar))
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
}
else
{
@@ -1398,8 +1397,7 @@ gtk_dialog_buildable_add_child (GtkBuildable *buildable,
else if (g_str_equal (type, "titlebar"))
{
priv->headerbar = GTK_WIDGET (child);
if (GTK_IS_HEADER_BAR (priv->headerbar))
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
gtk_window_set_titlebar (GTK_WINDOW (buildable), priv->headerbar);
}
else if (g_str_equal (type, "action"))
+2 -5
View File
@@ -12833,12 +12833,9 @@ gtk_tree_view_is_blank_at_pos (GtkTreeView *tree_view,
*column = real_column;
gtk_tree_model_get_iter (priv->model, &iter, real_path);
_gtk_tree_view_find_node (tree_view, real_path, &tree, &node);
if (node == NULL)
if (!_gtk_tree_view_find_node (tree_view, real_path, &tree, &node))
{
if (!path)
gtk_tree_path_free (real_path);
return TRUE;
g_assert_not_reached ();
}
/* Check if there's an expander arrow at (x, y) */
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More