Compare commits
166 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b6f479375e | |||
| 9e3f537a15 | |||
| 612e0e29f9 | |||
| e1cbc96b8c | |||
| 410240fe7b | |||
| 73cf3a92f9 | |||
| dd15122ccb | |||
| 5299f1384f | |||
| 58a0e4ffaa | |||
| 7ab9056c11 | |||
| 2d9fbb16bc | |||
| cbfd8542c6 | |||
| 7679504134 | |||
| 446d461ad2 | |||
| 5b6fcfe8c9 | |||
| 59ce7ab222 | |||
| 0992837b08 | |||
| aca02916ad | |||
| 98e883f9b4 | |||
| 2c66aa0c15 | |||
| 8843c0d504 | |||
| 8858f1c9ec | |||
| a1c5c20e2c | |||
| 1da674423d | |||
| 10250a0a6a | |||
| c0a2f9fbc3 | |||
| bd974b08b3 | |||
| d289c0d4f1 | |||
| f4722289f7 | |||
| 389af3591c | |||
| 008d9e5327 | |||
| 09723d79c6 | |||
| 4586af5876 | |||
| 193d9cd31a | |||
| f29303dea7 | |||
| 4e47d0d71e | |||
| dd8c6e9f51 | |||
| 65676150c4 | |||
| b0e26873f6 | |||
| f4a67ebcbb | |||
| 000c876953 | |||
| b8ffceaebb | |||
| 148b8e5cd8 | |||
| 583ad47b03 | |||
| b95d8ebdd3 | |||
| 677a601d11 | |||
| 194db51fba | |||
| d55fa0dfef | |||
| 612b5416af | |||
| 54637ae3b3 | |||
| 014adb841e | |||
| a5c6a40b3c | |||
| 402a51b876 | |||
| d1e091279c | |||
| 7325121c63 | |||
| 31abe56b7a | |||
| ca3fd16039 | |||
| 4417509515 | |||
| 9dc2e554e5 | |||
| bfb01f5a4b | |||
| 570e80a9ff | |||
| 6d90d25a74 | |||
| a7f6e65291 | |||
| 59641b3c7b | |||
| 2f842b087c | |||
| 699f6a7993 | |||
| f04ba3bc60 | |||
| 09aac114d4 | |||
| 9132600e1f | |||
| 5dcd6c7e12 | |||
| 9f8d34ab01 | |||
| 7a4580fa89 | |||
| 45a7617cc8 | |||
| 57d8cc08a3 | |||
| 1ca067a478 | |||
| 7a13e4f9b9 | |||
| d101e17608 | |||
| 203a4fc45e | |||
| a9823e05bb | |||
| 6f5833df28 | |||
| 5631ab6711 | |||
| 62fedf4eed | |||
| c274d073e0 | |||
| 8dda753505 | |||
| 4e66df79c4 | |||
| 71c7e61162 | |||
| e39ecbf16d | |||
| 0dbd2bd09e | |||
| 1297cc188d | |||
| e584d17aad | |||
| 4936965fb6 | |||
| e9cc53796e | |||
| c93efe85dd | |||
| 44daa847ff | |||
| d23e13aced | |||
| 40102a2b61 | |||
| 49fbbfb6cc | |||
| fefd856d67 | |||
| 39dab6d7bd | |||
| 7b5b78b065 | |||
| 005b5042f6 | |||
| b5149a483f | |||
| 15c43e5284 | |||
| fc4c0f769c | |||
| e8ecbb2009 | |||
| 964affb1cc | |||
| 05b51af2d5 | |||
| 28e51c763b | |||
| ebf8e18319 | |||
| d8bbe1c296 | |||
| c1417d3d4a | |||
| 3b4359d76d | |||
| 16806294e3 | |||
| 822425072b | |||
| 7cc1283a26 | |||
| f4198706d1 | |||
| 8478ba66fe | |||
| 1d58de6ffb | |||
| f5cec5c0f2 | |||
| 368f2af634 | |||
| 66a9fee071 | |||
| 6e0ac83d99 | |||
| 12ad6b3157 | |||
| fda9fd5ced | |||
| 029ce83a69 | |||
| 5ced6be416 | |||
| bbda833b01 | |||
| c86bc00330 | |||
| 68755c0fd2 | |||
| 9090c28125 | |||
| 3a3244891e | |||
| b55117334c | |||
| 02e5c7b9ad | |||
| 7268167f4c | |||
| 93c7502cf7 | |||
| 789705cfe4 | |||
| 741471a1f8 | |||
| f8da751cc2 | |||
| 8174842d9f | |||
| e872952f36 | |||
| b010e46d13 | |||
| eb646a8e8b | |||
| 1e2975147d | |||
| 653c10e8b6 | |||
| dfbafdf047 | |||
| d8c821a851 | |||
| 83376648d7 | |||
| 089c34fa03 | |||
| c846f8d745 | |||
| 79ebd76ac8 | |||
| 6eb9836eb0 | |||
| 4a8f8a6eea | |||
| 3ea723730b | |||
| 90be2baf8b | |||
| 0b64fa88a1 | |||
| c6cc446e63 | |||
| 0cad37760e | |||
| e720008dca | |||
| 9c636a6136 | |||
| 1e24aa425e | |||
| a8c597005a | |||
| 97a781b380 | |||
| 313cadefe6 | |||
| 9f078bd5c9 | |||
| 4c46f5a8f7 | |||
| 5c00dc7ef4 |
+12
-5
@@ -217,25 +217,32 @@ 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
|
||||
- python3 -m venv .venv
|
||||
- /opt/macports/bin/python3.10 -m venv .venv
|
||||
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
|
||||
- ln -s /opt/ccache/ccache .venv/bin
|
||||
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
|
||||
- ln -s /opt/bison/bin/bison .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}
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
-Dx11-backend=false
|
||||
-Dbroadway-backend=true
|
||||
-Dmacos-backend=true
|
||||
-Dmedia-gstreamer=disabled
|
||||
-Dintrospection=disabled
|
||||
-Dintrospection=enabled
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
-Dlibjpeg-turbo:simd=disabled
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
Overview of Changes in 4.13.1, xx-xx-xxxx
|
||||
Overview of Changes in 4.13.2, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.13.1, 28-09-2023
|
||||
=========================================
|
||||
|
||||
* GtkTooltip:
|
||||
@@ -7,20 +10,32 @@ Overview of Changes in 4.13.1, xx-xx-xxxx
|
||||
* 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
|
||||
@@ -29,6 +44,13 @@ Overview of Changes in 4.13.1, xx-xx-xxxx
|
||||
- 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
|
||||
@@ -43,20 +65,29 @@ Overview of Changes in 4.13.1, xx-xx-xxxx
|
||||
* 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
|
||||
|
||||
@@ -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 = g_get_monotonic_time ();
|
||||
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
gtk_widget_queue_allocate (widget);
|
||||
|
||||
@@ -66,11 +66,13 @@ clicked (GtkGestureClick *gesture,
|
||||
gpointer data)
|
||||
{
|
||||
DemoWidget *self = data;
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
if (self->tick_id != 0)
|
||||
return;
|
||||
|
||||
self->start_time = g_get_monotonic_time ();
|
||||
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
|
||||
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
*
|
||||
* 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"
|
||||
|
||||
@@ -165,6 +168,89 @@ 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)
|
||||
{
|
||||
@@ -172,12 +258,21 @@ 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), TRUE);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
|
||||
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 ();
|
||||
@@ -186,6 +281,8 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* Pickers and Launchers
|
||||
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
|
||||
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkPrintDialog, GtkFileLauncher, GtkUriLauncher
|
||||
*
|
||||
* The dialogs are mainly intended for use in preference dialogs.
|
||||
* They allow to select colors, fonts and applications.
|
||||
* They allow to select colors, fonts and files. There is also a
|
||||
* print dialog.
|
||||
*
|
||||
* The launchers let you open files or URIs in applications that
|
||||
* can handle them.
|
||||
@@ -11,11 +12,13 @@
|
||||
#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)
|
||||
@@ -31,6 +34,13 @@ 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
|
||||
@@ -47,6 +57,10 @@ 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);
|
||||
@@ -114,6 +128,53 @@ 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,
|
||||
@@ -234,8 +295,14 @@ 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);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
||||
|
||||
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);
|
||||
|
||||
@@ -170,35 +170,41 @@ 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`.
|
||||
|
||||
`cursor`
|
||||
: Information about cursor objects (only win32)
|
||||
`misc`
|
||||
: Miscellaneous information
|
||||
|
||||
`events`
|
||||
: Information about events
|
||||
|
||||
`dnd`
|
||||
: Information about drag-and-drop
|
||||
|
||||
`input`
|
||||
: Information about input (mostly Windows)
|
||||
|
||||
`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
|
||||
|
||||
`dnd`
|
||||
: Information about drag-and-drop
|
||||
|
||||
`opengl`
|
||||
: Information about OpenGL
|
||||
|
||||
`vulkan`
|
||||
: Information about Vulkan
|
||||
`dmabuf`
|
||||
: Information about dmabuf handling (Linux-only)
|
||||
|
||||
A number of options affect behavior instead of logging:
|
||||
|
||||
@@ -217,6 +223,9 @@ 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
|
||||
|
||||
@@ -244,6 +253,12 @@ 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,6 +117,8 @@ 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 },
|
||||
@@ -133,6 +135,7 @@ 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 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
#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>
|
||||
|
||||
+7
-1
@@ -183,7 +183,7 @@ gdk_array(reserve) (GdkArray *self,
|
||||
return;
|
||||
|
||||
size = gdk_array(get_size) (self);
|
||||
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
|
||||
new_size = ((gsize) 1) << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start == self->preallocated)
|
||||
@@ -215,7 +215,11 @@ 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;
|
||||
@@ -318,3 +322,5 @@ gdk_array(get) (const GdkArray *self,
|
||||
#undef GDK_ARRAY_TYPE_NAME
|
||||
#undef GDK_ARRAY_NO_MEMSET
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+19
-16
@@ -36,23 +36,26 @@ 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 << 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,
|
||||
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,
|
||||
} GdkDebugFlags;
|
||||
|
||||
extern guint _gdk_debug_flags;
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
#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"
|
||||
@@ -69,6 +72,7 @@ enum
|
||||
PROP_COMPOSITED,
|
||||
PROP_RGBA,
|
||||
PROP_INPUT_SHAPES,
|
||||
PROP_DMABUF_FORMATS,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
@@ -138,6 +142,10 @@ 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);
|
||||
}
|
||||
@@ -239,6 +247,11 @@ 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);
|
||||
|
||||
/**
|
||||
@@ -404,6 +417,8 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1824,6 +1839,76 @@ gdk_display_get_egl_display (GdkDisplay *self)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
static void
|
||||
gdk_display_add_dmabuf_downloader (GdkDisplay *display,
|
||||
const GdkDmabufDownloader *downloader,
|
||||
GdkDmabufFormatsBuilder *builder)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
downloader->add_formats (downloader, display, builder);
|
||||
|
||||
/* 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;
|
||||
|
||||
builder = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
if (!GDK_DEBUG_CHECK (DMABUF_DISABLE))
|
||||
{
|
||||
gdk_display_prepare_gl (self, NULL);
|
||||
|
||||
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_direct_downloader (), builder);
|
||||
}
|
||||
#endif
|
||||
|
||||
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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,6 +134,10 @@ 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,6 +25,7 @@
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
@@ -113,6 +114,9 @@ struct _GdkDisplay
|
||||
guint have_egl_buffer_age : 1;
|
||||
guint have_egl_no_config_context : 1;
|
||||
guint have_egl_pixel_format_float : 1;
|
||||
|
||||
GdkDmabufFormats *dmabuf_formats;
|
||||
const GdkDmabufDownloader *dmabuf_downloaders[4];
|
||||
};
|
||||
|
||||
struct _GdkDisplayClass
|
||||
@@ -207,6 +211,8 @@ 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);
|
||||
|
||||
|
||||
+602
@@ -0,0 +1,602 @@
|
||||
/* 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_LINUX_DMA_BUF_H
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/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;
|
||||
|
||||
if (dmabuf->fourcc == DRM_FORMAT_NV21)
|
||||
{
|
||||
U = 1; V = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
U = 0; V = 1;
|
||||
}
|
||||
|
||||
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 + 1) / 2 * uv_stride);
|
||||
|
||||
for (y = 0; y < height; y += 2)
|
||||
{
|
||||
guchar *dst2_data = dst_data + dst_stride;
|
||||
const guchar *y2_data = y_data + y_stride;
|
||||
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
get_uv_values (&itu601_wide, uv_data[x + U], uv_data[x + V], &r, &g, &b);
|
||||
|
||||
set_rgb_values (&dst_data[3 * x], y_data[x], r, g, b);
|
||||
if (x + 1 < width)
|
||||
set_rgb_values (&dst_data[3 * (x + 1)], y_data[x], r, g, b);
|
||||
if (y + 1 < height)
|
||||
{
|
||||
set_rgb_values (&dst2_data[3 * x], y2_data[x], r, g, b);
|
||||
if (x + 1 < width)
|
||||
set_rgb_values (&dst2_data[3 * (x + 1)], y2_data[x], r, g, b);
|
||||
}
|
||||
}
|
||||
dst_data += 2 * dst_stride;
|
||||
y_data += 2 * y_stride;
|
||||
uv_data += uv_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_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 },
|
||||
};
|
||||
|
||||
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 void
|
||||
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_dmabuf_formats_builder_add_format (builder,
|
||||
supported_formats[i].fourcc,
|
||||
DRM_FORMAT_MOD_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
char buf[36];
|
||||
|
||||
info = get_drm_format_info (dmabuf->fourcc);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"Unsupported dmabuf format %s",
|
||||
gdk_dmabuf_fourcc_print (buf, sizeof (buf), 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 %s (only linear buffers are supported)",
|
||||
gdk_dmabuf_modifier_print (buf, sizeof (buf), 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;
|
||||
gchar buf[64];
|
||||
|
||||
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 %s)",
|
||||
gdk_dmabuf_format_print (buf, sizeof (buf), 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;
|
||||
}
|
||||
|
||||
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. Treat the INVALID modifier the same as LINEAR.
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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 && src->modifier != DRM_FORMAT_MOD_INVALID)
|
||||
return TRUE;
|
||||
|
||||
switch (dest->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_NV12:
|
||||
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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_dmabuf_fourcc_print (char *buf,
|
||||
gsize size,
|
||||
guint32 fourcc)
|
||||
{
|
||||
snprintf (buf, size, "%.4s", (char *)&fourcc);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_modifier_name (char *buf,
|
||||
gsize size,
|
||||
guint64 modifier)
|
||||
{
|
||||
static struct {
|
||||
guchar id;
|
||||
const char *name;
|
||||
} vendors[] = {
|
||||
{ DRM_FORMAT_MOD_VENDOR_NONE, "NONE" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_INTEL, "Intel" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_AMD, "AMD" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_NVIDIA, "NVidia" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_SAMSUNG, "Samsung" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_QCOM, "Qualcomm" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_VIVANTE, "Vivante" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_BROADCOM, "Broadcom" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_ARM, "Arm" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_ALLWINNER, "Allwinner" },
|
||||
{ DRM_FORMAT_MOD_VENDOR_AMLOGIC, "Amlogic" },
|
||||
};
|
||||
|
||||
if (modifier == DRM_FORMAT_MOD_INVALID)
|
||||
return "INVALID";
|
||||
else if (modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
return "LINEAR";
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (vendors); i++)
|
||||
{
|
||||
if (vendors[i].id == fourcc_mod_get_vendor (modifier))
|
||||
{
|
||||
snprintf (buf, size, "%s,%" G_GINT64_MODIFIER "u", vendors[i].name, modifier & 0x00ffffffffffffffUL);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf (buf, size, "%#" G_GINT64_MODIFIER "x", modifier);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_dmabuf_modifier_print (char *buf,
|
||||
gsize size,
|
||||
guint64 modifier)
|
||||
{
|
||||
char buf2[64];
|
||||
|
||||
snprintf (buf, size, "%s", get_modifier_name (buf2, sizeof (buf2), modifier));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_dmabuf_format_print (char *buf,
|
||||
gsize size,
|
||||
guint32 fourcc,
|
||||
guint64 modifier)
|
||||
{
|
||||
gsize len;
|
||||
char buf2[64];
|
||||
|
||||
gdk_dmabuf_fourcc_print (buf, size, fourcc);
|
||||
len = strlen (buf);
|
||||
|
||||
snprintf (buf + len, size - len, ":%s", get_modifier_name (buf2, sizeof (buf2), modifier));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LINUX_DMA_BUF_H */
|
||||
@@ -0,0 +1,215 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* 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
|
||||
@@ -0,0 +1,133 @@
|
||||
/* 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"
|
||||
|
||||
#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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#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);
|
||||
@@ -0,0 +1,15 @@
|
||||
#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);
|
||||
@@ -0,0 +1,63 @@
|
||||
#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;
|
||||
void (* 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_LINUX_DMA_BUF_H
|
||||
const GdkDmabufDownloader *
|
||||
gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
|
||||
|
||||
gboolean gdk_dmabuf_sanitize (GdkDmabuf *dest,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *src,
|
||||
GError **error);
|
||||
|
||||
const char * gdk_dmabuf_fourcc_print (char *str,
|
||||
gsize size,
|
||||
guint32 fourcc);
|
||||
const char * gdk_dmabuf_modifier_print (char *str,
|
||||
gsize size,
|
||||
guint64 modifier);
|
||||
const char * gdk_dmabuf_format_print (char *str,
|
||||
gsize size,
|
||||
guint32 fourcc,
|
||||
guint64 modifier);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,219 @@
|
||||
/* 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_LINUX_DMA_BUF_H
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/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_LINUX_DMA_BUF_H
|
||||
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_LINUX_DMA_BUF_H */
|
||||
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
|
||||
"dmabuf support disabled at compile-time.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* 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
|
||||
@@ -0,0 +1,993 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdmabuftexturebuilder.h"
|
||||
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
|
||||
struct _GdkDmabufTextureBuilder
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkDisplay *display;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
gboolean premultiplied;
|
||||
|
||||
GdkDmabuf dmabuf;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
};
|
||||
|
||||
struct _GdkDmabufTextureBuilderClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:
|
||||
*
|
||||
* `GdkDmabufTextureBuilder` is a builder used to construct [class@Gdk.Texture]
|
||||
* objects from DMA buffers.
|
||||
*
|
||||
* DMA buffers are commonly called **_dma-bufs_**.
|
||||
*
|
||||
* DMA buffers a feature of the Linux kernel to enable efficient buffer and
|
||||
* memory sharing between hardware such as codecs, GPUs, displays, cameras and the
|
||||
* kernel drivers controlling them. For example, a decoder may want its output to
|
||||
* be directly shared with the display server for rendering without a copy.
|
||||
*
|
||||
* Any device driver which participates in DMA buffer sharing, can do so as either
|
||||
* the exporter or importer of buffers (or both).
|
||||
*
|
||||
* The memory that is shared via DMA buffers is usually stored in non-system memory
|
||||
* (maybe in device's local memory or something else not directly accessible by the
|
||||
* CPU), and accessing this memory from the CPU may have higher than usual overhead.
|
||||
*
|
||||
* In particular for graphics data, it is not uncommon that data consists of multiple
|
||||
* separate blocks of memory, for example one block for each of the red, green and
|
||||
* blue channels. These blocks are called **_planes_**. DMA buffers can have up to
|
||||
* four planes. Even if the memory is a single block, the data can be organized in
|
||||
* multiple planes, by specifying offsets from the beginning of the data.
|
||||
*
|
||||
* DMA buffers are exposed to user-space as file descriptors allowing to pass them
|
||||
* between processes. If a DMA buffer has multiple planes, there is one file
|
||||
* descriptor per plane.
|
||||
*
|
||||
* The format of the data (for graphics data, essentially its colorspace) is described
|
||||
* by a 32-bit integer. These format identifiers are defined in the header file
|
||||
* [drm/drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm/drm_fourcc.h)
|
||||
* and commonly referred to as **_fourcc_** values, since they are identified by 4 ASCII
|
||||
* characters. Additionally, each DMA buffer has a **_modifier_**, which is a 64-bit integer
|
||||
* that describes driver-specific details of the memory layout, such as tiling or compression.
|
||||
*
|
||||
* The operation of `GdkDmabufTextureBuilder` is quite simple: Create a texture builder,
|
||||
* set all the necessary properties, and then call [method@Gdk.DmabufTextureBuilder.build]
|
||||
* to create the new texture.
|
||||
*
|
||||
* The required properties for a dma-buf texture are
|
||||
* - The width and height in pixels
|
||||
* - The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
|
||||
* - The file descriptor, offset and stride for each of the planes
|
||||
*
|
||||
* `GdkDmabufTextureBuilder` can be used for quick one-shot construction of
|
||||
* textures as well as kept around and reused to construct multiple textures.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DISPLAY,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_FOURCC,
|
||||
PROP_MODIFIER,
|
||||
PROP_PREMULTIPLIED,
|
||||
PROP_N_PLANES,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, G_TYPE_OBJECT)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gdk_dmabuf_texture_builder_dispose (GObject *object)
|
||||
{
|
||||
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gdk_dmabuf_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_texture_builder_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, self->display);
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
g_value_set_uint (value, self->width);
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
g_value_set_uint (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_FOURCC:
|
||||
g_value_set_uint (value, self->dmabuf.fourcc);
|
||||
break;
|
||||
|
||||
case PROP_MODIFIER:
|
||||
g_value_set_uint64 (value, self->dmabuf.modifier);
|
||||
break;
|
||||
|
||||
case PROP_PREMULTIPLIED:
|
||||
g_value_set_boolean (value, self->premultiplied);
|
||||
break;
|
||||
|
||||
case PROP_N_PLANES:
|
||||
g_value_set_uint (value, self->dmabuf.n_planes);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
g_value_set_object (value, self->update_texture);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_texture_builder_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
gdk_dmabuf_texture_builder_set_display (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
gdk_dmabuf_texture_builder_set_width (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
gdk_dmabuf_texture_builder_set_height (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_FOURCC:
|
||||
gdk_dmabuf_texture_builder_set_fourcc (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_MODIFIER:
|
||||
gdk_dmabuf_texture_builder_set_modifier (self, g_value_get_uint64 (value));
|
||||
break;
|
||||
|
||||
case PROP_PREMULTIPLIED:
|
||||
gdk_dmabuf_texture_builder_set_premultiplied (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_N_PLANES:
|
||||
gdk_dmabuf_texture_builder_set_n_planes (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_dmabuf_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
gdk_dmabuf_texture_builder_set_update_texture (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_texture_builder_class_init (GdkDmabufTextureBuilderClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gdk_dmabuf_texture_builder_dispose;
|
||||
gobject_class->get_property = gdk_dmabuf_texture_builder_get_property;
|
||||
gobject_class->set_property = gdk_dmabuf_texture_builder_set_property;
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:display: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_display org.gdk.Property.set=gdk_dmabuf_texture_builder_set_display)
|
||||
*
|
||||
* The display that this texture will be used on.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display", NULL, NULL,
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:width: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_width org.gdk.Property.set=gdk_dmabuf_texture_builder_set_width)
|
||||
*
|
||||
* The width of the texture.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_WIDTH] =
|
||||
g_param_spec_uint ("width", NULL, NULL,
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:height: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_height org.gdk.Property.set=gdk_dmabuf_texture_builder_set_height)
|
||||
*
|
||||
* The height of the texture.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_HEIGHT] =
|
||||
g_param_spec_uint ("height", NULL, NULL,
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:fourcc: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_fourcc org.gdk.Property.set=gdk_dmabuf_texture_builder_set_fourcc)
|
||||
*
|
||||
* The format of the texture, as a fourcc value.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_FOURCC] =
|
||||
g_param_spec_uint ("fourcc", NULL, NULL,
|
||||
0, 0xffffffff, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:modifier:
|
||||
*
|
||||
* The modifier.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_MODIFIER] =
|
||||
g_param_spec_uint64 ("modifier", NULL, NULL,
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:premultiplied:
|
||||
*
|
||||
* Whether the alpha channel is premultiplied into the others.
|
||||
*
|
||||
* Only relevant if the format has alpha.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_PREMULTIPLIED] =
|
||||
g_param_spec_boolean ("premultiplied", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:n-planes: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_n_planes org.gdk.Property.set=gdk_dmabuf_texture_builder_set_n_planes)
|
||||
*
|
||||
* The number of planes of the texture.
|
||||
*
|
||||
* Note that you can set properties for other planes,
|
||||
* but they will be ignored when constructing the texture.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_N_PLANES] =
|
||||
g_param_spec_uint ("n-planes", NULL, NULL,
|
||||
1, GDK_DMABUF_MAX_PLANES, 1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:update-region: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_update_region org.gdk.Property.set=gdk_dmabuf_texture_builder_set_update_region)
|
||||
*
|
||||
* The update region for [property@Gdk.GLTextureBuilder:update-texture].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_UPDATE_REGION] =
|
||||
g_param_spec_boxed ("update-region", NULL, NULL,
|
||||
CAIRO_GOBJECT_TYPE_REGION,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:update-texture: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_update_texture org.gdk.Property.set=gdk_dmabuf_texture_builder_set_update_texture)
|
||||
*
|
||||
* The texture [property@Gdk.GLTextureBuilder:update-region] is an update for.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_UPDATE_TEXTURE] =
|
||||
g_param_spec_object ("update-texture", NULL, NULL,
|
||||
GDK_TYPE_TEXTURE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_texture_builder_init (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
self->premultiplied = TRUE;
|
||||
self->display = gdk_display_get_default ();
|
||||
self->dmabuf.n_planes = 1;
|
||||
|
||||
for (int i = 0; i < GDK_DMABUF_MAX_PLANES; i++)
|
||||
self->dmabuf.planes[i].fd = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_new: (constructor):
|
||||
*
|
||||
* Creates a new texture builder.
|
||||
*
|
||||
* Returns: the new `GdkTextureBuilder`
|
||||
*
|
||||
* Since: 4.14
|
||||
**/
|
||||
GdkDmabufTextureBuilder *
|
||||
gdk_dmabuf_texture_builder_new (void)
|
||||
{
|
||||
return g_object_new (GDK_TYPE_DMABUF_TEXTURE_BUILDER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_display:
|
||||
* @self: a `GdkDmabufTextureBuilder
|
||||
*
|
||||
* Returns the display that this texture builder is
|
||||
* associated with.
|
||||
*
|
||||
* Returns: (transfer none): the display
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
GdkDisplay *
|
||||
gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->display;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_display:
|
||||
* @self: a `GdkDmabufTextureBuilder
|
||||
* @display: the display
|
||||
*
|
||||
* Sets the display that this texture builder is
|
||||
* associated with.
|
||||
*
|
||||
* The display is used to determine the supported
|
||||
* dma-buf formats.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
|
||||
GdkDisplay *display)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (g_set_object (&self->display, display))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DISPLAY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_width: (attributes org.gdk.Method.get_property=width)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the width previously set via gdk_dmabuf_texture_builder_set_width() or
|
||||
* 0 if the width wasn't set.
|
||||
*
|
||||
* Returns: The width
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
unsigned int
|
||||
gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_width: (attributes org.gdk.Method.set_property=width)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @width: The texture's width or 0 to unset
|
||||
*
|
||||
* Sets the width of the texture.
|
||||
*
|
||||
* The width must be set before calling [method@Gdk.GLTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
|
||||
unsigned int width)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->width == width)
|
||||
return;
|
||||
|
||||
self->width = width;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WIDTH]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_height: (attributes org.gdk.Method.get_property=height)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the height previously set via gdk_dmabuf_texture_builder_set_height() or
|
||||
* 0 if the height wasn't set.
|
||||
*
|
||||
* Returns: The height
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
unsigned int
|
||||
gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_height: (attributes org.gdk.Method.set_property=height)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @height: the texture's height or 0 to unset
|
||||
*
|
||||
* Sets the height of the texture.
|
||||
*
|
||||
* The height must be set before calling [method@Gdk.GLTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
|
||||
unsigned int height)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->height == height)
|
||||
return;
|
||||
|
||||
self->height = height;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEIGHT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_fourcc: (attributes org.gdk.Method.get_property=fourcc)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the format previously set via gdk_dmabuf_texture_builder_set_fourcc()
|
||||
* or 0 if the format wasn't set.
|
||||
*
|
||||
* The format is specified as a fourcc code.
|
||||
*
|
||||
* Returns: The format
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
guint32
|
||||
gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->dmabuf.fourcc;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_fourcc: (attributes org.gdk.Method.set_property=fourcc)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @fourcc: the texture's format or 0 to unset
|
||||
*
|
||||
* Sets the format of the texture.
|
||||
*
|
||||
* The format is specified as a fourcc code.
|
||||
*
|
||||
* The format must be set before calling [method@Gdk.GLTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
|
||||
guint32 fourcc)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->dmabuf.fourcc == fourcc)
|
||||
return;
|
||||
|
||||
self->dmabuf.fourcc = fourcc;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FOURCC]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_modifier:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the modifier value.
|
||||
*
|
||||
* Returns: the modifier
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
guint64
|
||||
gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->dmabuf.modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_modifier:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @modifier: the modifier value
|
||||
*
|
||||
* Sets the modifier.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
|
||||
guint64 modifier)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->dmabuf.modifier == modifier)
|
||||
return;
|
||||
|
||||
self->dmabuf.modifier = modifier;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODIFIER]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_n_planes: (attributes org.gdk.Method.get_property=n-planes)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the number of planes.
|
||||
*
|
||||
* Returns: The number of planes
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
unsigned int
|
||||
gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->dmabuf.n_planes;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_premultiplied:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Whether the data is premultiplied.
|
||||
*
|
||||
* Returns: whether the data is premultiplied
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gdk_dmabuf_texture_builder_get_premultiplied (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), TRUE);
|
||||
|
||||
return self->premultiplied;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_premultiplied:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @premultiplied: whether the data is premultiplied
|
||||
*
|
||||
* Sets whether the data is premultiplied.
|
||||
*
|
||||
* Unless otherwise specified, all formats including alpha channels are assumed
|
||||
* to be premultiplied.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_premultiplied (GdkDmabufTextureBuilder *self,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->premultiplied == premultiplied)
|
||||
return;
|
||||
|
||||
self->premultiplied = premultiplied;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PREMULTIPLIED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_n_planes: (attributes org.gdk.Method.set_property=n-planes)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @n_planes: the number of planes
|
||||
*
|
||||
* Sets the number of planes of the texture.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
|
||||
unsigned int n_planes)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (n_planes > 0 && n_planes <= GDK_DMABUF_MAX_PLANES);
|
||||
|
||||
if (self->dmabuf.n_planes == n_planes)
|
||||
return;
|
||||
|
||||
self->dmabuf.n_planes = n_planes;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_PLANES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_fd:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to get the fd for
|
||||
*
|
||||
* Gets the file descriptor for a plane.
|
||||
*
|
||||
* Returns: the file descriptor
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
int
|
||||
gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
|
||||
|
||||
return self->dmabuf.planes[plane].fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_fd:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to set the fd for
|
||||
* @fd: the file descriptor
|
||||
*
|
||||
* Sets the file descriptor for a plane.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane,
|
||||
int fd)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
|
||||
|
||||
if (self->dmabuf.planes[plane].fd == fd)
|
||||
return;
|
||||
|
||||
self->dmabuf.planes[plane].fd = fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_stride:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to get the stride for
|
||||
*
|
||||
* Gets the stride value for a plane.
|
||||
*
|
||||
* Returns: the stride
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
unsigned int
|
||||
gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
|
||||
|
||||
return self->dmabuf.planes[plane].stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_stride:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to set the stride for
|
||||
* @stride: the stride value
|
||||
*
|
||||
* Sets the stride for a plane.
|
||||
*
|
||||
* The stride must be set for all planes before calling [method@Gdk.GLTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane,
|
||||
unsigned int stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
|
||||
|
||||
if (self->dmabuf.planes[plane].stride == stride)
|
||||
return;
|
||||
|
||||
self->dmabuf.planes[plane].stride = stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_offset:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to get the offset for
|
||||
*
|
||||
* Gets the offset value for a plane.
|
||||
*
|
||||
* Returns: the offset
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
unsigned int
|
||||
gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
|
||||
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
|
||||
|
||||
return self->dmabuf.planes[plane].offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_offset:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @plane: the plane to set the offset for
|
||||
* @offset: the offset value
|
||||
*
|
||||
* Sets the offset for a plane.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
|
||||
unsigned int plane,
|
||||
unsigned int offset)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
|
||||
|
||||
if (self->dmabuf.planes[plane].offset == offset)
|
||||
return;
|
||||
|
||||
self->dmabuf.planes[plane].offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_update_texture: (attributes org.gdk.Method.get_property=update_texture)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the texture previously set via gdk_dmabuf_texture_builder_set_update_texture() or
|
||||
* %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The texture
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_update_texture: (attributes org.gdk.Method.set_property=update_texture)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @texture: (nullable): the texture to update
|
||||
*
|
||||
* Sets the texture to be updated by this texture. See
|
||||
* [method@Gdk.DmabufTextureBuilder.set_update_region] for an explanation.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
|
||||
|
||||
if (!g_set_object (&self->update_texture, texture))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_update_region: (attributes org.gdk.Method.get_property=update_region)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the region previously set via gdk_dmabuf_texture_builder_set_update_region() or
|
||||
* %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The region
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
cairo_region_t *
|
||||
gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_update_region: (attributes org.gdk.Method.set_property=update_region)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @region: (nullable): the region to update
|
||||
*
|
||||
* Sets the region to be updated by this texture. Together with
|
||||
* [property@Gdk.DmabufTextureBuilder:update-texture] this describes an
|
||||
* update of a previous texture.
|
||||
*
|
||||
* When rendering animations of large textures, it is possible that
|
||||
* consecutive textures are only updating contents in parts of the texture.
|
||||
* It is then possible to describe this update via these two properties,
|
||||
* so that GTK can avoid rerendering parts that did not change.
|
||||
*
|
||||
* An example would be a screen recording where only the mouse pointer moves.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->update_region == region)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
|
||||
if (region)
|
||||
self->update_region = cairo_region_reference (region);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_build:
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @destroy: (nullable): destroy function to be called when the texture is
|
||||
* released
|
||||
* @data: user data to pass to the destroy function
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Builds a new `GdkTexture` with the values set up in the builder.
|
||||
*
|
||||
* It is a programming error to call this function if any mandatory
|
||||
* property has not been set.
|
||||
*
|
||||
* If the dmabuf is not supported by GTK, %NULL will be returned and @error will be set.
|
||||
*
|
||||
* The `destroy` function gets called when the returned texture gets released.
|
||||
*
|
||||
* It is possible to call this function multiple times to create multiple textures,
|
||||
* possibly with changing properties in between.
|
||||
*
|
||||
* It is the responsibility of the caller to keep the file descriptors for the planes
|
||||
* open until the created texture is no longer used, and close them afterwards (possibly
|
||||
* using the @destroy notify).
|
||||
*
|
||||
* Not all formats defined in the `drm_fourcc.h` header are supported. You can use
|
||||
* [method@Gdk.Display.get_dmabuf_formats] to get a list of supported formats.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a newly built `GdkTexture` or `NULL`
|
||||
* if the format is not supported
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
g_return_val_if_fail (destroy == NULL || data != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
g_return_val_if_fail (self->width > 0, NULL);
|
||||
g_return_val_if_fail (self->height > 0, NULL);
|
||||
g_return_val_if_fail (self->dmabuf.fourcc != 0, NULL);
|
||||
|
||||
for (i = 0; i < self->dmabuf.n_planes; i++)
|
||||
g_return_val_if_fail (self->dmabuf.planes[i].fd != -1, NULL);
|
||||
|
||||
if (GDK_DEBUG_CHECK (DMABUF_DISABLE))
|
||||
{
|
||||
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
|
||||
"dmabuf support disabled via GDK_DEBUG environment variable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gdk_dmabuf_texture_new_from_builder (self, destroy, data, error);
|
||||
}
|
||||
|
||||
const GdkDmabuf *
|
||||
gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
return &self->dmabuf;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#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): return location for the used mime type
|
||||
* @out_mime_type: (out) (type utf8) (transfer none): return location for the used mime type
|
||||
* @error: (nullable): location to store error information on failure
|
||||
*
|
||||
* Finishes an async drop read operation.
|
||||
|
||||
@@ -142,6 +142,22 @@ 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
|
||||
@@ -282,10 +298,16 @@ 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
|
||||
@@ -366,6 +388,11 @@ 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;
|
||||
|
||||
+87
-2
@@ -109,6 +109,7 @@ typedef struct {
|
||||
guint has_sync : 1;
|
||||
guint has_unpack_subimage : 1;
|
||||
guint has_debug_output : 1;
|
||||
guint has_bgra : 1;
|
||||
guint extensions_checked : 1;
|
||||
guint debug_enabled : 1;
|
||||
guint forward_compatible : 1;
|
||||
@@ -1531,11 +1532,13 @@ 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)))
|
||||
@@ -1567,7 +1570,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
" - GL_KHR_debug: %s\n"
|
||||
" - GL_EXT_unpack_subimage: %s\n"
|
||||
" - half float: %s\n"
|
||||
" - sync: %s",
|
||||
" - sync: %s\n"
|
||||
" - bgra: %s",
|
||||
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
|
||||
gdk_gl_version_get_major (&priv->gl_version), gdk_gl_version_get_minor (&priv->gl_version),
|
||||
priv->is_legacy ? "legacy" : "core",
|
||||
@@ -1576,7 +1580,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
priv->has_khr_debug ? "yes" : "no",
|
||||
priv->has_unpack_subimage ? "yes" : "no",
|
||||
priv->has_half_float ? "yes" : "no",
|
||||
priv->has_sync ? "yes" : "no");
|
||||
priv->has_sync ? "yes" : "no",
|
||||
priv->has_bgra ? "yes" : "no");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1715,6 +1720,56 @@ 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:
|
||||
*
|
||||
@@ -1812,6 +1867,36 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is currently private! */
|
||||
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
|
||||
gboolean
|
||||
|
||||
@@ -147,6 +147,8 @@ 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);
|
||||
@@ -155,6 +157,10 @@ 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;
|
||||
|
||||
double gdk_gl_context_get_scale (GdkGLContext *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+4
-9
@@ -141,9 +141,7 @@ struct _Download
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gdk_gl_texture_find_format (gboolean use_es,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
gdk_gl_texture_find_format (GdkGLContext *context,
|
||||
GdkMemoryAlpha alpha,
|
||||
GLint gl_format,
|
||||
GLint gl_type,
|
||||
@@ -159,7 +157,7 @@ gdk_gl_texture_find_format (gboolean use_es,
|
||||
if (gdk_memory_format_alpha (format) != alpha)
|
||||
continue;
|
||||
|
||||
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, q_swizzle))
|
||||
if (!gdk_memory_format_gl_format (format, context, &q_internal_format, &q_format, &q_type, q_swizzle))
|
||||
continue;
|
||||
|
||||
if (q_format != gl_format || q_type != gl_type)
|
||||
@@ -183,16 +181,13 @@ 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,
|
||||
FALSE,
|
||||
major, minor,
|
||||
context,
|
||||
&gl_internal_format,
|
||||
&gl_format, &gl_type, gl_swizzle))
|
||||
{
|
||||
@@ -243,7 +238,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 (TRUE, major, minor, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
|
||||
if (!gdk_gl_texture_find_format (context, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
|
||||
{
|
||||
gl_read_format = GL_RGBA;
|
||||
gl_read_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
+71
-5
@@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
@@ -93,10 +94,17 @@ 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)
|
||||
@@ -352,7 +360,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_premultiplied_to_float,
|
||||
b8g8r8a8_premultiplied_from_float,
|
||||
@@ -377,12 +385,22 @@ 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, G_MAXUINT, G_MAXUINT },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_to_float,
|
||||
b8g8r8a8_from_float,
|
||||
@@ -417,6 +435,46 @@ 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,
|
||||
@@ -733,14 +791,19 @@ gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth)
|
||||
|
||||
gboolean
|
||||
gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
GdkGLContext *context,
|
||||
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;
|
||||
@@ -752,6 +815,9 @@ 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,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkenums.h"
|
||||
#include "gdktypes.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@@ -46,9 +47,7 @@ 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,
|
||||
gboolean gles,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
GdkGLContext *context,
|
||||
guint *out_internal_format,
|
||||
guint *out_format,
|
||||
guint *out_type,
|
||||
|
||||
+5
-2
@@ -24,13 +24,16 @@
|
||||
#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);
|
||||
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot,
|
||||
const graphene_size_t *size);
|
||||
|
||||
/**
|
||||
* GdkPaintable:
|
||||
@@ -118,7 +121,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);
|
||||
return gtk_snapshot_free_to_paintable (snapshot, NULL);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
||||
@@ -40,7 +40,7 @@ struct _GdkIOPipe
|
||||
GCond cond;
|
||||
guchar *buffer;
|
||||
gsize size;
|
||||
GdkIOPipeState state : 2;
|
||||
guint state : 2; /* GdkIOPipeState */
|
||||
guint input_closed : 1;
|
||||
guint output_closed : 1;
|
||||
};
|
||||
|
||||
+1
-1
@@ -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)
|
||||
if ((secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size) || primary > bounds_pos + bounds_size)
|
||||
return secondary;
|
||||
|
||||
*flipped = FALSE;
|
||||
|
||||
+5
-3
@@ -345,7 +345,9 @@ gdk_texture_init (GdkTexture *self)
|
||||
*
|
||||
* Creates a new texture object representing the surface.
|
||||
*
|
||||
* @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
|
||||
* The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
|
||||
*
|
||||
* The newly created texture will acquire a reference on the @surface.
|
||||
*
|
||||
* Returns: a new `GdkTexture`
|
||||
*/
|
||||
@@ -364,7 +366,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,
|
||||
@@ -819,7 +821,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,6 +96,8 @@ 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,6 +1475,13 @@ 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,6 +329,7 @@ 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:
|
||||
@@ -340,6 +341,10 @@ 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,12 +236,17 @@ 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,6 +17,11 @@ gdk_public_sources = files([
|
||||
'gdkdevicetool.c',
|
||||
'gdkdisplay.c',
|
||||
'gdkdisplaymanager.c',
|
||||
'gdkdmabuf.c',
|
||||
'gdkdmabufformats.c',
|
||||
'gdkdmabufformatsbuilder.c',
|
||||
'gdkdmabuftexture.c',
|
||||
'gdkdmabuftexturebuilder.c',
|
||||
'gdkdrag.c',
|
||||
'gdkdragsurface.c',
|
||||
'gdkdragsurfacesize.c',
|
||||
@@ -79,6 +84,9 @@ gdk_public_headers = files([
|
||||
'gdkdisplay.h',
|
||||
'gdkdisplaymanager.h',
|
||||
'gdkdrag.h',
|
||||
'gdkdmabufformats.h',
|
||||
'gdkdmabuftexture.h',
|
||||
'gdkdmabuftexturebuilder.h',
|
||||
'gdkdragsurfacesize.h',
|
||||
'gdkdrawcontext.h',
|
||||
'gdkdrop.h',
|
||||
|
||||
@@ -4442,6 +4442,10 @@ _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 = gdk_texture_download_surface (texture);
|
||||
cairo_surface_t *surface;
|
||||
cairo_surface_t *image_surface;
|
||||
graphene_vec4_t pixel;
|
||||
guint32* pixel_data;
|
||||
@@ -475,6 +475,7 @@ 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);
|
||||
@@ -536,6 +537,8 @@ get_colorized_texture (GdkTexture *texture,
|
||||
colorized_list, (GDestroyNotify)colorized_texture_free_list);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return colorized_texture;
|
||||
}
|
||||
|
||||
@@ -611,7 +614,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_for_surface (image_surface);
|
||||
g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
|
||||
g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
@@ -902,6 +905,8 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
add_float (nodes, width);
|
||||
add_float (nodes, height);
|
||||
add_uint32 (nodes, texture_id);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-34
@@ -1070,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_get_use_es (self->context))
|
||||
if (gdk_gl_context_has_vertex_arrays (self->context))
|
||||
{
|
||||
glGenVertexArrays (1, &vao_id);
|
||||
glBindVertexArray (vao_id);
|
||||
@@ -1257,7 +1257,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
}
|
||||
|
||||
glDeleteBuffers (1, &vbo_id);
|
||||
if (!gdk_gl_context_get_use_es (self->context))
|
||||
if (gdk_gl_context_has_vertex_arrays (self->context))
|
||||
glDeleteVertexArrays (1, &vao_id);
|
||||
|
||||
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
|
||||
@@ -1450,9 +1450,7 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
|
||||
|
||||
static GdkMemoryFormat
|
||||
memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
gboolean use_es,
|
||||
guint major,
|
||||
guint minor,
|
||||
GdkGLContext *context,
|
||||
guint *gl_internalformat,
|
||||
guint *gl_format,
|
||||
guint *gl_type,
|
||||
@@ -1462,9 +1460,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
|
||||
/* First, try the format itself */
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1480,9 +1476,7 @@ 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,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1493,9 +1487,7 @@ 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,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1517,9 +1509,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
{
|
||||
data_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1530,9 +1520,7 @@ 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,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1561,19 +1549,13 @@ 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,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
self->context,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
@@ -1638,9 +1620,7 @@ 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));
|
||||
|
||||
@@ -1673,13 +1653,9 @@ 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,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
self->context,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskglcompilerprivate.h"
|
||||
#include "gskglglyphlibraryprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskgliconlibraryprivate.h"
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglshadowlibraryprivate.h"
|
||||
@@ -274,7 +273,6 @@ gsk_gl_driver_dispose (GObject *object)
|
||||
}
|
||||
|
||||
g_clear_object (&self->glyphs_library);
|
||||
g_clear_object (&self->glyphy_library);
|
||||
g_clear_object (&self->icons_library);
|
||||
g_clear_object (&self->shadows_library);
|
||||
|
||||
@@ -401,7 +399,6 @@ 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_ADD_UNIFORM
|
||||
#undef GSK_GL_SHADER_SINGLE
|
||||
@@ -465,7 +462,6 @@ gsk_gl_driver_new (GskGLCommandQueue *command_queue,
|
||||
}
|
||||
|
||||
self->glyphs_library = gsk_gl_glyph_library_new (self);
|
||||
self->glyphy_library = gsk_gl_glyphy_library_new (self);
|
||||
self->icons_library = gsk_gl_icon_library_new (self);
|
||||
self->shadows_library = gsk_gl_shadow_library_new (self);
|
||||
|
||||
@@ -576,8 +572,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
|
||||
self->current_frame_id);
|
||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs_library),
|
||||
self->current_frame_id);
|
||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphy_library),
|
||||
self->current_frame_id);
|
||||
|
||||
/* Cleanup old shadows */
|
||||
gsk_gl_shadow_library_begin_frame (self->shadows_library);
|
||||
@@ -1009,9 +1003,9 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
|
||||
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);
|
||||
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));
|
||||
|
||||
@@ -97,7 +97,6 @@ struct _GskGLDriver
|
||||
GskGLCommandQueue *command_queue;
|
||||
|
||||
GskGLGlyphLibrary *glyphs_library;
|
||||
GskGLGlyphyLibrary *glyphy_library;
|
||||
GskGLIconLibrary *icons_library;
|
||||
GskGLShadowLibrary *shadows_library;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
|
||||
|
||||
memset (pixel_data, 255, sizeof pixel_data);
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ()))
|
||||
{
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
@@ -127,9 +127,8 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
|
||||
else
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
@@ -277,7 +276,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
|
||||
|
||||
g_assert (texture_id > 0);
|
||||
|
||||
if G_UNLIKELY (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (G_UNLIKELY (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())))
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
@@ -294,7 +293,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_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / 4);
|
||||
|
||||
@@ -1,544 +0,0 @@
|
||||
/* gskglglyphylibrary.c
|
||||
*
|
||||
* Copyright 2020 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
/* Some of the glyphy cache is based upon the original glyphy code.
|
||||
* It's license is provided below.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012 Google, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskgldriverprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#include "gskpathprivate.h"
|
||||
|
||||
#include <glyphy.h>
|
||||
|
||||
#define TOLERANCE (1/2048.)
|
||||
#define MIN_FONT_SIZE 14
|
||||
#define GRID_SIZE 20 /* Per EM */
|
||||
#define ENLIGHTEN_MAX .01 /* Per EM */
|
||||
#define EMBOLDEN_MAX .024 /* Per EM */
|
||||
|
||||
/* We split the atlas into cells of size 64x8, so the minimum number of
|
||||
* bytes we store per glyph is 2048, and an atlas of size 2048x1024 can
|
||||
* hold at most 4096 glyphs. We need 5 and 7 bits to store the position
|
||||
* of a glyph in the atlas.
|
||||
*
|
||||
* We allocate each glyph a column of as many vertically adjacent cells
|
||||
* as it needs.
|
||||
*/
|
||||
#define ITEM_W 64
|
||||
#define ITEM_H_QUANTUM 8
|
||||
|
||||
G_DEFINE_TYPE (GskGLGlyphyLibrary, gsk_gl_glyphy_library, GSK_TYPE_GL_TEXTURE_LIBRARY)
|
||||
|
||||
GskGLGlyphyLibrary *
|
||||
gsk_gl_glyphy_library_new (GskGLDriver *driver)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), NULL);
|
||||
|
||||
return g_object_new (GSK_TYPE_GL_GLYPHY_LIBRARY,
|
||||
"driver", driver,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static guint
|
||||
gsk_gl_glyphy_key_hash (gconstpointer data)
|
||||
{
|
||||
const GskGLGlyphyKey *key = data;
|
||||
|
||||
/* malloc()'d pointers already guarantee 3 bits from the LSB on 64-bit and
|
||||
* 2 bits from the LSB on 32-bit. Shift by enough to give us 256 entries
|
||||
* in our front cache for the glyph since languages will naturally cluster
|
||||
* for us.
|
||||
*/
|
||||
|
||||
return (key->font << 8) ^ key->glyph;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_glyphy_key_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
return memcmp (v1, v2, sizeof (GskGLGlyphyKey)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_key_free (gpointer data)
|
||||
{
|
||||
GskGLGlyphyKey *key = data;
|
||||
|
||||
g_slice_free (GskGLGlyphyKey, key);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_value_free (gpointer data)
|
||||
{
|
||||
g_slice_free (GskGLGlyphyValue, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_clear_cache (GskGLTextureLibrary *library)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)library;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
|
||||
memset (self->front, 0, sizeof self->front);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_init_atlas (GskGLTextureLibrary *library,
|
||||
GskGLTextureAtlas *atlas)
|
||||
{
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (library));
|
||||
g_assert (atlas != NULL);
|
||||
|
||||
atlas->cursor_x = 0;
|
||||
atlas->cursor_y = 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_glyphy_library_allocate (GskGLTextureLibrary *library,
|
||||
GskGLTextureAtlas *atlas,
|
||||
int width,
|
||||
int height,
|
||||
int *out_x,
|
||||
int *out_y)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)library;
|
||||
int cursor_save_x;
|
||||
int cursor_save_y;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
g_assert (atlas != NULL);
|
||||
|
||||
cursor_save_x = atlas->cursor_x;
|
||||
cursor_save_y = atlas->cursor_y;
|
||||
|
||||
if ((height & (self->item_h_q-1)) != 0)
|
||||
height = (height + self->item_h_q - 1) & ~(self->item_h_q - 1);
|
||||
|
||||
/* Require allocations in columns of 64 and rows of 8 */
|
||||
g_assert (width == self->item_w);
|
||||
g_assert ((height % self->item_h_q) == 0);
|
||||
|
||||
if (atlas->cursor_y + height > atlas->height)
|
||||
{
|
||||
/* Go to next column */
|
||||
atlas->cursor_x += self->item_w;
|
||||
atlas->cursor_y = 0;
|
||||
}
|
||||
|
||||
if (atlas->cursor_x + width <= atlas->width &&
|
||||
atlas->cursor_y + height <= atlas->height)
|
||||
{
|
||||
*out_x = atlas->cursor_x;
|
||||
*out_y = atlas->cursor_y;
|
||||
atlas->cursor_y += height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
atlas->cursor_x = cursor_save_x;
|
||||
atlas->cursor_y = cursor_save_y;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_finalize (GObject *object)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)object;
|
||||
|
||||
g_clear_pointer (&self->acc, glyphy_arc_accumulator_destroy);
|
||||
g_clear_pointer (&self->acc_endpoints, g_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_glyphy_library_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GQuark quark_glyphy_font_key;
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_class_init (GskGLGlyphyLibraryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GskGLTextureLibraryClass *library_class = GSK_GL_TEXTURE_LIBRARY_CLASS (klass);
|
||||
|
||||
quark_glyphy_font_key = g_quark_from_static_string ("glyphy-font-key");
|
||||
|
||||
object_class->finalize = gsk_gl_glyphy_library_finalize;
|
||||
|
||||
library_class->allocate = gsk_gl_glyphy_library_allocate;
|
||||
library_class->clear_cache = gsk_gl_glyphy_library_clear_cache;
|
||||
library_class->init_atlas = gsk_gl_glyphy_library_init_atlas;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_init (GskGLGlyphyLibrary *self)
|
||||
{
|
||||
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
|
||||
|
||||
tl->max_entry_size = 0;
|
||||
tl->max_frame_age = 512;
|
||||
tl->atlas_width = 2048;
|
||||
tl->atlas_height = 1024;
|
||||
gsk_gl_texture_library_set_funcs (tl,
|
||||
gsk_gl_glyphy_key_hash,
|
||||
gsk_gl_glyphy_key_equal,
|
||||
gsk_gl_glyphy_key_free,
|
||||
gsk_gl_glyphy_value_free);
|
||||
|
||||
self->acc = glyphy_arc_accumulator_create ();
|
||||
self->acc_endpoints = g_array_new (FALSE, FALSE, sizeof (glyphy_arc_endpoint_t));
|
||||
self->item_w = ITEM_W;
|
||||
self->item_h_q = ITEM_H_QUANTUM;
|
||||
}
|
||||
|
||||
static glyphy_bool_t
|
||||
accumulate_endpoint (glyphy_arc_endpoint_t *endpoint,
|
||||
GArray *endpoints)
|
||||
{
|
||||
g_array_append_vals (endpoints, endpoint, 1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
move_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x,
|
||||
float y,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_move_to (builder, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
line_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x,
|
||||
float y,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_line_to (builder, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
cubic_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_cubic_to (builder, x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
static void
|
||||
close_path (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_close (builder);
|
||||
}
|
||||
|
||||
static hb_draw_funcs_t *
|
||||
gsk_path_get_draw_funcs (void)
|
||||
{
|
||||
static hb_draw_funcs_t *funcs = NULL;
|
||||
|
||||
if (!funcs)
|
||||
{
|
||||
funcs = hb_draw_funcs_create ();
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
|
||||
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
|
||||
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
|
||||
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
|
||||
|
||||
hb_draw_funcs_make_immutable (funcs);
|
||||
}
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
acc_callback (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer user_data)
|
||||
{
|
||||
glyphy_arc_accumulator_t *acc = user_data;
|
||||
glyphy_point_t p0, p1, p2, p3;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GSK_PATH_MOVE:
|
||||
p0.x = pts[0].x; p0.y = pts[0].y;
|
||||
glyphy_arc_accumulator_move_to (acc, &p0);
|
||||
break;
|
||||
case GSK_PATH_CLOSE:
|
||||
glyphy_arc_accumulator_close_path (acc);
|
||||
break;
|
||||
case GSK_PATH_LINE:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
glyphy_arc_accumulator_line_to (acc, &p1);
|
||||
break;
|
||||
case GSK_PATH_QUAD:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
p2.x = pts[2].x; p2.y = pts[2].y;
|
||||
/* This glyphy api is mis-named */
|
||||
glyphy_arc_accumulator_conic_to (acc, &p1, &p2);
|
||||
break;
|
||||
case GSK_PATH_CUBIC:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
p2.x = pts[2].x; p2.y = pts[2].y;
|
||||
p3.x = pts[3].x; p3.y = pts[3].y;
|
||||
glyphy_arc_accumulator_cubic_to (acc, &p1, &p2, &p3);
|
||||
break;
|
||||
case GSK_PATH_CONIC:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
encode_glyph (GskGLGlyphyLibrary *self,
|
||||
hb_font_t *font,
|
||||
unsigned int glyph_index,
|
||||
double tolerance_per_em,
|
||||
glyphy_rgba_t *buffer,
|
||||
guint buffer_len,
|
||||
guint *output_len,
|
||||
guint *nominal_width,
|
||||
guint *nominal_height,
|
||||
glyphy_extents_t *extents)
|
||||
{
|
||||
hb_face_t *face = hb_font_get_face (font);
|
||||
guint upem = hb_face_get_upem (face);
|
||||
double tolerance = upem * tolerance_per_em;
|
||||
double faraway = (double)upem / (MIN_FONT_SIZE * M_SQRT2);
|
||||
double unit_size = (double) upem / GRID_SIZE;
|
||||
double enlighten_max = (double) upem * ENLIGHTEN_MAX;
|
||||
double embolden_max = (double) upem * EMBOLDEN_MAX;
|
||||
double avg_fetch_achieved;
|
||||
GskPathBuilder *builder;
|
||||
GskPath *path, *simplified;
|
||||
|
||||
self->acc_endpoints->len = 0;
|
||||
|
||||
glyphy_arc_accumulator_reset (self->acc);
|
||||
glyphy_arc_accumulator_set_tolerance (self->acc, tolerance);
|
||||
glyphy_arc_accumulator_set_callback (self->acc,
|
||||
(glyphy_arc_endpoint_accumulator_callback_t)accumulate_endpoint,
|
||||
self->acc_endpoints);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
#if HB_VERSION_ATLEAST (7, 0, 0)
|
||||
hb_font_draw_glyph (font, glyph_index, gsk_path_get_draw_funcs (), builder);
|
||||
#else
|
||||
hb_font_get_glyph_shape (font, glyph_index, gsk_path_get_draw_funcs (), builder);
|
||||
#endif
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
simplified = gsk_path_op (GSK_PATH_OP_SIMPLIFY, GSK_FILL_RULE_WINDING, path, NULL);
|
||||
gsk_path_foreach (simplified, -1, acc_callback, self->acc);
|
||||
gsk_path_unref (simplified);
|
||||
gsk_path_unref (path);
|
||||
|
||||
if (!glyphy_arc_accumulator_successful (self->acc))
|
||||
return FALSE;
|
||||
|
||||
g_assert (glyphy_arc_accumulator_get_error (self->acc) <= tolerance);
|
||||
|
||||
if (self->acc_endpoints->len > 0)
|
||||
glyphy_outline_winding_from_even_odd ((gpointer)self->acc_endpoints->data,
|
||||
self->acc_endpoints->len,
|
||||
FALSE);
|
||||
|
||||
if (!glyphy_arc_list_encode_blob2 ((gpointer)self->acc_endpoints->data,
|
||||
self->acc_endpoints->len,
|
||||
buffer,
|
||||
buffer_len,
|
||||
faraway,
|
||||
unit_size,
|
||||
enlighten_max,
|
||||
embolden_max,
|
||||
&avg_fetch_achieved,
|
||||
output_len,
|
||||
nominal_width,
|
||||
nominal_height,
|
||||
extents))
|
||||
return FALSE;
|
||||
|
||||
glyphy_extents_scale (extents, 1./upem, 1./upem);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline hb_font_t *
|
||||
get_nominal_size_hb_font (PangoFont *font)
|
||||
{
|
||||
hb_font_t *hbfont;
|
||||
const float *coords;
|
||||
unsigned int length;
|
||||
|
||||
hbfont = (hb_font_t *) g_object_get_data ((GObject *)font, "glyph-nominal-size-font");
|
||||
if (hbfont == NULL)
|
||||
{
|
||||
hbfont = hb_font_create (hb_font_get_face (pango_font_get_hb_font (font)));
|
||||
coords = hb_font_get_var_coords_design (pango_font_get_hb_font (font), &length);
|
||||
if (length > 0)
|
||||
hb_font_set_var_coords_design (hbfont, coords, length);
|
||||
|
||||
g_object_set_data_full ((GObject *)font, "glyphy-nominal-size-font",
|
||||
hbfont, (GDestroyNotify)hb_font_destroy);
|
||||
}
|
||||
|
||||
return hbfont;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
|
||||
GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value)
|
||||
{
|
||||
static glyphy_rgba_t buffer[4096 * 16];
|
||||
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
|
||||
GskGLGlyphyValue *value;
|
||||
glyphy_extents_t extents;
|
||||
hb_font_t *hbfont;
|
||||
guint packed_x;
|
||||
guint packed_y;
|
||||
guint nominal_w, nominal_h;
|
||||
guint output_len = 0;
|
||||
guint texture_id;
|
||||
guint width, height;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
g_assert (key != NULL);
|
||||
g_assert (font != NULL);
|
||||
g_assert (out_value != NULL);
|
||||
|
||||
hbfont = get_nominal_size_hb_font (font);
|
||||
|
||||
/* Convert the glyph to a list of arcs */
|
||||
if (!encode_glyph (self, hbfont, key->glyph, TOLERANCE,
|
||||
buffer, sizeof buffer, &output_len,
|
||||
&nominal_w, &nominal_h, &extents))
|
||||
return FALSE;
|
||||
|
||||
/* Allocate space for list within atlas */
|
||||
width = self->item_w;
|
||||
height = (output_len + width - 1) / width;
|
||||
GSK_DEBUG (GLYPH_CACHE, "font %u glyph %u: %u bytes (%u x %u)", key->font, key->glyph, output_len * 4, width, height);
|
||||
|
||||
value = gsk_gl_texture_library_pack (tl, key, sizeof *value,
|
||||
width, height, 0,
|
||||
&packed_x, &packed_y);
|
||||
|
||||
g_assert (packed_x % ITEM_W == 0);
|
||||
g_assert (packed_y % ITEM_H_QUANTUM == 0);
|
||||
|
||||
/* Make sure we found space to pack */
|
||||
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (value);
|
||||
if (texture_id == 0)
|
||||
return FALSE;
|
||||
|
||||
if (!glyphy_extents_is_empty (&extents))
|
||||
{
|
||||
/* Connect the texture for data upload */
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
|
||||
g_assert (width > 0);
|
||||
g_assert (height > 0);
|
||||
|
||||
/* Upload the arc list */
|
||||
if (width * height == output_len)
|
||||
{
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y,
|
||||
width, height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y,
|
||||
width, height - 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer);
|
||||
/* Upload the last row separately */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y + height - 1,
|
||||
output_len - (width * (height - 1)), 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer + (width * (height - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
value->extents.min_x = extents.min_x;
|
||||
value->extents.min_y = extents.min_y;
|
||||
value->extents.max_x = extents.max_x;
|
||||
value->extents.max_y = extents.max_y;
|
||||
value->nominal_w = nominal_w;
|
||||
value->nominal_h = nominal_h;
|
||||
value->atlas_x = packed_x / self->item_w;
|
||||
value->atlas_y = packed_y / self->item_h_q;
|
||||
|
||||
*out_value = value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/* gskglglyphylibraryprivate.h
|
||||
*
|
||||
* Copyright 2020-2022 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__
|
||||
#define __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__
|
||||
|
||||
#include <glyphy.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include "gskgltexturelibraryprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_GLYPHY_LIBRARY (gsk_gl_glyphy_library_get_type())
|
||||
|
||||
typedef guint FontKey;
|
||||
|
||||
extern GQuark quark_glyphy_font_key;
|
||||
|
||||
static inline FontKey
|
||||
gsk_gl_glyphy_library_get_font_key (PangoFont *font)
|
||||
{
|
||||
FontKey key;
|
||||
|
||||
key = (FontKey) GPOINTER_TO_UINT (g_object_get_qdata ((GObject *)font, quark_glyphy_font_key));
|
||||
if (key == 0)
|
||||
{
|
||||
PangoFontDescription *desc = pango_font_describe (font);
|
||||
pango_font_description_set_size (desc, 10 * PANGO_SCALE);
|
||||
key = (FontKey) pango_font_description_hash (desc);
|
||||
pango_font_description_free (desc);
|
||||
g_object_set_qdata ((GObject *)font, quark_glyphy_font_key, GUINT_TO_POINTER (key));
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static inline float
|
||||
gsk_gl_glyphy_library_get_font_scale (PangoFont *font)
|
||||
{
|
||||
hb_font_t *hbfont;
|
||||
int x_scale, y_scale;
|
||||
|
||||
hbfont = pango_font_get_hb_font (font);
|
||||
hb_font_get_scale (hbfont, &x_scale, &y_scale);
|
||||
|
||||
return MAX (x_scale, y_scale) / 1000.0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct _GskGLGlyphyKey
|
||||
{
|
||||
FontKey font;
|
||||
PangoGlyph glyph;
|
||||
} GskGLGlyphyKey;
|
||||
|
||||
typedef struct _GskGLGlyphyValue
|
||||
{
|
||||
GskGLTextureAtlasEntry entry;
|
||||
struct {
|
||||
float min_x;
|
||||
float min_y;
|
||||
float max_x;
|
||||
float max_y;
|
||||
} extents;
|
||||
guint nominal_w;
|
||||
guint nominal_h;
|
||||
guint atlas_x;
|
||||
guint atlas_y;
|
||||
} GskGLGlyphyValue;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLGlyphyLibrary, gsk_gl_glyphy_library, GSK, GL_GLYPHY_LIBRARY, GskGLTextureLibrary)
|
||||
|
||||
struct _GskGLGlyphyLibrary
|
||||
{
|
||||
GskGLTextureLibrary parent_instance;
|
||||
glyphy_arc_accumulator_t *acc;
|
||||
GArray *acc_endpoints;
|
||||
guint item_w;
|
||||
guint item_h_q;
|
||||
struct {
|
||||
GskGLGlyphyKey key;
|
||||
const GskGLGlyphyValue *value;
|
||||
} front[256];
|
||||
};
|
||||
|
||||
GskGLGlyphyLibrary *gsk_gl_glyphy_library_new (GskGLDriver *driver);
|
||||
gboolean gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
|
||||
GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value);
|
||||
|
||||
static inline guint
|
||||
gsk_gl_glyphy_library_lookup_or_add (GskGLGlyphyLibrary *self,
|
||||
const GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value)
|
||||
{
|
||||
GskGLTextureAtlasEntry *entry;
|
||||
guint front_index = key->glyph & 0xFF;
|
||||
|
||||
if (memcmp (key, &self->front[front_index], sizeof *key) == 0)
|
||||
{
|
||||
*out_value = self->front[front_index].value;
|
||||
}
|
||||
else if (gsk_gl_texture_library_lookup ((GskGLTextureLibrary *)self, key, &entry))
|
||||
{
|
||||
*out_value = (GskGLGlyphyValue *)entry;
|
||||
self->front[front_index].key = *key;
|
||||
self->front[front_index].value = *out_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
GskGLGlyphyKey *k = g_slice_copy (sizeof *key, key);
|
||||
gsk_gl_glyphy_library_add (self, k, font, out_value);
|
||||
self->front[front_index].key = *key;
|
||||
self->front[front_index].value = *out_value;
|
||||
}
|
||||
|
||||
return GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (*out_value);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__ */
|
||||
@@ -111,7 +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_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ()))
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
@@ -125,7 +125,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
|
||||
{
|
||||
pixel_data = surface_data;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
|
||||
|
||||
@@ -87,21 +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))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM (glyphy,
|
||||
GSK_GL_SHADER_JOINED (VERTEX,
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.vs.glsl"),
|
||||
NULL)
|
||||
GSK_GL_SHADER_JOINED (FRAGMENT,
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.atlas.glsl"),
|
||||
GSK_GL_SHADER_STRING (glyphy_common_shader_source ()),
|
||||
GSK_GL_SHADER_STRING ("#define GLYPHY_SDF_PSEUDO_DISTANCE 1\n"),
|
||||
GSK_GL_SHADER_STRING (glyphy_sdf_shader_source ()),
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.fs.glsl"),
|
||||
NULL),
|
||||
GSK_GL_ADD_UNIFORM (0, GLYPHY_CONTRAST, u_contrast)
|
||||
GSK_GL_ADD_UNIFORM (1, GLYPHY_GAMMA_ADJUST, u_gamma_adjust)
|
||||
GSK_GL_ADD_UNIFORM (2, GLYPHY_OUTLINE_THICKNESS, u_outline_thickness)
|
||||
GSK_GL_ADD_UNIFORM (3, GLYPHY_OUTLINE, u_outline)
|
||||
GSK_GL_ADD_UNIFORM (4, GLYPHY_BOLDNESS, u_boldness)
|
||||
GSK_GL_ADD_UNIFORM (6, GLYPHY_ATLAS_INFO, u_atlas_info))
|
||||
|
||||
@@ -150,13 +150,6 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
|
||||
gsk_gl_command_queue_set_profiler (self->command_queue,
|
||||
gsk_renderer_get_profiler (renderer));
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (gsk_renderer_get_debug_flags (renderer) & GSK_DEBUG_NO_GLYPHY)
|
||||
GSK_RENDERER_DEBUG (renderer, RENDERER, "GL Renderer will use cairo for glyph rendering");
|
||||
else
|
||||
GSK_RENDERER_DEBUG (renderer, RENDERER, "GL Renderer will use glyphy for glyph rendering");
|
||||
#endif
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
failure:
|
||||
@@ -314,15 +307,10 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
|
||||
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
|
||||
job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer);
|
||||
|
||||
if ((gsk_renderer_get_debug_flags (renderer) & GSK_DEBUG_NO_GLYPHY) == 0)
|
||||
gsk_gl_render_job_set_use_glyphy (job, TRUE);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK))
|
||||
gsk_gl_render_job_set_debug_fallback (job, TRUE);
|
||||
#endif
|
||||
|
||||
gsk_gl_render_job_render (job, root);
|
||||
gsk_gl_driver_end_frame (self->driver);
|
||||
gsk_gl_render_job_free (job);
|
||||
|
||||
+138
-306
@@ -39,7 +39,6 @@
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskgldriverprivate.h"
|
||||
#include "gskglglyphlibraryprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskgliconlibraryprivate.h"
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglrenderjobprivate.h"
|
||||
@@ -66,6 +65,14 @@ 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;
|
||||
@@ -78,6 +85,14 @@ 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
|
||||
@@ -118,12 +133,12 @@ struct _GskGLRenderJob
|
||||
/* An array of GskGLRenderModelview updated as nodes are processed. The
|
||||
* current modelview is the last element.
|
||||
*/
|
||||
GArray *modelview;
|
||||
Modelviews modelview;
|
||||
|
||||
/* An array of GskGLRenderClip updated as nodes are processed. The
|
||||
* current clip is the last element.
|
||||
*/
|
||||
GArray *clip;
|
||||
Clips clip;
|
||||
|
||||
/* Our current alpha state as we process nodes */
|
||||
float alpha;
|
||||
@@ -153,9 +168,6 @@ struct _GskGLRenderJob
|
||||
*/
|
||||
guint clear_framebuffer : 1;
|
||||
|
||||
/* Allow experimental glyph rendering with glyphy */
|
||||
guint use_glyphy : 1;
|
||||
|
||||
/* Format we want to use for intermediate textures, determined by
|
||||
* looking at the format of the framebuffer we are rendering on.
|
||||
*/
|
||||
@@ -196,6 +208,26 @@ 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,
|
||||
@@ -242,7 +274,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_get_node_type (node))
|
||||
switch (GSK_RENDER_NODE_TYPE (node))
|
||||
{
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_OPACITY_NODE:
|
||||
@@ -304,7 +336,7 @@ node_supports_transform (const GskRenderNode *node)
|
||||
* opacity or color matrix.
|
||||
*/
|
||||
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
switch (GSK_RENDER_NODE_TYPE (node))
|
||||
{
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_OPACITY_NODE:
|
||||
@@ -470,15 +502,10 @@ 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]++;
|
||||
|
||||
g_array_set_size (job->modelview, job->modelview->len + 1);
|
||||
|
||||
modelview = &g_array_index (job->modelview,
|
||||
GskGLRenderModelview,
|
||||
job->modelview->len - 1);
|
||||
modelview = modelviews_grow_one (&job->modelview);
|
||||
|
||||
modelview->transform = transform;
|
||||
|
||||
@@ -503,26 +530,17 @@ 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]++;
|
||||
|
||||
g_array_set_size (job->modelview, job->modelview->len + 1);
|
||||
modelview = modelviews_grow_one (&job->modelview);
|
||||
|
||||
modelview = &g_array_index (job->modelview,
|
||||
GskGLRenderModelview,
|
||||
job->modelview->len - 1);
|
||||
|
||||
if G_LIKELY (job->modelview->len > 1)
|
||||
if G_LIKELY (modelviews_get_size (&job->modelview) > 1)
|
||||
{
|
||||
GskGLRenderModelview *last;
|
||||
GskGLRenderModelview *last = job->modelview.end - 2;
|
||||
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) {
|
||||
@@ -556,8 +574,7 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
|
||||
const GskGLRenderModelview *head;
|
||||
|
||||
g_assert (job != NULL);
|
||||
g_assert (job->modelview);
|
||||
g_assert (job->modelview->len > 0);
|
||||
g_assert (modelviews_get_size (&job->modelview) > 0);
|
||||
|
||||
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
|
||||
|
||||
@@ -568,11 +585,11 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
|
||||
|
||||
gsk_transform_unref (head->transform);
|
||||
|
||||
job->modelview->len--;
|
||||
job->modelview.end--;
|
||||
|
||||
if (job->modelview->len >= 1)
|
||||
if (modelviews_get_size (&job->modelview) >= 1)
|
||||
{
|
||||
head = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len - 1);
|
||||
head = job->modelview.end - 1;
|
||||
|
||||
job->scale_x = head->scale_x;
|
||||
job->scale_y = head->scale_y;
|
||||
@@ -592,14 +609,12 @@ 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]++;
|
||||
|
||||
g_array_set_size (job->clip, job->clip->len + 1);
|
||||
clip = clips_grow_one (&job->clip);
|
||||
|
||||
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;
|
||||
@@ -614,16 +629,13 @@ gsk_gl_render_job_push_contained_clip (GskGLRenderJob *job)
|
||||
GskGLRenderClip *old_clip;
|
||||
|
||||
g_assert (job != NULL);
|
||||
g_assert (job->clip != NULL);
|
||||
g_assert (job->clip->len > 0);
|
||||
g_assert (clips_get_size (&job->clip) > 0);
|
||||
|
||||
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
|
||||
|
||||
old_clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
|
||||
clip = clips_grow_one (&job->clip);
|
||||
old_clip = clips_get (&job->clip, clips_get_size (&job->clip) - 2);
|
||||
|
||||
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;
|
||||
@@ -636,12 +648,11 @@ static void
|
||||
gsk_gl_render_job_pop_clip (GskGLRenderJob *job)
|
||||
{
|
||||
g_assert (job != NULL);
|
||||
g_assert (job->clip != NULL);
|
||||
g_assert (job->clip->len > 0);
|
||||
g_assert (clips_get_size (&job->clip) > 0);
|
||||
|
||||
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
|
||||
job->current_clip--;
|
||||
job->clip->len--;
|
||||
job->clip.end--;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -723,7 +734,7 @@ gsk_gl_render_job_transform_bounds (GskGLRenderJob *job,
|
||||
GskTransformCategory category;
|
||||
|
||||
g_assert (job != NULL);
|
||||
g_assert (job->modelview->len > 0);
|
||||
g_assert (modelviews_get_size (&job->modelview) > 0);
|
||||
g_assert (rect != NULL);
|
||||
g_assert (out_rect != NULL);
|
||||
|
||||
@@ -1218,12 +1229,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_get_node_type (node) == GSK_CAIRO_NODE)
|
||||
if (GSK_RENDER_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_get_node_type (node) == GSK_CAIRO_NODE)
|
||||
if (GSK_RENDER_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);
|
||||
@@ -1516,7 +1527,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_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
|
||||
gboolean repeat = GSK_RENDER_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;
|
||||
@@ -1589,7 +1600,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_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
|
||||
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
|
||||
float scale = 1.0f / (end - start);
|
||||
float bias = -start * scale;
|
||||
|
||||
@@ -1734,7 +1745,7 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
|
||||
* which both have rounded corners.
|
||||
*/
|
||||
|
||||
if (job->clip->len <= 1)
|
||||
if (clips_get_size (&job->clip) <= 1)
|
||||
need_offscreen = FALSE;
|
||||
else if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
|
||||
need_offscreen = FALSE;
|
||||
@@ -2803,8 +2814,8 @@ static inline gboolean G_GNUC_PURE
|
||||
equal_texture_nodes (const GskRenderNode *node1,
|
||||
const GskRenderNode *node2)
|
||||
{
|
||||
if (gsk_render_node_get_node_type (node1) != GSK_TEXTURE_NODE ||
|
||||
gsk_render_node_get_node_type (node2) != GSK_TEXTURE_NODE)
|
||||
if (GSK_RENDER_NODE_TYPE (node1) != GSK_TEXTURE_NODE ||
|
||||
GSK_RENDER_NODE_TYPE (node2) != GSK_TEXTURE_NODE)
|
||||
return FALSE;
|
||||
|
||||
if (gsk_texture_node_get_texture (node1) !=
|
||||
@@ -2957,10 +2968,10 @@ compute_phase_and_pos (float value, float *pos)
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node_legacy (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
{
|
||||
const PangoFont *font = gsk_text_node_get_font (node);
|
||||
const PangoGlyphInfo *glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
@@ -3097,234 +3108,6 @@ gsk_gl_render_job_visit_text_node_legacy (GskGLRenderJob *job,
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep this in sync with glyph_vertex_transcode in glyphy.vs.glsl */
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float g16hi;
|
||||
float g16lo;
|
||||
} EncodedGlyph;
|
||||
|
||||
static inline unsigned int
|
||||
glyph_encode (guint atlas_x , /* 7 bits */
|
||||
guint atlas_y, /* 7 bits */
|
||||
guint corner_x, /* 1 bit */
|
||||
guint corner_y, /* 1 bit */
|
||||
guint nominal_w, /* 6 bits */
|
||||
guint nominal_h) /* 6 bits */
|
||||
{
|
||||
guint x, y;
|
||||
|
||||
g_assert (0 == (atlas_x & ~0x7F));
|
||||
g_assert (0 == (atlas_y & ~0x7F));
|
||||
g_assert (0 == (corner_x & ~1));
|
||||
g_assert (0 == (corner_y & ~1));
|
||||
g_assert (0 == (nominal_w & ~0x3F));
|
||||
g_assert (0 == (nominal_h & ~0x3F));
|
||||
|
||||
x = (((atlas_x << 6) | nominal_w) << 1) | corner_x;
|
||||
y = (((atlas_y << 6) | nominal_h) << 1) | corner_y;
|
||||
|
||||
return (x << 16) | y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
encoded_glyph_init (EncodedGlyph *eg,
|
||||
float x,
|
||||
float y,
|
||||
guint corner_x,
|
||||
guint corner_y,
|
||||
const GskGLGlyphyValue *gi)
|
||||
{
|
||||
guint encoded = glyph_encode (gi->atlas_x, gi->atlas_y, corner_x, corner_y, gi->nominal_w, gi->nominal_h);
|
||||
|
||||
eg->x = x;
|
||||
eg->y = y;
|
||||
eg->g16hi = encoded >> 16;
|
||||
eg->g16lo = encoded & 0xFFFF;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_encoded_glyph (GskGLDrawVertex *vertices,
|
||||
const EncodedGlyph *eg,
|
||||
const guint16 c[4])
|
||||
{
|
||||
*vertices = (GskGLDrawVertex) { .position = { eg->x, eg->y}, .uv = { eg->g16hi, eg->g16lo}, .color = { c[0], c[1], c[2], c[3] } };
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
const graphene_point_t *offset;
|
||||
const PangoGlyphInfo *glyphs;
|
||||
const PangoGlyphInfo *gi;
|
||||
GskGLGlyphyLibrary *library;
|
||||
GskGLCommandBatch *batch;
|
||||
PangoFont *font;
|
||||
GskGLDrawVertex *vertices;
|
||||
const guint16 *c;
|
||||
GskGLGlyphyKey lookup;
|
||||
guint16 cc[4];
|
||||
float x;
|
||||
float y;
|
||||
guint last_texture = 0;
|
||||
guint num_glyphs;
|
||||
guint used = 0;
|
||||
guint i;
|
||||
int x_position = 0;
|
||||
float font_scale;
|
||||
gboolean embolden;
|
||||
const PangoMatrix *matrix;
|
||||
|
||||
#define GRID_SIZE 20
|
||||
|
||||
g_assert (!gsk_text_node_has_color_glyphs (node));
|
||||
|
||||
if (!(num_glyphs = gsk_text_node_get_num_glyphs (node)))
|
||||
return;
|
||||
|
||||
if (RGBA_IS_CLEAR (color))
|
||||
return;
|
||||
|
||||
font = (PangoFont *)gsk_text_node_get_font (node);
|
||||
|
||||
embolden = gsk_text_node_get_font_embolden (node);
|
||||
matrix = gsk_text_node_get_font_matrix (node);
|
||||
|
||||
glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
library = job->driver->glyphy_library;
|
||||
offset = gsk_text_node_get_offset (node);
|
||||
x = offset->x + job->offset_x;
|
||||
y = offset->y + job->offset_y;
|
||||
|
||||
rgba_to_half (color, cc);
|
||||
c = cc;
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, glyphy));
|
||||
|
||||
batch = gsk_gl_command_queue_get_batch (job->command_queue);
|
||||
vertices = gsk_gl_command_queue_add_n_vertices (job->command_queue, num_glyphs);
|
||||
|
||||
lookup.font = gsk_gl_glyphy_library_get_font_key (font);
|
||||
font_scale = gsk_gl_glyphy_library_get_font_scale (font);
|
||||
|
||||
for (i = 0, gi = glyphs; i < num_glyphs; i++, gi++)
|
||||
{
|
||||
const GskGLGlyphyValue *glyph;
|
||||
float cx = 0, cy = 0;
|
||||
guint texture_id;
|
||||
|
||||
lookup.glyph = gi->glyph;
|
||||
texture_id = gsk_gl_glyphy_library_lookup_or_add (library, &lookup, font, &glyph);
|
||||
|
||||
if G_UNLIKELY (texture_id == 0)
|
||||
continue;
|
||||
|
||||
if G_UNLIKELY (last_texture != texture_id || batch->draw.vbo_count + GSK_GL_N_VERTICES > 0xffff)
|
||||
{
|
||||
if G_LIKELY (last_texture != 0)
|
||||
{
|
||||
guint vbo_offset = batch->draw.vbo_offset + batch->draw.vbo_count;
|
||||
|
||||
/* Since we have batched added our VBO vertices to avoid repeated
|
||||
* calls to the buffer, we need to manually tweak the vbo offset
|
||||
* of the new batch as otherwise it will point at the end of our
|
||||
* vbo array.
|
||||
*/
|
||||
gsk_gl_render_job_split_draw (job);
|
||||
batch = gsk_gl_command_queue_get_batch (job->command_queue);
|
||||
batch->draw.vbo_offset = vbo_offset;
|
||||
}
|
||||
|
||||
gsk_gl_program_set_uniform4i (job->current_program,
|
||||
UNIFORM_GLYPHY_ATLAS_INFO, 0,
|
||||
GSK_GL_TEXTURE_LIBRARY (library)->atlas_width,
|
||||
GSK_GL_TEXTURE_LIBRARY (library)->atlas_height,
|
||||
library->item_w,
|
||||
library->item_h_q);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
texture_id);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_GAMMA_ADJUST, 0,
|
||||
1.0);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_CONTRAST, 0,
|
||||
1.0);
|
||||
|
||||
/* 0.0208 is the value used by freetype for synthetic emboldening */
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_BOLDNESS, 0,
|
||||
embolden ? 0.0208 * GRID_SIZE : 0.0);
|
||||
|
||||
#if 0
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_OUTLINE_THICKNESS, 0,
|
||||
1.0);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_OUTLINE, 0,
|
||||
1.0);
|
||||
#endif
|
||||
|
||||
last_texture = texture_id;
|
||||
}
|
||||
|
||||
cx = (float)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
if G_UNLIKELY (gi->geometry.y_offset != 0)
|
||||
cy = (float)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
|
||||
x_position += gi->geometry.width;
|
||||
|
||||
EncodedGlyph encoded[4];
|
||||
#define ENCODE_CORNER(_cx, _cy) \
|
||||
G_STMT_START { \
|
||||
float _dx = _cx * (glyph->extents.max_x - glyph->extents.min_x); \
|
||||
float _dy = _cy * (glyph->extents.max_y - glyph->extents.min_y); \
|
||||
float _vx = x + cx + font_scale * (glyph->extents.min_x + matrix->xx * _dx + matrix->xy * _dy); \
|
||||
float _vy = y + cy - font_scale * (glyph->extents.min_y + matrix->yx * _dx + matrix->yy * _dy); \
|
||||
encoded_glyph_init (&encoded[_cx * 2 + _cy], _vx, _vy, _cx, _cy, glyph); \
|
||||
} G_STMT_END
|
||||
ENCODE_CORNER (0, 0);
|
||||
ENCODE_CORNER (0, 1);
|
||||
ENCODE_CORNER (1, 0);
|
||||
ENCODE_CORNER (1, 1);
|
||||
#undef ENCODE_CORNER
|
||||
|
||||
add_encoded_glyph (vertices++, &encoded[0], c);
|
||||
add_encoded_glyph (vertices++, &encoded[1], c);
|
||||
add_encoded_glyph (vertices++, &encoded[2], c);
|
||||
|
||||
add_encoded_glyph (vertices++, &encoded[1], c);
|
||||
add_encoded_glyph (vertices++, &encoded[2], c);
|
||||
add_encoded_glyph (vertices++, &encoded[3], c);
|
||||
|
||||
batch->draw.vbo_count += GSK_GL_N_VERTICES;
|
||||
used++;
|
||||
}
|
||||
|
||||
if (used != num_glyphs)
|
||||
gsk_gl_command_queue_retract_n_vertices (job->command_queue, num_glyphs - used);
|
||||
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
{
|
||||
if (job->use_glyphy && !gsk_text_node_has_color_glyphs (node))
|
||||
gsk_gl_render_job_visit_text_node_glyphy (job, node, color);
|
||||
else
|
||||
gsk_gl_render_job_visit_text_node_legacy (job, node, color, force_color);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -3335,7 +3118,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_get_node_type (shadow_child) == GSK_COLOR_MATRIX_NODE &&
|
||||
if (GSK_RENDER_NODE_TYPE (shadow_child) == GSK_COLOR_MATRIX_NODE &&
|
||||
!color_matrix_modifies_alpha (shadow_child))
|
||||
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
|
||||
|
||||
@@ -3355,7 +3138,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
|
||||
continue;
|
||||
|
||||
if (shadow->radius == 0 &&
|
||||
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
|
||||
GSK_RENDER_NODE_TYPE (shadow_child) == GSK_TEXT_NODE)
|
||||
{
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
@@ -3549,6 +3332,53 @@ 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)
|
||||
@@ -3558,6 +3388,17 @@ 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;
|
||||
@@ -4178,7 +4019,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_get_node_type (node))
|
||||
switch (GSK_RENDER_NODE_TYPE (node))
|
||||
{
|
||||
case GSK_BLEND_NODE:
|
||||
gsk_gl_render_job_visit_blend_node (job, node);
|
||||
@@ -4231,12 +4072,12 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
|
||||
|
||||
if (i + 1 < n_children &&
|
||||
job->current_clip->is_fully_contained &&
|
||||
gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE)
|
||||
GSK_RENDER_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_get_node_type (grandchild) == GSK_COLOR_NODE &&
|
||||
gsk_render_node_get_node_type (child2) == GSK_BORDER_NODE &&
|
||||
if (GSK_RENDER_NODE_TYPE (grandchild) == GSK_COLOR_NODE &&
|
||||
GSK_RENDER_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)))
|
||||
@@ -4390,7 +4231,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
|
||||
if (GSK_RENDER_NODE_TYPE (node) == GSK_TEXTURE_NODE &&
|
||||
!offscreen->force_offscreen)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
@@ -4708,15 +4549,6 @@ gsk_gl_render_job_set_debug_fallback (GskGLRenderJob *job,
|
||||
job->debug_fallback = !!debug_fallback;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_render_job_set_use_glyphy (GskGLRenderJob *job,
|
||||
gboolean use_glyphy)
|
||||
{
|
||||
g_return_if_fail (job != NULL);
|
||||
|
||||
job->use_glyphy = !!use_glyphy;
|
||||
}
|
||||
|
||||
static int
|
||||
get_framebuffer_format (GdkGLContext *context,
|
||||
guint framebuffer)
|
||||
@@ -4772,8 +4604,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;
|
||||
job->clip = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderClip), 16);
|
||||
job->modelview = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderModelview), 16);
|
||||
clips_init (&job->clip);
|
||||
modelviews_init (&job->modelview);
|
||||
job->framebuffer = framebuffer;
|
||||
job->clear_framebuffer = !!clear_framebuffer;
|
||||
job->default_framebuffer = default_framebuffer;
|
||||
@@ -4823,16 +4655,16 @@ gsk_gl_render_job_free (GskGLRenderJob *job)
|
||||
job->current_modelview = NULL;
|
||||
job->current_clip = NULL;
|
||||
|
||||
while (job->modelview->len > 0)
|
||||
while (job->modelview.end > job->modelview.start)
|
||||
{
|
||||
GskGLRenderModelview *modelview = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len-1);
|
||||
GskGLRenderModelview *modelview = job->modelview.end-1;
|
||||
g_clear_pointer (&modelview->transform, gsk_transform_unref);
|
||||
job->modelview->len--;
|
||||
job->modelview.end--;
|
||||
}
|
||||
|
||||
g_clear_object (&job->driver);
|
||||
g_clear_pointer (&job->region, cairo_region_destroy);
|
||||
g_clear_pointer (&job->modelview, g_array_unref);
|
||||
g_clear_pointer (&job->clip, g_array_unref);
|
||||
modelviews_clear (&job->modelview);
|
||||
clips_clear (&job->clip);
|
||||
g_free (job);
|
||||
}
|
||||
|
||||
@@ -35,5 +35,4 @@ void gsk_gl_render_job_render_flipped (GskGLRenderJob *job
|
||||
GskRenderNode *root);
|
||||
void gsk_gl_render_job_set_debug_fallback (GskGLRenderJob *job,
|
||||
gboolean debug_fallback);
|
||||
void gsk_gl_render_job_set_use_glyphy (GskGLRenderJob *job,
|
||||
gboolean use_glyphy);
|
||||
|
||||
|
||||
@@ -36,14 +36,9 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskGLTextureAtlas
|
||||
{
|
||||
/* Used by Glyph/Icons */
|
||||
struct stbrp_context context;
|
||||
struct stbrp_node *nodes;
|
||||
|
||||
/* Used by Glyphy */
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
@@ -53,6 +48,7 @@ typedef struct _GskGLTextureAtlas
|
||||
* But are now unused.
|
||||
*/
|
||||
int unused_pixels;
|
||||
|
||||
} GskGLTextureAtlas;
|
||||
|
||||
typedef struct _GskGLTextureAtlasEntry
|
||||
|
||||
@@ -36,7 +36,6 @@ typedef struct _GskGLCompiler GskGLCompiler;
|
||||
typedef struct _GskGLDrawVertex GskGLDrawVertex;
|
||||
typedef struct _GskGLRenderTarget GskGLRenderTarget;
|
||||
typedef struct _GskGLGlyphLibrary GskGLGlyphLibrary;
|
||||
typedef struct _GskGLGlyphyLibrary GskGLGlyphyLibrary;
|
||||
typedef struct _GskGLIconLibrary GskGLIconLibrary;
|
||||
typedef struct _GskGLProgram GskGLProgram;
|
||||
typedef struct _GskGLRenderJob GskGLRenderJob;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
uniform ivec4 u_atlas_info;
|
||||
|
||||
#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos
|
||||
#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos
|
||||
#define GLYPHY_DEMO_EXTRA_ARGS , u_source, u_atlas_info, gi.atlas_pos
|
||||
|
||||
vec4
|
||||
glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS)
|
||||
{
|
||||
ivec2 item_geom = _atlas_info.zw;
|
||||
vec2 pos = (vec2 (_atlas_pos.xy * item_geom +
|
||||
ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) +
|
||||
+ vec2 (.5, .5)) / vec2(_atlas_info.xy);
|
||||
return GskTexture (_tex, pos);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// FRAGMENT_SHADER:
|
||||
// glyphy.fs.glsl
|
||||
|
||||
uniform float u_contrast;
|
||||
uniform float u_gamma_adjust;
|
||||
uniform float u_outline_thickness;
|
||||
uniform bool u_outline;
|
||||
uniform float u_boldness;
|
||||
|
||||
_IN_ vec4 v_glyph;
|
||||
_IN_ vec4 final_color;
|
||||
|
||||
#define SQRT2 1.4142135623730951
|
||||
#define SQRT2_INV 0.70710678118654757 /* 1 / sqrt(2.) */
|
||||
|
||||
struct glyph_info_t {
|
||||
ivec2 nominal_size;
|
||||
ivec2 atlas_pos;
|
||||
};
|
||||
|
||||
glyph_info_t
|
||||
glyph_info_decode (vec4 v)
|
||||
{
|
||||
glyph_info_t gi;
|
||||
gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4;
|
||||
gi.atlas_pos = ivec2 (v_glyph.zw) / 256;
|
||||
return gi;
|
||||
}
|
||||
|
||||
float
|
||||
antialias (float d)
|
||||
{
|
||||
return smoothstep (-.75, +.75, d);
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
vec2 p = v_glyph.xy;
|
||||
glyph_info_t gi = glyph_info_decode (v_glyph);
|
||||
|
||||
/* isotropic antialiasing */
|
||||
vec2 dpdx = dFdx (p);
|
||||
vec2 dpdy = dFdy (p);
|
||||
float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_INV;
|
||||
|
||||
float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);
|
||||
gsdist -= u_boldness;
|
||||
float sdist = gsdist / m * u_contrast;
|
||||
|
||||
if (u_outline)
|
||||
sdist = abs (sdist) - u_outline_thickness * .5;
|
||||
|
||||
if (sdist > 1.)
|
||||
discard;
|
||||
|
||||
float alpha = antialias (-sdist);
|
||||
if (u_gamma_adjust != 1.)
|
||||
alpha = pow (alpha, 1./u_gamma_adjust);
|
||||
|
||||
gskSetOutputColor(final_color * alpha);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// VERTEX_SHADER:
|
||||
// glyphy.vs.glsl
|
||||
|
||||
_OUT_ vec4 v_glyph;
|
||||
_OUT_ vec4 final_color;
|
||||
|
||||
// Keep this in sync with glyph_encode in gskglrenderjob.c
|
||||
vec4
|
||||
glyph_vertex_transcode (vec2 v)
|
||||
{
|
||||
ivec2 g = ivec2 (v);
|
||||
ivec2 corner = ivec2 (mod (v, 2.));
|
||||
g /= 2;
|
||||
ivec2 nominal_size = ivec2 (mod (vec2(g), 64.));
|
||||
return vec4 (corner * nominal_size, g * 4);
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
v_glyph = glyph_vertex_transcode(aUv);
|
||||
vUv = v_glyph.zw;
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
final_color = gsk_scaled_premultiply(aColor, u_alpha);
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#extension GL_OES_standard_derivatives : enable
|
||||
|
||||
#ifndef GSK_LEGACY
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
+12
-16
@@ -19,8 +19,10 @@
|
||||
|
||||
#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
|
||||
@@ -63,9 +65,6 @@ 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];
|
||||
@@ -84,11 +83,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -160,6 +155,13 @@ 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) {
|
||||
@@ -223,7 +225,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;
|
||||
@@ -323,7 +325,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
||||
return res;
|
||||
}
|
||||
|
||||
static int rect_height_compare(const void *a, const void *b)
|
||||
static int STBRP__CDECL 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;
|
||||
@@ -334,19 +336,13 @@ static int rect_height_compare(const void *a, const void *b)
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int rect_original_order(const void *a, const void *b)
|
||||
static int STBRP__CDECL 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;
|
||||
|
||||
+13
-5
@@ -1,9 +1,15 @@
|
||||
// stb_rect_pack.h - v0.99 - public domain - rectangle packing
|
||||
// stb_rect_pack.h - v1.01 - 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).
|
||||
@@ -31,9 +37,12 @@
|
||||
//
|
||||
// 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
|
||||
@@ -72,11 +81,10 @@ 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;
|
||||
#else
|
||||
typedef unsigned short stbrp_coord;
|
||||
#endif
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
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
|
||||
|
||||
+181
-24
@@ -2330,30 +2330,6 @@ 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,
|
||||
@@ -2475,6 +2451,187 @@ 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
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "gskpathopprivate.h"
|
||||
#include "gskpath.h"
|
||||
#include "gskpathprivate.h"
|
||||
#include "gskboundingboxprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -188,19 +187,6 @@ 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
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ static const GdkDebugKey gsk_debug_keys[] = {
|
||||
{ "full-redraw", GSK_DEBUG_FULL_REDRAW, "Force full redraws" },
|
||||
{ "sync", GSK_DEBUG_SYNC, "Sync after each frame" },
|
||||
{ "staging", GSK_DEBUG_STAGING, "Use a staging image for texture upload (Vulkan only)" },
|
||||
{ "no-glyphy", GSK_DEBUG_NO_GLYPHY, "Don't use GPU for glyph rendering (OpenGL only)", TRUE },
|
||||
};
|
||||
|
||||
static guint gsk_debug_flags;
|
||||
|
||||
@@ -19,8 +19,7 @@ typedef enum {
|
||||
GSK_DEBUG_GEOMETRY = 1 << 9,
|
||||
GSK_DEBUG_FULL_REDRAW = 1 << 10,
|
||||
GSK_DEBUG_SYNC = 1 << 11,
|
||||
GSK_DEBUG_STAGING = 1 << 12,
|
||||
GSK_DEBUG_NO_GLYPHY = 1 << 13
|
||||
GSK_DEBUG_STAGING = 1 << 12
|
||||
} GskDebugFlags;
|
||||
|
||||
#define GSK_DEBUG_ANY ((1 << 13) - 1)
|
||||
|
||||
-1712
File diff suppressed because it is too large
Load Diff
@@ -56,27 +56,5 @@ gboolean gsk_path_foreach_with_tolerance (GskPath
|
||||
void gsk_path_builder_add_contour (GskPathBuilder *builder,
|
||||
GskContour *contour);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSK_PATH_INTERSECTION_NONE,
|
||||
GSK_PATH_INTERSECTION_NORMAL,
|
||||
GSK_PATH_INTERSECTION_START,
|
||||
GSK_PATH_INTERSECTION_END,
|
||||
} GskPathIntersection;
|
||||
|
||||
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
|
||||
|
||||
|
||||
+12
-7
@@ -287,15 +287,21 @@ 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);
|
||||
|
||||
g_atomic_ref_count_inc (&node->ref_count);
|
||||
|
||||
return node;
|
||||
return _gsk_render_node_ref (node);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gsk_render_node_unref:
|
||||
* @node: (transfer full): a `GskRenderNode`
|
||||
@@ -306,12 +312,11 @@ gsk_render_node_ref (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));
|
||||
|
||||
if (g_atomic_ref_count_dec (&node->ref_count))
|
||||
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
|
||||
_gsk_render_node_unref (node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@
|
||||
#endif
|
||||
#include <hb-ot.h>
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
#include <pango/pangofc-font.h>
|
||||
#endif
|
||||
|
||||
/* maximal number of rectangles we keep in a diff region before we throw
|
||||
* the towel and just use the bounding box of the parent node.
|
||||
* Meant to avoid performance corner cases.
|
||||
@@ -5464,8 +5460,6 @@ struct _GskTextNode
|
||||
|
||||
PangoFont *font;
|
||||
gboolean has_color_glyphs;
|
||||
gboolean embolden;
|
||||
PangoMatrix matrix;
|
||||
|
||||
GdkRGBA color;
|
||||
graphene_point_t offset;
|
||||
@@ -5474,37 +5468,6 @@ struct _GskTextNode
|
||||
PangoGlyphInfo *glyphs;
|
||||
};
|
||||
|
||||
static void
|
||||
get_synthetic_font_params (PangoFont *font,
|
||||
gboolean *embolden,
|
||||
PangoMatrix *matrix)
|
||||
{
|
||||
*embolden = FALSE;
|
||||
*matrix = (PangoMatrix) PANGO_MATRIX_INIT;
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
if (PANGO_IS_FC_FONT (font))
|
||||
{
|
||||
FcPattern *pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
||||
FcBool b;
|
||||
FcMatrix mat;
|
||||
FcMatrix *m;
|
||||
|
||||
if (FcPatternGetBool (pattern, FC_EMBOLDEN, 0, &b) == FcResultMatch)
|
||||
*embolden = b;
|
||||
|
||||
FcMatrixInit (&mat);
|
||||
for (int i = 0; FcPatternGetMatrix (pattern, FC_MATRIX, i, &m) == FcResultMatch; i++)
|
||||
FcMatrixMultiply (&mat, &mat, m);
|
||||
|
||||
matrix->xx = mat.xx;
|
||||
matrix->xy = mat.xy;
|
||||
matrix->yx = mat.yx;
|
||||
matrix->yy = mat.yy;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_text_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
@@ -5630,8 +5593,6 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->offset = *offset;
|
||||
self->has_color_glyphs = FALSE;
|
||||
|
||||
get_synthetic_font_params (self->font, &self->embolden, &self->matrix);
|
||||
|
||||
glyph_infos = g_malloc_n (glyphs->num_glyphs, sizeof (PangoGlyphInfo));
|
||||
|
||||
n = 0;
|
||||
@@ -5764,22 +5725,6 @@ gsk_text_node_get_offset (const GskRenderNode *node)
|
||||
return &self->offset;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_text_node_get_font_embolden (const GskRenderNode *node)
|
||||
{
|
||||
const GskTextNode *self = (const GskTextNode *) node;
|
||||
|
||||
return self->embolden;
|
||||
}
|
||||
|
||||
const PangoMatrix *
|
||||
gsk_text_node_get_font_matrix (const GskRenderNode *node)
|
||||
{
|
||||
const GskTextNode *self = (const GskTextNode *) node;
|
||||
|
||||
return &self->matrix;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ GSK_BLUR_NODE */
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#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"
|
||||
@@ -3169,45 +3170,20 @@ append_texture_param (Printer *p,
|
||||
g_hash_table_insert (p->named_textures, texture, new_name);
|
||||
}
|
||||
|
||||
switch (gdk_texture_get_format (texture))
|
||||
switch (gdk_memory_format_get_depth (gdk_texture_get_format (texture)))
|
||||
{
|
||||
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:
|
||||
case GDK_MEMORY_U8:
|
||||
case GDK_MEMORY_U16:
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_string_append (p->str, "url(\"data:image/png;base64,");
|
||||
break;
|
||||
|
||||
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:
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
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,6 +21,9 @@ 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;
|
||||
@@ -57,6 +60,8 @@ 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,
|
||||
@@ -87,11 +92,15 @@ gboolean gsk_container_node_is_disjoint (const GskRenderNode
|
||||
|
||||
gboolean gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
|
||||
|
||||
gboolean gsk_text_node_get_font_embolden (const GskRenderNode *node);
|
||||
|
||||
const PangoMatrix *
|
||||
gsk_text_node_get_font_matrix (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
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@ gsk_private_gl_shaders = [
|
||||
'gl/resources/custom.glsl',
|
||||
'gl/resources/filled_border.glsl',
|
||||
'gl/resources/mask.glsl',
|
||||
'gl/resources/glyphy.atlas.glsl',
|
||||
'gl/resources/glyphy.fs.glsl',
|
||||
'gl/resources/glyphy.vs.glsl',
|
||||
]
|
||||
|
||||
gsk_public_sources = files([
|
||||
@@ -32,7 +29,6 @@ gsk_public_sources = files([
|
||||
'gskpath.c',
|
||||
'gskpathbuilder.c',
|
||||
'gskpathmeasure.c',
|
||||
'gskpathops.c',
|
||||
'gskpathparser.c',
|
||||
'gskpathpoint.c',
|
||||
'gskrenderer.c',
|
||||
@@ -49,7 +45,6 @@ gsk_private_sources = files([
|
||||
'gskcairoblur.c',
|
||||
'gskcontour.c',
|
||||
'gskcurve.c',
|
||||
'gskcurveintersect.c',
|
||||
'gskdebug.c',
|
||||
'gskprivate.c',
|
||||
'gskprofiler.c',
|
||||
@@ -59,7 +54,6 @@ gsk_private_sources = files([
|
||||
'gl/gskglcompiler.c',
|
||||
'gl/gskgldriver.c',
|
||||
'gl/gskglglyphlibrary.c',
|
||||
'gl/gskglglyphylibrary.c',
|
||||
'gl/gskgliconlibrary.c',
|
||||
'gl/gskglprogram.c',
|
||||
'gl/gskglrenderjob.c',
|
||||
@@ -200,7 +194,6 @@ gsk_deps = [
|
||||
cairo_dep,
|
||||
cairo_csi_dep,
|
||||
libgdk_dep,
|
||||
libglyphy_dep
|
||||
]
|
||||
|
||||
libgsk_f16c = static_library('gsk_f16c',
|
||||
|
||||
@@ -80,6 +80,15 @@ 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[] = {
|
||||
@@ -117,6 +126,17 @@ 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[] = {
|
||||
@@ -324,6 +344,7 @@ 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:
|
||||
@@ -331,6 +352,10 @@ 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,7 +714,9 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
+12
-3
@@ -1614,7 +1614,10 @@ insert_text_cb (GtkEditable *editable,
|
||||
return;
|
||||
|
||||
length = g_utf8_strlen (new_text, new_text_length);
|
||||
changed->text_changed (changed->data, "insert", *position - length, length, new_text);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1629,6 +1632,10 @@ 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);
|
||||
}
|
||||
@@ -1707,7 +1714,9 @@ insert_range_cb (GtkTextBuffer *buffer,
|
||||
position = gtk_text_iter_get_offset (iter);
|
||||
length = g_utf8_strlen (text, len);
|
||||
|
||||
changed->text_changed (changed->data, "insert", position - length, length, text);
|
||||
char *inserted_text = g_utf8_substring (text, 0, length);
|
||||
changed->text_changed (changed->data, "insert", position - length, length, inserted_text);
|
||||
g_free (inserted_text);
|
||||
|
||||
update_cursor (buffer, changed);
|
||||
}
|
||||
@@ -1784,7 +1793,7 @@ buffer_changed (GtkWidget *widget,
|
||||
if (changed->buffer)
|
||||
{
|
||||
g_object_ref (changed->buffer);
|
||||
g_signal_connect (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
|
||||
g_signal_connect_after (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,6 +171,9 @@ 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;
|
||||
|
||||
|
||||
@@ -12833,9 +12833,12 @@ gtk_tree_view_is_blank_at_pos (GtkTreeView *tree_view,
|
||||
*column = real_column;
|
||||
|
||||
gtk_tree_model_get_iter (priv->model, &iter, real_path);
|
||||
if (!_gtk_tree_view_find_node (tree_view, real_path, &tree, &node))
|
||||
_gtk_tree_view_find_node (tree_view, real_path, &tree, &node);
|
||||
if (node == NULL)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
if (!path)
|
||||
gtk_tree_path_free (real_path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 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.
Binary file not shown.
Binary file not shown.
@@ -209,6 +209,7 @@
|
||||
#include <gtk/gtkpopover.h>
|
||||
#include <gtk/gtkpopovermenu.h>
|
||||
#include <gtk/gtkpopovermenubar.h>
|
||||
#include <gtk/gtkprintdialog.h>
|
||||
#include <gtk/print/gtkprintcontext.h>
|
||||
#include <gtk/print/gtkprintoperation.h>
|
||||
#include <gtk/print/gtkprintoperationpreview.h>
|
||||
|
||||
@@ -832,6 +832,7 @@ static const char *role_names[] = {
|
||||
[GTK_ACCESSIBLE_ROLE_WINDOW] = NC_("accessibility", "window"),
|
||||
[GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON] = NC_("accessibility", "toggle button"),
|
||||
[GTK_ACCESSIBLE_ROLE_APPLICATION] = NC_("accessibility", "application"),
|
||||
[GTK_ACCESSIBLE_ROLE_PARAGRAPH] = NC_("accessibility", "paragraph"),
|
||||
};
|
||||
|
||||
/*< private >
|
||||
@@ -912,6 +913,7 @@ static struct {
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_APPLICATION },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_DOCUMENT },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_GENERIC },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_PARAGRAPH },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_PRESENTATION },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_RANGE },
|
||||
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_ROW_GROUP },
|
||||
|
||||
@@ -46,7 +46,7 @@ static gboolean
|
||||
gtk_accessible_range_default_set_current_value (GtkAccessibleRange *accessible_range,
|
||||
double value)
|
||||
{
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1103,6 +1103,7 @@ static guint8 naming[] = {
|
||||
[GTK_ACCESSIBLE_ROLE_WINDOW] = NAME_FROM_AUTHOR,
|
||||
[GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON] = NAME_FROM_AUTHOR|GTK_ACCESSIBLE_NAME_REQUIRED,
|
||||
[GTK_ACCESSIBLE_ROLE_APPLICATION] = NAME_FROM_AUTHOR|GTK_ACCESSIBLE_NAME_REQUIRED,
|
||||
[GTK_ACCESSIBLE_ROLE_PARAGRAPH] = GTK_ACCESSIBLE_NAME_PROHIBITED,
|
||||
};
|
||||
|
||||
/* < private >
|
||||
|
||||
@@ -511,7 +511,7 @@ gtk_color_dialog_button_set_dialog (GtkColorDialogButton *self,
|
||||
*
|
||||
* This function is what should be used to obtain
|
||||
* the color that was chosen by the user. To get
|
||||
* informed about changes, listen to "notify::color".
|
||||
* informed about changes, listen to "notify::rgba".
|
||||
*
|
||||
* Returns: the color
|
||||
*
|
||||
|
||||
+4
-1
@@ -1362,6 +1362,8 @@ typedef enum {
|
||||
* @GTK_ACCESSIBLE_ROLE_APPLICATION: A toplevel element of a graphical user interface.
|
||||
* This is the role that GTK uses by default for windows.
|
||||
* Since: 4.12
|
||||
* @GTK_ACCESSIBLE_ROLE_PARAGRAPH: A paragraph of content.
|
||||
* Since: 4.14
|
||||
*
|
||||
* The accessible role for a [iface@Accessible] implementation.
|
||||
*
|
||||
@@ -1448,7 +1450,8 @@ typedef enum {
|
||||
GTK_ACCESSIBLE_ROLE_WIDGET,
|
||||
GTK_ACCESSIBLE_ROLE_WINDOW,
|
||||
GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON GDK_AVAILABLE_ENUMERATOR_IN_4_10,
|
||||
GTK_ACCESSIBLE_ROLE_APPLICATION GDK_AVAILABLE_ENUMERATOR_IN_4_12
|
||||
GTK_ACCESSIBLE_ROLE_APPLICATION GDK_AVAILABLE_ENUMERATOR_IN_4_12,
|
||||
GTK_ACCESSIBLE_ROLE_PARAGRAPH GDK_AVAILABLE_ENUMERATOR_IN_4_14
|
||||
} GtkAccessibleRole;
|
||||
|
||||
/**
|
||||
|
||||
@@ -177,6 +177,7 @@ response_cb (GDBusConnection *connection,
|
||||
self->custom_files = NULL;
|
||||
for (i = 0; uris[i]; i++)
|
||||
self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i]));
|
||||
self->custom_files = g_slist_reverse (self->custom_files);
|
||||
|
||||
g_free (uris);
|
||||
g_variant_unref (response_data);
|
||||
|
||||
@@ -4772,7 +4772,7 @@ gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref_sink (filter);
|
||||
g_object_ref (filter);
|
||||
|
||||
g_list_store_append (impl->filters, filter);
|
||||
g_object_unref (filter);
|
||||
@@ -6000,7 +6000,7 @@ set_current_filter (GtkFileChooserWidget *impl,
|
||||
g_object_unref (impl->current_filter);
|
||||
impl->current_filter = filter;
|
||||
if (impl->current_filter)
|
||||
g_object_ref_sink (impl->current_filter);
|
||||
g_object_ref (impl->current_filter);
|
||||
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (impl->filter_combo), filter_index);
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ struct _GtkMenuTrackerItem
|
||||
char *action_namespace;
|
||||
char *action_and_target;
|
||||
GMenuItem *item;
|
||||
GtkMenuTrackerItemRole role : 4;
|
||||
guint role : 4; /* GtkMenuTrackerItemRole */
|
||||
guint is_separator : 1;
|
||||
guint can_activate : 1;
|
||||
guint sensitive : 1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 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 (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/print/gtkprintsettings.h>
|
||||
#include <gtk/print/gtkpagesetup.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkPrintSetup GtkPrintSetup;
|
||||
|
||||
#define GTK_TYPE_PRINT_SETUP (gtk_print_setup_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GType gtk_print_setup_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPrintSetup *gtk_print_setup_ref (GtkPrintSetup *setup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_setup_unref (GtkPrintSetup *setup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPrintSettings *
|
||||
gtk_print_setup_get_print_settings (GtkPrintSetup *setup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPageSetup * gtk_print_setup_get_page_setup (GtkPrintSetup *setup);
|
||||
|
||||
|
||||
#define GTK_TYPE_PRINT_DIALOG (gtk_print_dialog_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
G_DECLARE_FINAL_TYPE (GtkPrintDialog, gtk_print_dialog, GTK, PRINT_DIALOG, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPrintDialog *gtk_print_dialog_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
const char * gtk_print_dialog_get_title (GtkPrintDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_set_title (GtkPrintDialog *self,
|
||||
const char *title);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
const char * gtk_print_dialog_get_accept_label (GtkPrintDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_set_accept_label (GtkPrintDialog *self,
|
||||
const char *accept_label);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gtk_print_dialog_get_modal (GtkPrintDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_set_modal (GtkPrintDialog *self,
|
||||
gboolean modal);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPageSetup * gtk_print_dialog_get_page_setup (GtkPrintDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_set_page_setup (GtkPrintDialog *self,
|
||||
GtkPageSetup *page_setup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPrintSettings * gtk_print_dialog_get_print_settings (GtkPrintDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_set_print_settings (GtkPrintDialog *self,
|
||||
GtkPrintSettings *print_settings);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_setup (GtkPrintDialog *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GtkPrintSetup *gtk_print_dialog_setup_finish (GtkPrintDialog *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_print (GtkPrintDialog *self,
|
||||
GtkWindow *parent,
|
||||
GtkPrintSetup *setup,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GOutputStream * gtk_print_dialog_print_finish (GtkPrintDialog *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gtk_print_dialog_print_file (GtkPrintDialog *self,
|
||||
GtkWindow *parent,
|
||||
GtkPrintSetup *setup,
|
||||
GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gtk_print_dialog_print_file_finish (GtkPrintDialog *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -70,7 +70,7 @@ typedef struct {
|
||||
CachedSizeX cached_size_x;
|
||||
CachedSizeY cached_size_y;
|
||||
|
||||
GtkSizeRequestMode request_mode : 3;
|
||||
guint request_mode : 3; /* GtkSizeRequestMode */
|
||||
guint request_mode_valid : 1;
|
||||
struct {
|
||||
guint n_cached_requests : 15;
|
||||
|
||||
+1
-1
@@ -6536,7 +6536,7 @@ gtk_widget_update_default_pango_context (GtkWidget *widget)
|
||||
return;
|
||||
|
||||
if (gtk_widget_update_pango_context (widget, context, _gtk_widget_get_direction (widget)))
|
||||
gtk_widget_queue_draw (widget);
|
||||
gtk_widget_queue_resize (widget);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-1
@@ -310,6 +310,7 @@ gtk_public_sources = files([
|
||||
'gtkpopover.c',
|
||||
'gtkpopovermenu.c',
|
||||
'gtkpopovermenubar.c',
|
||||
'gtkprintdialog.c',
|
||||
'gtkprogressbar.c',
|
||||
'gtkpropertylookuplistmodel.c',
|
||||
'gtkrange.c',
|
||||
@@ -549,6 +550,7 @@ gtk_public_headers = files([
|
||||
'gtkpopover.h',
|
||||
'gtkpopovermenu.h',
|
||||
'gtkpopovermenubar.h',
|
||||
'gtkprintdialog.h',
|
||||
'gtkprogressbar.h',
|
||||
'gtkrange.h',
|
||||
'gtkrecentmanager.h',
|
||||
@@ -853,20 +855,27 @@ else
|
||||
endif
|
||||
|
||||
foreach lang : [
|
||||
'bn',
|
||||
'de',
|
||||
'da',
|
||||
'fr',
|
||||
'es',
|
||||
'et',
|
||||
'fi',
|
||||
'hi',
|
||||
'hu',
|
||||
'it',
|
||||
'ja',
|
||||
'ko',
|
||||
'lt',
|
||||
'ms',
|
||||
'nb',
|
||||
'nl',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'sv',
|
||||
'th',
|
||||
'uk',
|
||||
'zh'
|
||||
]
|
||||
@@ -1017,7 +1026,6 @@ gtk_deps = [
|
||||
epoxy_dep,
|
||||
libm,
|
||||
graphene_dep,
|
||||
libglyphy_dep,
|
||||
]
|
||||
|
||||
if x11_enabled
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user