Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 08b786a984 | |||
| 54bf63259c | |||
| 53b5441e39 | |||
| 3b2ab7ad1e | |||
| 42eaacbab4 | |||
| 6a1660b78e | |||
| 821fc35941 | |||
| af0492ed0c | |||
| dcdbb73702 | |||
| 60b2cf5d4a | |||
| 2fcb20cc4a | |||
| 89567767c5 | |||
| 6577f386b0 | |||
| 6ce8bd6581 |
+5
-12
@@ -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,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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -86,8 +86,6 @@ struct _GdkWaylandSurface
|
||||
uint32_t last_configure_serial;
|
||||
|
||||
int state_freeze_count;
|
||||
|
||||
GPtrArray *subsurfaces;
|
||||
};
|
||||
|
||||
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¢er1, &radius1, &ccw1);
|
||||
gsk_circle_contour_get_params (contour2, ¢er2, &radius2, &ccw2);
|
||||
|
||||
if (graphene_point_equal (¢er1, ¢er2) && 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 (¢er1, radius1, ¢er2, 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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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) */
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user