Compare commits

..

24 Commits

Author SHA1 Message Date
Matthias Clasen e2c7936ceb Store synthetic font params in the text node
This lets use reduce the overhead by doing the
fontconfig calls only once, instead of every
time.
2023-09-26 21:59:57 -04:00
Matthias Clasen 6846a5aaa7 movingtext: Avoid fontconfig overhead
Instead of redoing the pango layout every
frame, just scale the node.
2023-09-24 18:28:00 -04:00
Matthias Clasen 1cff54ea92 gsk: Make glyphy optional for now
Enable glyphy by default, but make it possible
to get the previous cairo rendering by setting
GSK_DEBUG=no-glyphy in the environment.

Keeping this optional will make it easier to
debug issues and compare output.
2023-09-24 17:47:21 -04:00
Matthias Clasen 72a704d145 Add an animated text example 2023-09-24 17:47:21 -04:00
Matthias Clasen e2969bec04 Add a font rendering test 2023-09-24 17:47:21 -04:00
Matthias Clasen 370c47e595 glyphy: Implement synthetic italic
Use the font matrix found in the FcPattern to
transform the quads we use to render the glyphs.

This makes Cantarell Italic come out just like
it does with freetype.
2023-09-24 17:47:21 -04:00
Matthias Clasen 922daf2ed7 glyphy: Update for api changes in glyphy
With this, synthetic bold fonts work as well
as they do with freetype.
2023-09-24 17:47:21 -04:00
Matthias Clasen f3b00d075e glyphy: Implement synthetic bold
When the font appears to be synthetic bold (as
indicated by th embolden property in FcPattern),
use glyphys boldness uniform to render the font
bolder.
2023-09-24 17:47:21 -04:00
Matthias Clasen c1d7a820ab glyphy: Remove glyphy debug code
We don't have a knob to turn this on, and it is
not really useful outside of glyphy itself, so
remove it.
2023-09-24 17:47:21 -04:00
Matthias Clasen c09f6a8041 glyphy: Simplify the path
Use path ops to simplify the path we get from
harfbuzz, since variable fonts often have overlapping
contours, and the glyphy shader can't handle those.
2023-09-24 17:47:21 -04:00
Matthias Clasen 6f3ee51371 build: Bump the harfbuzz requirement to 4.0
The hb_font_get_glyph_shape api was introduced
in 4.0.
2023-09-24 17:47:21 -04:00
Matthias Clasen 30c73365dd glyphy: Pencil in outline rendering 2023-09-24 17:47:21 -04:00
Matthias Clasen cc250beadc glyphy: Declare that we are using dFdx
GLES2 does not have these by default :(
2023-09-24 17:47:21 -04:00
Christian Hergert 73a82faad3 gsk/gl: Fix output color of glyphy fragment shader
This copied more or less what the coloring vertex shader
was doing in that we premultiply alpha. That changes how
we apply alpha in the fragment shader to match.

This fixes a white halo around the fonts.
2023-09-24 17:47:21 -04:00
Matthias Clasen a3d82174e6 glyphy: Make glyphy cache size-independent
Use a hb font at nominal size when generating sdf
contours, and use a cache key that is independent
of the size.
2023-09-24 17:47:21 -04:00
Christian Hergert ad9d916dfd gsk/gl: Start on basic glyphy renderjob integration
This doesn't work correctly yet, as there are lots of
bumps along the way to still smooth out.
2023-09-24 17:47:21 -04:00
Christian Hergert 5cadf635ab gsk/gl: Add a texture library for Glyphy
This adds a new texture library that can upload SDF data
from libglyphy into regions of a texture atlas so that it
can be accessed by Glyphy shaders in the appropriate place
and format.

Some of the placement positioning may seem odd in that it
needs to follow a certain format to be decoded from the
Glyphy shaders.
2023-09-24 17:47:21 -04:00
Christian Hergert 2d15c5e55f gsk/gl: Dispatch text_node to legacy vs glyphy
If the text node has color glyphs, then we need to dispatch
to the legacy form of rendering which uses FreeType/Cairo/etc
to upload glyphs to a rendered glyph cache.

Otherwise, we can dispatch to a new function which will
eventually use Glyphy to shape to SDF content and upload
to an alternate texture atlas.
2023-09-24 17:47:21 -04:00
Matthias Clasen 3195a1e6df build: Add a dependency on glyphy
We have a subproject, and we link statically
if we can, to avoid depending on a project
that is not generally packaged in distros.
2023-09-24 17:47:21 -04:00
Matthias Clasen b21a5d9a06 Add some tests for pathops 2023-09-24 17:47:21 -04:00
Matthias Clasen 01d844a994 Implement boolean operations on paths
Implement union, intersection, difference and
symmetric difference of two paths, as well as
simplification of a single path.
2023-09-24 17:47:21 -04:00
Matthias Clasen b41c45ab5b Add tests for gsk_curve_intersect 2023-09-24 17:47:21 -04:00
Matthias Clasen 6f97c02c4d curve: Add gsk_curve_intersect
Add a way to find the intersections of two curves.
We can handle some curve-line intersections directly,
the general case is handled via bisection.
2023-09-24 17:47:21 -04:00
Matthias Clasen fffa490280 curve: Some refactoring
Move cusp-related code to gskcurveintersect.c.
Add functions to find cusps and inflection points of cubics.
These will be used for intersections and in the stroker.
2023-09-24 17:47:21 -04:00
128 changed files with 6078 additions and 6987 deletions
+5 -12
View File
@@ -217,32 +217,25 @@ macos-x86_64:
MESON_FORCE_BACKTRACKE: 1
TMPDIR: /Users/Shared/work/tmp
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
CCACHE_DIR: /Users/Shared/work/ccache
PIP_CACHE_DIR: /Users/Shared/build/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
EXTRA_MESON_FLAGS: "-Dgobject-introspection:werror=false"
before_script:
# Not using ccache on purpose as it accelerates the build so much that it
# can trigger race conditions in the gobject-introspection subproject.
- bash .gitlab-ci/show-info-osx.sh
- /opt/macports/bin/python3.10 -m venv .venv
- python3 -m venv .venv
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
- ln -s /opt/bison/bin/bison .venv/bin
- ln -s /opt/ccache/ccache .venv/bin
- source .venv/bin/activate
- pip3 install meson==1.2.0
- pip3 install ninja==1.11.1
- pip3 install /Users/Shared/build/pkgs/PyGObject-3.44.0-cp310-cp310-macosx_10_13_x86_64.whl
/Users/Shared/build/pkgs/pycairo-1.23.0-cp310-cp310-macosx_10_13_x86_64.whl
script:
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
- meson setup ${COMMON_MESON_FLAGS}
-Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=enabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
-Dlibjpeg-turbo:simd=disabled
+1 -32
View File
@@ -1,7 +1,4 @@
Overview of Changes in 4.13.2, xx-xx-xxxx
=========================================
Overview of Changes in 4.13.1, 28-09-2023
Overview of Changes in 4.13.1, xx-xx-xxxx
=========================================
* GtkTooltip:
@@ -10,32 +7,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* GtkCenterLayout, GtkEntry, GtkSearchEntry:
- Fix some issues with baseline handling
* GtkColorButton, GtkFontButton:
- Propagate focus-on-click
* GtkFileChooser:
- Make "Visit file" scroll to the file
* GtkSwitch:
- Respect text direction
* GtkWindow:
- Don't assume titlebars are GtkHeaderBars
* Printing:
- Fix some problems with the portal implementation
- Add a new simple print API: GtkPrintDialog
* Paths:
- GskPathMeasure performance has been improved
- Add custom contours for circles, rounded rectangles and rectangles
- Simplify GskPathPoint handling
- gsk_path_point_get_closest_point now returns the distance as well
- Make GskPathBuilder simplify curves
* Input:
- Handle (some) single-key compose sequences
- Fix active state tracking with sensitivity changes and grabs
* GSK:
- Make the repeated gradients match between GL and cairo
@@ -44,13 +29,6 @@ Overview of Changes in 4.13.1, 28-09-2023
- Restrict an optimization to the cases where it is crrect
- Fix rendering of shadows with opacity
- The Vulkan renderer now requires Vulkan 1.2
- GL: Transition gradients unpremultiplied
- GL: Fix clipping of shadows
- GL: Some optimizations
- Broadway: Fix memory leaks in the renderer
* Wayland:
- Make activation more reliable
* macOS:
- Clamp damage regions to the surface size
@@ -65,29 +43,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* Build:
- Fix build problems with C++ compilers
* Deprecations:
- gtk_window_present_with_time
* Translation updates
Brazilian Portuguese
British English
Catalan
Chinese (China)
Czech
Danish
Dutch
Esperanto
Galician
Georgian
Italian
Korean
Latvian
Lithuanian
Persian
Polish
Punjabi
Slovenian
Turkish
Overview of Changes in 4.13.0, 25-08-2023
+2 -4
View File
@@ -34,7 +34,7 @@ transition (GtkWidget *widget,
{
DemoWidget *self = DEMO_WIDGET (widget);
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
gint64 now = g_get_monotonic_time ();
gtk_widget_queue_allocate (widget);
@@ -66,13 +66,11 @@ clicked (GtkGestureClick *gesture,
gpointer data)
{
DemoWidget *self = data;
GdkFrameClock *frame_clock;
if (self->tick_id != 0)
return;
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
self->start_time = g_get_monotonic_time ();
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
}
+1 -98
View File
@@ -2,13 +2,10 @@
*
* This demo shows how to use GskPath to draw shapes that are (a bit)
* more complex than a rounded rectangle.
*
* It also demonstrates printing to a stream with GtkPrintDialog.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <cairo-pdf.h>
#include "paintable.h"
@@ -168,89 +165,6 @@ gtk_logo_paintable_new (void)
return GDK_PAINTABLE (self);
}
static cairo_status_t
write_cairo (void *closure,
const unsigned char *data,
unsigned int length)
{
GOutputStream *stream = closure;
gsize written;
GError *error = NULL;
if (!g_output_stream_write_all (stream, data, length, &written, NULL, &error))
{
g_print ("Error writing pdf stream: %s\n", error->message);
g_error_free (error);
return CAIRO_STATUS_WRITE_ERROR;
}
return CAIRO_STATUS_SUCCESS;
}
static void
print_ready (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GOutputStream *stream;
GtkSnapshot *snapshot;
GdkPaintable *paintable;
GskRenderNode *node;
cairo_surface_t *surface;
cairo_t *cr;
stream = gtk_print_dialog_print_finish (dialog, result, &error);
if (stream == NULL)
{
g_print ("Failed to get output stream: %s\n", error->message);
g_error_free (error);
return;
}
snapshot = gtk_snapshot_new ();
paintable = gtk_picture_get_paintable (GTK_PICTURE (data));
gdk_paintable_snapshot (paintable, snapshot, 100, 100);
node = gtk_snapshot_free_to_node (snapshot);
surface = cairo_pdf_surface_create_for_stream (write_cairo, stream, 100, 100);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
gsk_render_node_unref (node);
if (!g_output_stream_close (stream, NULL, &error))
{
g_print ("Error from close: %s\n", error->message);
g_error_free (error);
}
g_object_unref (stream);
}
static void
print (GtkButton *button,
gpointer data)
{
GtkWidget *picture = data;
GtkPrintDialog *dialog;
dialog = gtk_print_dialog_new ();
gtk_print_dialog_print (dialog,
GTK_WINDOW (gtk_widget_get_root (picture)),
NULL,
NULL,
print_ready,
picture);
g_object_unref (dialog);
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
@@ -258,21 +172,12 @@ do_path_fill (GtkWidget *do_widget)
if (!window)
{
GtkWidget *header, *button, *label;
GtkWidget *picture;
GdkPaintable *paintable;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Fill and Stroke");
header = gtk_header_bar_new ();
button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
label = gtk_label_new ("Fill and Stroke");
gtk_widget_add_css_class (label, "title");
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header), label);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paintable = gtk_logo_paintable_new ();
@@ -281,8 +186,6 @@ do_path_fill (GtkWidget *do_widget)
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
g_signal_connect (button, "clicked", G_CALLBACK (print), picture);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
+3 -70
View File
@@ -1,9 +1,8 @@
/* Pickers and Launchers
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkPrintDialog, GtkFileLauncher, GtkUriLauncher
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
*
* The dialogs are mainly intended for use in preference dialogs.
* They allow to select colors, fonts and files. There is also a
* print dialog.
* They allow to select colors, fonts and applications.
*
* The launchers let you open files or URIs in applications that
* can handle them.
@@ -12,13 +11,11 @@
#include <gtk/gtk.h>
static GtkWidget *app_picker;
static GtkWidget *print_button;
static void
set_file (GFile *file,
gpointer data)
{
GFileInfo *info;
char *name;
if (!file)
@@ -34,13 +31,6 @@ set_file (GFile *file,
gtk_widget_set_sensitive (app_picker, TRUE);
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
info = g_file_query_info (file, "standard::content-type", 0, NULL, NULL);
if (strcmp (g_file_info_get_content_type (info), "application/pdf") == 0)
{
gtk_widget_set_sensitive (print_button, TRUE);
g_object_set_data_full (G_OBJECT (print_button), "file", g_object_ref (file), g_object_unref);
}
}
static void
@@ -57,10 +47,6 @@ file_opened (GObject *source,
{
g_print ("%s\n", error->message);
g_error_free (error);
gtk_widget_set_sensitive (app_picker, FALSE);
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
gtk_widget_set_sensitive (print_button, FALSE);
g_object_set_data (G_OBJECT (print_button), "file", NULL);
}
set_file (file, data);
@@ -128,53 +114,6 @@ open_app (GtkButton *picker)
g_object_unref (launcher);
}
static void
print_file_done (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GCancellable *cancellable;
unsigned int id;
cancellable = g_task_get_cancellable (G_TASK (result));
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cancellable), "timeout"));
if (id)
g_source_remove (id);
if (!gtk_print_dialog_print_file_finish (dialog, result, &error))
{
g_print ("%s\n", error->message);
g_error_free (error);
}
}
static void
print_file (GtkButton *picker)
{
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
GtkPrintDialog *dialog;
GCancellable *cancellable;
GFile *file;
unsigned int id;
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
dialog = gtk_print_dialog_new ();
cancellable = g_cancellable_new ();
id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
20,
abort_mission, g_object_ref (cancellable), g_object_unref);
g_object_set_data (G_OBJECT (cancellable), "timeout", GUINT_TO_POINTER (id));
gtk_print_dialog_print_file (dialog, parent, NULL, file, cancellable, print_file_done, NULL);
g_object_unref (cancellable);
g_object_unref (dialog);
}
static void
open_uri_done (GObject *source,
GAsyncResult *result,
@@ -295,15 +234,9 @@ do_pickers (GtkWidget *do_widget)
gtk_widget_set_sensitive (app_picker, FALSE);
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
gtk_box_append (GTK_BOX (picker), app_picker);
print_button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_widget_set_tooltip_text (print_button, "Print file");
gtk_widget_set_sensitive (print_button, FALSE);
g_signal_connect (print_button, "clicked", G_CALLBACK (print_file), NULL);
gtk_box_append (GTK_BOX (picker), print_button);
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
label = gtk_label_new ("URI:");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+13 -28
View File
@@ -170,41 +170,35 @@ This variable can be set to a list of debug options, which cause GDK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
`misc`
: Miscellaneous information
`events`
: Information about events
`dnd`
: Information about drag-and-drop
`input`
: Information about input (mostly Windows)
`cursor`
: Information about cursor objects (only win32)
`eventloop`
: Information about event loop operation (mostly macOS)
`misc`
: Miscellaneous information
`frames`
: Information about the frame clock
`settings`
: Information about xsettings
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
`selection`
: Information about selections
`clipboard`
: Information about clipboards
`dmabuf`
: Information about dmabuf handling (Linux-only)
`dnd`
: Information about drag-and-drop
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
A number of options affect behavior instead of logging:
@@ -223,9 +217,6 @@ A number of options affect behavior instead of logging:
`gl-fractional`
: Enable fractional scaling for OpenGL. This is experimental
`gl-debug`
: Insert debugging information in OpenGL
`gl-legacy`
: Use a legacy OpenGL context
@@ -253,12 +244,6 @@ A number of options affect behavior instead of logging:
`high-depth`
: Use high bit depth rendering if possible
`no-vsync`
: Repaint instantly (uses 100% CPU with animations)
`dmabuf-disable`
: Disable dmabuf support
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to obtain a list of all supported debug options.
-3
View File
@@ -117,8 +117,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "vulkan", GDK_DEBUG_VULKAN, "Information about Vulkan" },
{ "selection", GDK_DEBUG_SELECTION, "Information about selections" },
{ "clipboard", GDK_DEBUG_CLIPBOARD, "Information about clipboards" },
{ "dmabuf", GDK_DEBUG_DMABUF, "Information about dmabuf buffers" },
{ "nograbs", GDK_DEBUG_NOGRABS, "Disable pointer and keyboard grabs (X11)", TRUE },
{ "portals", GDK_DEBUG_PORTALS, "Force use of portals", TRUE },
{ "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals", TRUE },
@@ -135,7 +133,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible", TRUE },
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)", TRUE },
{ "dmabuf-disable", GDK_DEBUG_DMABUF_DISABLE, "Disable dmabuf support", TRUE },
};
-3
View File
@@ -42,9 +42,6 @@
#include <gdk/gdkdevicetool.h>
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdmabufformats.h>
#include <gdk/gdkdmabuftexture.h>
#include <gdk/gdkdmabuftexturebuilder.h>
#include <gdk/gdkdrag.h>
#include <gdk/gdkdragsurface.h>
#include <gdk/gdkdragsurfacesize.h>
+1 -7
View File
@@ -183,7 +183,7 @@ gdk_array(reserve) (GdkArray *self,
return;
size = gdk_array(get_size) (self);
new_size = ((gsize) 1) << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
#ifdef GDK_ARRAY_PREALLOC
if (self->start == self->preallocated)
@@ -215,11 +215,7 @@ gdk_array(splice) (GdkArray *self,
gsize pos,
gsize removed,
gboolean stolen,
#ifdef GDK_ARRAY_BY_VALUE
const _T_ *additions,
#else
_T_ *additions,
#endif
gsize added)
{
gsize size;
@@ -322,5 +318,3 @@ gdk_array(get) (const GdkArray *self,
#undef GDK_ARRAY_TYPE_NAME
#undef GDK_ARRAY_NO_MEMSET
#endif
G_END_DECLS
+16 -19
View File
@@ -36,26 +36,23 @@ typedef enum {
GDK_DEBUG_VULKAN = 1 << 8,
GDK_DEBUG_SELECTION = 1 << 9,
GDK_DEBUG_CLIPBOARD = 1 << 10,
GDK_DEBUG_DMABUF = 1 << 11,
/* flags below are influencing behavior */
GDK_DEBUG_NOGRABS = 1 << 12,
GDK_DEBUG_PORTALS = 1 << 13,
GDK_DEBUG_NO_PORTALS = 1 << 14,
GDK_DEBUG_GL_DISABLE = 1 << 15,
GDK_DEBUG_GL_FRACTIONAL = 1 << 16,
GDK_DEBUG_GL_LEGACY = 1 << 17,
GDK_DEBUG_GL_GLES = 1 << 18,
GDK_DEBUG_GL_DEBUG = 1 << 19,
GDK_DEBUG_GL_EGL = 1 << 20,
GDK_DEBUG_GL_GLX = 1 << 21,
GDK_DEBUG_GL_WGL = 1 << 22,
GDK_DEBUG_VULKAN_DISABLE = 1 << 23,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 24,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 25,
GDK_DEBUG_HIGH_DEPTH = 1 << 26,
GDK_DEBUG_NO_VSYNC = 1 << 27,
GDK_DEBUG_DMABUF_DISABLE = 1 << 28,
GDK_DEBUG_NOGRABS = 1 << 11,
GDK_DEBUG_PORTALS = 1 << 12,
GDK_DEBUG_NO_PORTALS = 1 << 13,
GDK_DEBUG_GL_DISABLE = 1 << 14,
GDK_DEBUG_GL_FRACTIONAL = 1 << 15,
GDK_DEBUG_GL_LEGACY = 1 << 16,
GDK_DEBUG_GL_GLES = 1 << 17,
GDK_DEBUG_GL_DEBUG = 1 << 18,
GDK_DEBUG_GL_EGL = 1 << 19,
GDK_DEBUG_GL_GLX = 1 << 20,
GDK_DEBUG_GL_WGL = 1 << 21,
GDK_DEBUG_VULKAN_DISABLE = 1 << 22,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 23,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 24,
GDK_DEBUG_HIGH_DEPTH = 1 << 25,
GDK_DEBUG_NO_VSYNC = 1 << 26,
} GdkDebugFlags;
extern guint _gdk_debug_flags;
-85
View File
@@ -31,9 +31,6 @@
#include "gdkclipboardprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdisplaymanagerprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkeventsprivate.h"
#include "gdkframeclockidleprivate.h"
#include "gdkglcontextprivate.h"
@@ -72,7 +69,6 @@ enum
PROP_COMPOSITED,
PROP_RGBA,
PROP_INPUT_SHAPES,
PROP_DMABUF_FORMATS,
LAST_PROP
};
@@ -142,10 +138,6 @@ gdk_display_get_property (GObject *object,
g_value_set_boolean (value, gdk_display_supports_input_shapes (display));
break;
case PROP_DMABUF_FORMATS:
g_value_set_boxed (value, gdk_display_get_dmabuf_formats (display));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -247,11 +239,6 @@ gdk_display_class_init (GdkDisplayClass *class)
TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
props[PROP_DMABUF_FORMATS] =
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
GDK_TYPE_DMABUF_FORMATS,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, props);
/**
@@ -417,8 +404,6 @@ gdk_display_finalize (GObject *object)
g_list_free_full (display->seats, g_object_unref);
g_clear_pointer (&display->dmabuf_formats, gdk_dmabuf_formats_unref);
G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
}
@@ -1839,76 +1824,6 @@ 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)
{
-4
View File
@@ -134,10 +134,6 @@ gboolean gdk_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value);
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats *
gdk_display_get_dmabuf_formats (GdkDisplay *display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
G_END_DECLS
-6
View File
@@ -25,7 +25,6 @@
#include "gdksurfaceprivate.h"
#include "gdkkeysprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdmabufprivate.h"
#ifdef GDK_RENDERING_VULKAN
#include <vulkan/vulkan.h>
@@ -114,9 +113,6 @@ 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
@@ -211,8 +207,6 @@ gulong _gdk_display_get_next_serial (GdkDisplay *display
void _gdk_display_pause_events (GdkDisplay *display);
void _gdk_display_unpause_events (GdkDisplay *display);
void gdk_display_init_dmabuf (GdkDisplay *self);
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
GError **error);
-602
View File
@@ -1,602 +0,0 @@
/* gdkdmabuf.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdmabufprivate.h"
#include "gdkdebugprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#ifdef HAVE_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 */
-215
View File
@@ -1,215 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <glib-object.h>
#include "gdkdmabufformatsprivate.h"
/**
* GdkDmabufFormats:
*
* The `GdkDmabufFormats struct provides information about
* supported DMA buffer formats.
*
* You can query whether a given format is supported with
* [method@Gdk.DmabufFormats.contains] and you can iterate
* over the list of all supported formats with
* [method@Gdk.DmabufFormats.get_n_formats] and
* [method@Gdk.DmabufFormats.get_format].
*
* The list of supported formats is sorted by preference,
* with the best formats coming first.
*
* See [class@Gdk.DmabufTextureBuilder] for more information
* about DMA buffers.
*
* Note that DMA buffers only exist on Linux.
*
* Since: 4.14
*/
struct _GdkDmabufFormats
{
int ref_count;
gsize n_formats;
GdkDmabufFormat *formats;
};
G_DEFINE_BOXED_TYPE (GdkDmabufFormats, gdk_dmabuf_formats, gdk_dmabuf_formats_ref, gdk_dmabuf_formats_unref)
/**
* gdk_dmabuf_formats_ref:
* @formats: a `GdkDmabufFormats`
*
* Increases the reference count of @formats.
*
* Returns: the passed-in object
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_ref (GdkDmabufFormats *formats)
{
formats->ref_count++;
return formats;
}
/**
* gdk_dmabuf_formats_unref:
* @formats: a `GdkDmabufFormats`
*
* Decreases the reference count of @formats.
*
* When the reference count reaches zero,
* the object is freed.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_unref (GdkDmabufFormats *formats)
{
formats->ref_count--;
if (formats->ref_count > 0)
return;
g_free (formats->formats);
g_free (formats);
}
/**
* gdk_dmabuf_formats_get_n_formats:
* @formats: a `GdkDmabufFormats`
*
* Returns the number of formats that the @formats object
* contains.
*
* Note that DMA buffers are a Linux concept, so on other
* platforms, [method@Gdk.DmabufFormats.get_n_formats] will
* always return zero.
*
* Returns: the number of formats
*
* Since: 4.14
*/
gsize
gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats)
{
return formats->n_formats;
}
/**
* gdk_dmabuf_formats_get_format:
* @formats: a `GdkDmabufFormats`
* @idx: the index of the format to return
* @fourcc: (out): return location for the format code
* @modifier: (out): return location for the format modifier
*
* Gets the fourcc code and modifier for a format
* that is contained in @formats.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier)
{
GdkDmabufFormat *format;
g_return_if_fail (idx < formats->n_formats);
g_return_if_fail (fourcc != NULL);
g_return_if_fail (modifier != NULL);
format = &formats->formats[idx];
*fourcc = format->fourcc;
*modifier = format->modifier;
}
/**
* gdk_dmabuf_format_contains:
* @formats: a `GdkDmabufFormats`
* @fourcc: a format code
* @modfier: a format modifier
*
* Returns whether a given format is contained in @formats.
*
* Returns: `TRUE` if the format specified by the arguments
* is part of @formats
*
* Since: 4.14
*/
gboolean
gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier)
{
for (gsize i = 0; i < formats->n_formats; i++)
{
GdkDmabufFormat *format = &formats->formats[i];
if (format->fourcc == fourcc && format->modifier == modifier)
return TRUE;
}
return FALSE;
}
/*< private >
* gdk_dmabuf_formats_new:
* @formats: the formats
* @n_formats: the length of @formats
*
* Creates a new `GdkDmabufFormats struct for
* the given formats.
*
* The @formats array is expected to be sorted
* by preference.
*
* Returns: (transfer full): the new `GdkDmabufFormats`
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats)
{
GdkDmabufFormats *self;
self = g_new0 (GdkDmabufFormats, 1);
self->ref_count = 1;
self->n_formats = n_formats;
self->formats = g_new (GdkDmabufFormat, n_formats);
memcpy (self->formats, formats, n_formats * sizeof (GdkDmabufFormat));
return self;
}
const GdkDmabufFormat *
gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self)
{
return self->formats;
}
-54
View File
@@ -1,54 +0,0 @@
/* gdkdmabufformats.h
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_FORMATS (gdk_dmabuf_formats_get_type ())
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_formats_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats * gdk_dmabuf_formats_ref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_unref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
gsize gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier) G_GNUC_PURE;
G_END_DECLS
-133
View File
@@ -1,133 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#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));
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct GdkDmabufFormatsBuilder GdkDmabufFormatsBuilder;
GdkDmabufFormatsBuilder * gdk_dmabuf_formats_builder_new (void);
GdkDmabufFormats * gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self);
void gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier);
void gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats);
-15
View File
@@ -1,15 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct _GdkDmabufFormat GdkDmabufFormat;
struct _GdkDmabufFormat
{
guint32 fourcc;
guint64 modifier;
};
GdkDmabufFormats * gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats);
const GdkDmabufFormat * gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self);
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#include "gdkdmabufformatsbuilderprivate.h"
#define GDK_DMABUF_MAX_PLANES 4
typedef struct _GdkDmabuf GdkDmabuf;
typedef struct _GdkDmabufDownloader GdkDmabufDownloader;
struct _GdkDmabuf
{
guint32 fourcc;
guint64 modifier;
unsigned int n_planes;
struct {
int fd;
unsigned int stride;
unsigned int offset;
} planes[GDK_DMABUF_MAX_PLANES];
};
struct _GdkDmabufDownloader
{
const char *name;
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
-219
View File
@@ -1,219 +0,0 @@
/* gdkdmabuftexture.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufprivate.h"
#include "gdktextureprivate.h"
#include <gdk/gdkglcontext.h>
#include <gdk/gdkgltexturebuilder.h>
#include <gdk/gdktexturedownloader.h>
#ifdef HAVE_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
}
-48
View File
@@ -1,48 +0,0 @@
/* gdkdmabuftexture.h
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
#include <gdk/gdktexture.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE (gdk_dmabuf_texture_get_type ())
#define GDK_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DMABUF_TEXTURE, GdkDmabufTexture))
#define GDK_IS_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DMABUF_TEXTURE))
#define GDK_DMABUF_ERROR (gdk_dmabuf_error_quark ())
typedef struct _GdkDmabufTexture GdkDmabufTexture;
typedef struct _GdkDmabufTextureClass GdkDmabufTextureClass;
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_texture_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GQuark gdk_dmabuf_error_quark (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDmabufTexture, g_object_unref)
G_END_DECLS
-993
View File
@@ -1,993 +0,0 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#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;
}
-122
View File
@@ -1,122 +0,0 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE_BUILDER (gdk_dmabuf_texture_builder_get_type ())
GDK_AVAILABLE_IN_4_14
GDK_DECLARE_INTERNAL_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, GDK, DMABUF_TEXTURE_BUILDER, GObject)
GDK_AVAILABLE_IN_4_14
GdkDmabufTextureBuilder *gdk_dmabuf_texture_builder_new (void);
GDK_AVAILABLE_IN_4_14
GdkDisplay * gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
GdkDisplay *display);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
unsigned int width);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
unsigned int height);
GDK_AVAILABLE_IN_4_14
guint32 gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
guint32 fourcc);
GDK_AVAILABLE_IN_4_14
guint64 gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_texture_builder_get_premultiplied (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_premultiplied (GdkDmabufTextureBuilder *self,
gboolean premultiplied);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
unsigned int n_planes);
GDK_AVAILABLE_IN_4_14
int gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
unsigned int plane,
int fd);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int stride);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int offset);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_14
cairo_region_t * gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
cairo_region_t *region);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
GDestroyNotify destroy,
gpointer data,
GError **error);
G_END_DECLS
-21
View File
@@ -1,21 +0,0 @@
#pragma once
#include "gdkdmabuftexture.h"
#include "gdkdmabuftexturebuilder.h"
#include "gdkdmabufprivate.h"
G_BEGIN_DECLS
const GdkDmabuf * gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *builder);
GdkTexture * gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data,
GError **error);
GdkDisplay * gdk_dmabuf_texture_get_display (GdkDmabufTexture *self);
const GdkDmabuf * gdk_dmabuf_texture_get_dmabuf (GdkDmabufTexture *self);
G_END_DECLS
+1 -1
View File
@@ -684,7 +684,7 @@ gdk_drop_read_async (GdkDrop *self,
* gdk_drop_read_finish:
* @self: a `GdkDrop`
* @result: a `GAsyncResult`
* @out_mime_type: (out) (type utf8) (transfer none): return location for the used mime type
* @out_mime_type: (out) (type utf8): return location for the used mime type
* @error: (nullable): location to store error information on failure
*
* Finishes an async drop read operation.
-27
View File
@@ -142,22 +142,6 @@ typedef enum
GDK_BUTTON4_MASK|GDK_BUTTON5_MASK)
/**
* GdkDmabufError:
* @GDK_DMABUF_ERROR_NOT_AVAILABLE: Dmabuf support is not available, because the OS
* is not Linux, or it was explicitly disabled at compile- or runtime
* @GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT: The requested format is not supported
* @GDK_DMABUF_ERROR_CREATION_FAILED: GTK failed to create the resource for other
* reasons
*
* Error enumeration for `GdkDmabufTexture`.
*/
typedef enum {
GDK_DMABUF_ERROR_NOT_AVAILABLE,
GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
GDK_DMABUF_ERROR_CREATION_FAILED,
} GdkDmabufError;
/**
* GdkGLError:
* @GDK_GL_ERROR_NOT_AVAILABLE: OpenGL support is not available
@@ -298,16 +282,10 @@ typedef enum
* The color values are premultiplied with the alpha value.
* @GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: 4 bytes; for red, green, blue, alpha
* The color values are premultiplied with the alpha value.
* @GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: 4 bytes; for alpha, blue, green, red,
* The color values are premultiplied with the alpha value. Since 4.14
* @GDK_MEMORY_B8G8R8A8: 4 bytes; for blue, green, red, alpha.
* @GDK_MEMORY_A8R8G8B8: 4 bytes; for alpha, red, green, blue.
* @GDK_MEMORY_R8G8B8A8: 4 bytes; for red, green, blue, alpha.
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
* @GDK_MEMORY_B8G8R8X8: 4 bytes; for blue, green, red, unused. Since 4.14
* @GDK_MEMORY_X8R8G8B8: 4 bytes; for unused, red, green, blue. Since 4.14
* @GDK_MEMORY_R8G8B8X8: 4 bytes; for red, green, blue, unused. Since 4.14
* @GDK_MEMORY_X8B8G8R8: 4 bytes; for unused, blue, green, red. Since 4.14
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since: 4.6
@@ -388,11 +366,6 @@ typedef enum {
GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A16_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A32_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GDK_MEMORY_A8B8G8R8_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_B8G8R8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_X8R8G8B8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_R8G8B8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_X8B8G8R8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
+2 -87
View File
@@ -109,7 +109,6 @@ 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;
@@ -1532,13 +1531,11 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
priv->has_unpack_subimage = gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888");
}
else
{
priv->has_unpack_subimage = TRUE;
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = TRUE;
/* We asked for a core profile, but we didn't get one, so we're in legacy mode */
if (!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
@@ -1570,8 +1567,7 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s\n"
" - half float: %s\n"
" - sync: %s\n"
" - bgra: %s",
" - sync: %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",
@@ -1580,8 +1576,7 @@ 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_bgra ? "yes" : "no");
priv->has_sync ? "yes" : "no");
}
#endif
@@ -1720,56 +1715,6 @@ gdk_gl_context_get_version (GdkGLContext *context,
*minor = gdk_gl_version_get_minor (&priv->gl_version);
}
const char *
gdk_gl_context_get_glsl_version_string (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
if (priv->api == GDK_GL_API_GL)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 6)))
return "#version 460";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 5)))
return "#version 450";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 4)))
return "#version 440";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 3)))
return "#version 430";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 2)))
return "#version 420";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 1)))
return "#version 410";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 0)))
return "#version 400";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 3)))
return "#version 330";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 150";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 140";
else
return "#version 130";
}
else if (priv->api == GDK_GL_API_GLES)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 320 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 310 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else
return "#version 100";
}
else
{
/* must be realized to be called */
g_assert_not_reached ();
}
}
/**
* gdk_gl_context_clear_current:
*
@@ -1867,36 +1812,6 @@ gdk_gl_context_has_sync (GdkGLContext *self)
return priv->has_sync;
}
/* Return if GL_BGRA works with glTexImage2D */
gboolean
gdk_gl_context_has_bgra (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_bgra;
}
/* Return if glGenVertexArrays, glBindVertexArray and glDeleteVertexArrays
* can be used
*/
gboolean
gdk_gl_context_has_vertex_arrays (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
switch (priv->api)
{
case GDK_GL_API_GL:
return TRUE;
case GDK_GL_API_GLES:
return gdk_gl_version_get_major (&priv->gl_version) >= 3;
default:
g_return_val_if_reached (FALSE);
}
}
/* This is currently private! */
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
gboolean
-6
View File
@@ -147,8 +147,6 @@ void gdk_gl_context_label_object_printf (GdkGLContext
const char *format,
...) G_GNUC_PRINTF (4, 5);
const char * gdk_gl_context_get_glsl_version_string (GdkGLContext *self);
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
@@ -157,10 +155,6 @@ 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
+9 -4
View File
@@ -141,7 +141,9 @@ struct _Download
};
static gboolean
gdk_gl_texture_find_format (GdkGLContext *context,
gdk_gl_texture_find_format (gboolean use_es,
guint gl_major,
guint gl_minor,
GdkMemoryAlpha alpha,
GLint gl_format,
GLint gl_type,
@@ -157,7 +159,7 @@ gdk_gl_texture_find_format (GdkGLContext *context,
if (gdk_memory_format_alpha (format) != alpha)
continue;
if (!gdk_memory_format_gl_format (format, context, &q_internal_format, &q_format, &q_type, q_swizzle))
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, q_swizzle))
continue;
if (q_format != gl_format || q_type != gl_type)
@@ -181,13 +183,16 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
Download *download = download_;
GLenum gl_internal_format, gl_format, gl_type;
GLint gl_swizzle[4];
int major, minor;
format = gdk_texture_get_format (texture),
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
gdk_gl_context_get_version (context, &major, &minor);
if (!gdk_gl_context_get_use_es (context) &&
gdk_memory_format_gl_format (format,
context,
FALSE,
major, minor,
&gl_internal_format,
&gl_format, &gl_type, gl_swizzle))
{
@@ -238,7 +243,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
{
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
if (!gdk_gl_texture_find_format (context, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
if (!gdk_gl_texture_find_format (TRUE, major, minor, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
{
gl_read_format = GL_RGBA;
gl_read_type = GL_UNSIGNED_BYTE;
+5 -71
View File
@@ -20,7 +20,6 @@
#include "config.h"
#include "gdkmemoryformatprivate.h"
#include "gdkglcontextprivate.h"
#include "gsk/gl/fp16private.h"
@@ -94,17 +93,10 @@ name ## _from_float (guchar *dest_data, \
TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
TYPED_FUNCS (a8b8g8r8_premultiplied, guchar, 3, 2, 1, 0, 4, 255)
TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
TYPED_FUNCS (r8g8b8x8, guchar, 0, 1, 2, -1, 4, 255)
TYPED_FUNCS (x8r8g8b8, guchar, 1, 2, 3, -1, 4, 255)
TYPED_FUNCS (b8g8r8x8, guchar, 2, 1, 0, -1, 4, 255)
TYPED_FUNCS (x8b8g8r8, guchar, 3, 2, 1, -1, 4, 255)
TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
@@ -360,7 +352,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, 0, 0 },
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_premultiplied_to_float,
b8g8r8a8_premultiplied_from_float,
@@ -385,22 +377,12 @@ static const GdkMemoryFormatDescription memory_formats[] = {
r8g8b8a8_premultiplied_to_float,
r8g8b8a8_premultiplied_from_float,
},
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
a8b8g8r8_premultiplied_to_float,
a8b8g8r8_premultiplied_from_float,
},
[GDK_MEMORY_B8G8R8A8] = {
GDK_MEMORY_ALPHA_STRAIGHT,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, 0, 0 },
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
b8g8r8a8_to_float,
b8g8r8a8_from_float,
@@ -435,46 +417,6 @@ static const GdkMemoryFormatDescription memory_formats[] = {
a8b8g8r8_to_float,
a8b8g8r8_from_float,
},
[GDK_MEMORY_B8G8R8X8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
b8g8r8x8_to_float,
b8g8r8x8_from_float,
},
[GDK_MEMORY_X8R8G8B8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
x8r8g8b8_to_float,
x8r8g8b8_from_float,
},
[GDK_MEMORY_R8G8B8X8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ 0, 0, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
r8g8b8x8_to_float,
r8g8b8x8_from_float,
},
[GDK_MEMORY_X8B8G8R8] = {
GDK_MEMORY_ALPHA_OPAQUE,
4,
G_ALIGNOF (guchar),
GDK_MEMORY_U8,
{ G_MAXUINT, G_MAXUINT, G_MAXUINT, G_MAXUINT },
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
x8b8g8r8_to_float,
x8b8g8r8_from_float,
},
[GDK_MEMORY_R8G8B8] = {
GDK_MEMORY_ALPHA_OPAQUE,
3,
@@ -791,19 +733,14 @@ gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth)
gboolean
gdk_memory_format_gl_format (GdkMemoryFormat format,
GdkGLContext *context,
gboolean gles,
guint gl_major,
guint gl_minor,
guint *out_internal_format,
guint *out_format,
guint *out_type,
GLint out_swizzle[4])
{
int gl_major;
int gl_minor;
gboolean gles;
gdk_gl_context_get_version (context, &gl_major, &gl_minor);
gles = gdk_gl_context_get_use_es (context);
*out_internal_format = memory_formats[format].gl.internal_format;
*out_format = memory_formats[format].gl.format;
*out_type = memory_formats[format].gl.type;
@@ -815,9 +752,6 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
(memory_formats[format].min_gl_version.gles_major == gl_major &&
memory_formats[format].min_gl_version.gles_minor > gl_minor))
return FALSE;
if (*out_format == GL_BGRA && !gdk_gl_context_has_bgra (context))
return FALSE;
}
else
{
+3 -2
View File
@@ -20,7 +20,6 @@
#pragma once
#include "gdkenums.h"
#include "gdktypes.h"
#include <epoxy/gl.h>
@@ -47,7 +46,9 @@ GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth
GdkMemoryDepth depth2) G_GNUC_CONST;
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
GdkGLContext *context,
gboolean gles,
guint gl_major,
guint gl_minor,
guint *out_internal_format,
guint *out_format,
guint *out_type,
+2 -5
View File
@@ -24,16 +24,13 @@
#include "gdksnapshotprivate.h"
#include "gdkprivate.h"
#include <graphene.h>
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
GdkSnapshot * gtk_snapshot_new (void);
void gtk_snapshot_push_debug (GdkSnapshot *snapshot,
const char *message,
...) G_GNUC_PRINTF (2, 3);
void gtk_snapshot_pop (GdkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot,
const graphene_size_t *size);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot);
/**
* GdkPaintable:
@@ -121,7 +118,7 @@ gdk_paintable_default_get_current_image (GdkPaintable *paintable)
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
return gtk_snapshot_free_to_paintable (snapshot, NULL);
return gtk_snapshot_free_to_paintable (snapshot);
}
static GdkPaintableFlags
+1 -1
View File
@@ -40,7 +40,7 @@ struct _GdkIOPipe
GCond cond;
guchar *buffer;
gsize size;
guint state : 2; /* GdkIOPipeState */
GdkIOPipeState state : 2;
guint input_closed : 1;
guint output_closed : 1;
};
+1 -1
View File
@@ -254,7 +254,7 @@ maybe_flip_position (int bounds_pos,
*flipped = TRUE;
secondary = rect_pos + (1 - rect_sign) * rect_size / 2 - offset - (1 - surface_sign) * surface_size / 2;
if ((secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size) || primary > bounds_pos + bounds_size)
if (secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size)
return secondary;
*flipped = FALSE;
+3 -5
View File
@@ -345,9 +345,7 @@ gdk_texture_init (GdkTexture *self)
*
* Creates a new texture object representing the surface.
*
* The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* The newly created texture will acquire a reference on the @surface.
* @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* Returns: a new `GdkTexture`
*/
@@ -366,7 +364,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
@@ -821,7 +819,7 @@ gdk_texture_set_render_data (GdkTexture *self,
GDestroyNotify notify)
{
g_return_val_if_fail (data != NULL, FALSE);
if (self->render_key != NULL)
return FALSE;
-2
View File
@@ -96,8 +96,6 @@ typedef struct _GdkCairoContext GdkCairoContext;
typedef struct _GdkGLContext GdkGLContext;
typedef struct _GdkVulkanContext GdkVulkanContext;
typedef struct _GdkDmabufFormats GdkDmabufFormats;
/*
* GDK_DECLARE_INTERNAL_TYPE:
* @ModuleObjName: The name of the new type, in camel case (like GtkWidget)
-7
View File
@@ -1475,13 +1475,6 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
gboolean validate = FALSE, have_debug_report = FALSE;
VkResult res;
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_DISABLE)
{
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
_("Vulkan support disabled via GDK_DEBUG"));
return FALSE;
}
if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
{
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
-5
View File
@@ -329,7 +329,6 @@ gdk_save_png (GdkTexture *texture)
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
@@ -341,10 +340,6 @@ gdk_save_png (GdkTexture *texture)
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8B8G8R8:
format = GDK_MEMORY_R8G8B8;
png_format = PNG_COLOR_TYPE_RGB;
depth = 8;
-5
View File
@@ -236,17 +236,12 @@ static const FormatData format_data[] = {
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8R8G8B8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_A8B8G8R8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R8G8B8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_X8R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_B8G8R8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_X8B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16] = { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
[GDK_MEMORY_R16G16B16A16] = { GDK_MEMORY_R16G16B16A16, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
-8
View File
@@ -17,11 +17,6 @@ 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',
@@ -84,9 +79,6 @@ gdk_public_headers = files([
'gdkdisplay.h',
'gdkdisplaymanager.h',
'gdkdrag.h',
'gdkdmabufformats.h',
'gdkdmabuftexture.h',
'gdkdmabuftexturebuilder.h',
'gdkdragsurfacesize.h',
'gdkdrawcontext.h',
'gdkdrop.h',
-4
View File
@@ -4442,10 +4442,6 @@ _gdk_win32_surface_request_layout (GdkSurface *surface)
{
_gdk_win32_get_window_rect (surface, &rect);
/* Keep current position if rect is invalid (i.e. queried in bad context) */
if (rect.right == rect.left || rect.bottom == rect.top)
return;
impl->next_layout.configured_width = (rect.right - rect.left + scale - 1) / scale;
impl->next_layout.configured_height = (rect.bottom - rect.top + scale - 1) / scale;
+2 -7
View File
@@ -453,7 +453,7 @@ get_colorized_texture (GdkTexture *texture,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset)
{
cairo_surface_t *surface;
cairo_surface_t *surface = gdk_texture_download_surface (texture);
cairo_surface_t *image_surface;
graphene_vec4_t pixel;
guint32* pixel_data;
@@ -475,7 +475,6 @@ get_colorized_texture (GdkTexture *texture,
return g_object_ref (colorized->texture);
}
surface = gdk_texture_download_surface (texture);
image_surface = cairo_surface_map_to_image (surface, NULL);
data = cairo_image_surface_get_data (image_surface);
width = cairo_image_surface_get_width (image_surface);
@@ -537,8 +536,6 @@ get_colorized_texture (GdkTexture *texture,
colorized_list, (GDestroyNotify)colorized_texture_free_list);
}
cairo_surface_destroy (surface);
return colorized_texture;
}
@@ -614,7 +611,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
}
texture = gdk_texture_new_for_surface (image_surface);
g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */
g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
texture_id = gdk_broadway_display_ensure_texture (display, texture);
add_rect (nodes, &node->bounds, offset_x, offset_y);
@@ -905,8 +902,6 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
add_float (nodes, width);
add_float (nodes, height);
add_uint32 (nodes, texture_id);
cairo_surface_destroy (surface);
}
}
+34 -10
View File
@@ -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_has_vertex_arrays (self->context))
if (!gdk_gl_context_get_use_es (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_has_vertex_arrays (self->context))
if (!gdk_gl_context_get_use_es (self->context))
glDeleteVertexArrays (1, &vao_id);
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
@@ -1450,7 +1450,9 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
static GdkMemoryFormat
memory_format_gl_format (GdkMemoryFormat data_format,
GdkGLContext *context,
gboolean use_es,
guint major,
guint minor,
guint *gl_internalformat,
guint *gl_format,
guint *gl_type,
@@ -1460,7 +1462,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
/* First, try the format itself */
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1476,7 +1480,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
case GDK_MEMORY_FLOAT16:
data_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1487,7 +1493,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
case GDK_MEMORY_U16:
data_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1509,7 +1517,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
{
data_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
if (gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1520,7 +1530,9 @@ memory_format_gl_format (GdkMemoryFormat data_format,
/* If all else fails, pick the one format that's always supported */
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
if (!gdk_memory_format_gl_format (data_format,
context,
use_es,
major,
minor,
gl_internalformat,
gl_format,
gl_type,
@@ -1549,13 +1561,19 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
GLenum gl_type;
GLint gl_swizzle[4];
gsize bpp;
gboolean use_es;
int major, minor;
use_es = gdk_gl_context_get_use_es (self->context);
gdk_gl_context_get_version (self->context, &major, &minor);
data_format = gdk_texture_get_format (texture);
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
data_format = memory_format_gl_format (data_format,
self->context,
use_es,
major,
minor,
&gl_internalformat,
&gl_format,
&gl_type,
@@ -1620,7 +1638,9 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
GLenum gl_format;
GLenum gl_type;
GLint gl_swizzle[4];
gboolean use_es;
int texture_id;
int major, minor;
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
@@ -1653,9 +1673,13 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
glBindTexture (GL_TEXTURE_2D, texture_id);
/* Initialize the texture */
use_es = gdk_gl_context_get_use_es (self->context);
gdk_gl_context_get_version (self->context, &major, &minor);
data_format = gdk_texture_get_format (chunks[0].texture);
data_format = memory_format_gl_format (data_format,
self->context,
use_es,
major,
minor,
&gl_internalformat,
&gl_format,
&gl_type,
+9 -3
View File
@@ -32,6 +32,7 @@
#include "gskglcommandqueueprivate.h"
#include "gskglcompilerprivate.h"
#include "gskglglyphlibraryprivate.h"
#include "gskglglyphylibraryprivate.h"
#include "gskgliconlibraryprivate.h"
#include "gskglprogramprivate.h"
#include "gskglshadowlibraryprivate.h"
@@ -273,6 +274,7 @@ 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);
@@ -399,6 +401,7 @@ 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
@@ -462,6 +465,7 @@ 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);
@@ -572,6 +576,8 @@ 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);
@@ -1003,9 +1009,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));
+1
View File
@@ -97,6 +97,7 @@ struct _GskGLDriver
GskGLCommandQueue *command_queue;
GskGLGlyphLibrary *glyphs_library;
GskGLGlyphyLibrary *glyphy_library;
GskGLIconLibrary *icons_library;
GskGLShadowLibrary *shadows_library;
+5 -4
View File
@@ -119,7 +119,7 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
memset (pixel_data, 255, sizeof pixel_data);
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ()))
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
@@ -127,8 +127,9 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
else
{
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
glTexSubImage2D (GL_TEXTURE_2D, 0,
@@ -276,7 +277,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
g_assert (texture_id > 0);
if (G_UNLIKELY (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())))
if G_UNLIKELY (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
@@ -293,7 +294,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
{
pixel_data = cairo_image_surface_get_data (surface);
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / 4);
+544
View File
@@ -0,0 +1,544 @@
/* 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;
}
+142
View File
@@ -0,0 +1,142 @@
/* 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__ */
+2 -2
View File
@@ -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_has_bgra (gdk_gl_context_get_current ()))
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
@@ -125,7 +125,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
{
pixel_data = surface_data;
gl_format = GL_BGRA;
gl_type = GL_UNSIGNED_BYTE;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
+18
View File
@@ -87,3 +87,21 @@ 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))
+12
View File
@@ -150,6 +150,13 @@ 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:
@@ -307,10 +314,15 @@ 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);
+306 -138
View File
@@ -39,6 +39,7 @@
#include "gskglcommandqueueprivate.h"
#include "gskgldriverprivate.h"
#include "gskglglyphlibraryprivate.h"
#include "gskglglyphylibraryprivate.h"
#include "gskgliconlibraryprivate.h"
#include "gskglprogramprivate.h"
#include "gskglrenderjobprivate.h"
@@ -65,14 +66,6 @@ typedef struct _GskGLRenderClip
guint is_fully_contained : 1;
} GskGLRenderClip;
#define GDK_ARRAY_NAME clips
#define GDK_ARRAY_TYPE_NAME Clips
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderClip
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
typedef struct _GskGLRenderModelview
{
GskTransform *transform;
@@ -85,14 +78,6 @@ typedef struct _GskGLRenderModelview
graphene_matrix_t matrix;
} GskGLRenderModelview;
#define GDK_ARRAY_NAME modelviews
#define GDK_ARRAY_TYPE_NAME Modelviews
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderModelview
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
struct _GskGLRenderJob
{
/* The context containing the framebuffer we are drawing to. Generally this
@@ -133,12 +118,12 @@ struct _GskGLRenderJob
/* An array of GskGLRenderModelview updated as nodes are processed. The
* current modelview is the last element.
*/
Modelviews modelview;
GArray *modelview;
/* An array of GskGLRenderClip updated as nodes are processed. The
* current clip is the last element.
*/
Clips clip;
GArray *clip;
/* Our current alpha state as we process nodes */
float alpha;
@@ -168,6 +153,9 @@ 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.
*/
@@ -208,26 +196,6 @@ static void gsk_gl_render_job_visit_node (GskGLRenderJob
static gboolean gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
const GskRenderNode *node,
GskGLRenderOffscreen *offscreen);
static void gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen);
static inline GskGLRenderClip *
clips_grow_one (Clips *clips)
{
guint len = clips_get_size (clips);
clips_set_size (clips, len + 1);
return clips_get (clips, len);
}
static inline GskGLRenderModelview *
modelviews_grow_one (Modelviews *modelviews)
{
guint len = modelviews_get_size (modelviews);
modelviews_set_size (modelviews, len + 1);
return modelviews_get (modelviews, len);
}
static inline int
get_target_format (GskGLRenderJob *job,
@@ -274,7 +242,7 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
static inline gboolean G_GNUC_PURE
node_supports_2d_transform (const GskRenderNode *node)
{
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -336,7 +304,7 @@ node_supports_transform (const GskRenderNode *node)
* opacity or color matrix.
*/
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -502,10 +470,15 @@ gsk_gl_render_job_set_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
modelview->transform = transform;
@@ -530,17 +503,26 @@ gsk_gl_render_job_push_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
g_assert (transform != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
if G_LIKELY (modelviews_get_size (&job->modelview) > 1)
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
if G_LIKELY (job->modelview->len > 1)
{
GskGLRenderModelview *last = job->modelview.end - 2;
GskGLRenderModelview *last;
GskTransform *t = NULL;
last = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 2);
/* Multiply given matrix with our previous modelview */
t = gsk_transform_translate (gsk_transform_ref (last->transform),
&(graphene_point_t) {
@@ -574,7 +556,8 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
const GskGLRenderModelview *head;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview);
g_assert (job->modelview->len > 0);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
@@ -585,11 +568,11 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
gsk_transform_unref (head->transform);
job->modelview.end--;
job->modelview->len--;
if (modelviews_get_size (&job->modelview) >= 1)
if (job->modelview->len >= 1)
{
head = job->modelview.end - 1;
head = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len - 1);
job->scale_x = head->scale_x;
job->scale_y = head->scale_y;
@@ -609,12 +592,14 @@ gsk_gl_render_job_push_clip (GskGLRenderJob *job,
GskGLRenderClip *clip;
g_assert (job != NULL);
g_assert (job->clip != NULL);
g_assert (rect != NULL);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect, rect, sizeof *rect);
clip->is_rectilinear = gsk_rounded_rect_is_rectilinear (rect);
clip->is_fully_contained = FALSE;
@@ -629,13 +614,16 @@ gsk_gl_render_job_push_contained_clip (GskGLRenderJob *job)
GskGLRenderClip *old_clip;
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
old_clip = clips_get (&job->clip, clips_get_size (&job->clip) - 2);
old_clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect.bounds, &old_clip->rect.bounds, sizeof (graphene_rect_t));
memset (clip->rect.corner, 0, sizeof clip->rect.corner);
clip->is_rectilinear = TRUE;
@@ -648,11 +636,12 @@ static void
gsk_gl_render_job_pop_clip (GskGLRenderJob *job)
{
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
job->current_clip--;
job->clip.end--;
job->clip->len--;
}
static inline void
@@ -734,7 +723,7 @@ gsk_gl_render_job_transform_bounds (GskGLRenderJob *job,
GskTransformCategory category;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview->len > 0);
g_assert (rect != NULL);
g_assert (out_rect != NULL);
@@ -1229,12 +1218,12 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
cairo_move_to (cr, 0, 0);
cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 0.25);
else
cairo_set_source_rgba (cr, 1, 0, 0, 0.25);
cairo_fill_preserve (cr);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 1);
else
cairo_set_source_rgba (cr, 1, 0, 0, 1);
@@ -1527,7 +1516,7 @@ gsk_gl_render_job_visit_linear_gradient_node (GskGLRenderJob *job,
const graphene_point_t *start = gsk_linear_gradient_node_get_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_get_end (node);
int n_color_stops = gsk_linear_gradient_node_get_n_color_stops (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
float x1 = job->offset_x + start->x;
float x2 = job->offset_x + end->x;
float y1 = job->offset_y + start->y;
@@ -1600,7 +1589,7 @@ gsk_gl_render_job_visit_radial_gradient_node (GskGLRenderJob *job,
float end = gsk_radial_gradient_node_get_end (node);
float hradius = gsk_radial_gradient_node_get_hradius (node);
float vradius = gsk_radial_gradient_node_get_vradius (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
float scale = 1.0f / (end - start);
float bias = -start * scale;
@@ -1745,7 +1734,7 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
* which both have rounded corners.
*/
if (clips_get_size (&job->clip) <= 1)
if (job->clip->len <= 1)
need_offscreen = FALSE;
else if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
need_offscreen = FALSE;
@@ -2814,8 +2803,8 @@ static inline gboolean G_GNUC_PURE
equal_texture_nodes (const GskRenderNode *node1,
const GskRenderNode *node2)
{
if (GSK_RENDER_NODE_TYPE (node1) != GSK_TEXTURE_NODE ||
GSK_RENDER_NODE_TYPE (node2) != GSK_TEXTURE_NODE)
if (gsk_render_node_get_node_type (node1) != GSK_TEXTURE_NODE ||
gsk_render_node_get_node_type (node2) != GSK_TEXTURE_NODE)
return FALSE;
if (gsk_texture_node_get_texture (node1) !=
@@ -2968,10 +2957,10 @@ compute_phase_and_pos (float value, float *pos)
}
static inline void
gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
const GskRenderNode *node,
const GdkRGBA *color,
gboolean force_color)
gsk_gl_render_job_visit_text_node_legacy (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);
@@ -3108,6 +3097,234 @@ gsk_gl_render_job_visit_text_node (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)
@@ -3118,7 +3335,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
/* Shadow nodes recolor every pixel of the source texture, but leave the alpha in tact.
* If the child is a color matrix node that doesn't touch the alpha, we can throw that away. */
if (GSK_RENDER_NODE_TYPE (shadow_child) == GSK_COLOR_MATRIX_NODE &&
if (gsk_render_node_get_node_type (shadow_child) == GSK_COLOR_MATRIX_NODE &&
!color_matrix_modifies_alpha (shadow_child))
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
@@ -3138,7 +3355,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
continue;
if (shadow->radius == 0 &&
GSK_RENDER_NODE_TYPE (shadow_child) == GSK_TEXT_NODE)
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
{
if (dx != 0 || dy != 0)
{
@@ -3332,53 +3549,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
}
}
static gboolean
gsk_gl_render_job_texture_mask_for_color (GskGLRenderJob *job,
const GskRenderNode *mask,
const GskRenderNode *color,
const graphene_rect_t *bounds)
{
int max_texture_size = job->command_queue->max_texture_size;
GdkTexture *texture = gsk_texture_node_get_texture (mask);
const GdkRGBA *rgba;
rgba = gsk_color_node_get_color (color);
if (RGBA_IS_CLEAR (rgba))
return TRUE;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size &&
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)))
{
GskGLRenderOffscreen offscreen = {0};
float scale_x = mask->bounds.size.width / texture->width;
float scale_y = mask->bounds.size.height / texture->height;
gboolean use_mipmap;
guint16 cc[4];
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
rgba_to_half (rgba, cc);
gsk_gl_render_job_upload_texture (job, texture, use_mipmap, &offscreen);
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
GL_TEXTURE0,
offscreen.texture_id,
offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR,
GL_LINEAR,
offscreen.sync);
job->source_is_glyph_atlas = FALSE;
gsk_gl_render_job_draw_offscreen_with_color (job, bounds, &offscreen, cc);
gsk_gl_render_job_end_draw (job);
return TRUE;
}
return FALSE;
}
static inline void
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
const GskRenderNode *node)
@@ -3388,17 +3558,6 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
GskGLRenderOffscreen source_offscreen = {0};
GskGLRenderOffscreen mask_offscreen = {0};
/* If the mask is a texture and the source is a color node
* then we can take a shortcut and avoid offscreens.
*/
if (GSK_RENDER_NODE_TYPE (mask) == GSK_TEXTURE_NODE &&
GSK_RENDER_NODE_TYPE (source) == GSK_COLOR_NODE &&
gsk_mask_node_get_mask_mode (node) == GSK_MASK_MODE_ALPHA)
{
if (gsk_gl_render_job_texture_mask_for_color (job, mask, source, &node->bounds))
return;
}
source_offscreen.bounds = &node->bounds;
source_offscreen.force_offscreen = TRUE;
source_offscreen.reset_clip = TRUE;
@@ -4019,7 +4178,7 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_update_clip (job, &node->bounds, &has_clip))
return;
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_BLEND_NODE:
gsk_gl_render_job_visit_blend_node (job, node);
@@ -4072,12 +4231,12 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (i + 1 < n_children &&
job->current_clip->is_fully_contained &&
GSK_RENDER_NODE_TYPE (child) == GSK_ROUNDED_CLIP_NODE)
gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE)
{
const GskRenderNode *grandchild = gsk_rounded_clip_node_get_child (child);
const GskRenderNode *child2 = children[i + 1];
if (GSK_RENDER_NODE_TYPE (grandchild) == GSK_COLOR_NODE &&
GSK_RENDER_NODE_TYPE (child2) == GSK_BORDER_NODE &&
if (gsk_render_node_get_node_type (grandchild) == GSK_COLOR_NODE &&
gsk_render_node_get_node_type (child2) == GSK_BORDER_NODE &&
gsk_border_node_get_uniform_color (child2) &&
rounded_rect_equal (gsk_rounded_clip_node_get_clip (child),
gsk_border_node_get_outline (child2)))
@@ -4231,7 +4390,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
return FALSE;
}
if (GSK_RENDER_NODE_TYPE (node) == GSK_TEXTURE_NODE &&
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
!offscreen->force_offscreen)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
@@ -4549,6 +4708,15 @@ 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)
@@ -4604,8 +4772,8 @@ gsk_gl_render_job_new (GskGLDriver *driver,
job = g_new0 (GskGLRenderJob, 1);
job->driver = g_object_ref (driver);
job->command_queue = job->driver->command_queue;
clips_init (&job->clip);
modelviews_init (&job->modelview);
job->clip = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderClip), 16);
job->modelview = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderModelview), 16);
job->framebuffer = framebuffer;
job->clear_framebuffer = !!clear_framebuffer;
job->default_framebuffer = default_framebuffer;
@@ -4655,16 +4823,16 @@ gsk_gl_render_job_free (GskGLRenderJob *job)
job->current_modelview = NULL;
job->current_clip = NULL;
while (job->modelview.end > job->modelview.start)
while (job->modelview->len > 0)
{
GskGLRenderModelview *modelview = job->modelview.end-1;
GskGLRenderModelview *modelview = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len-1);
g_clear_pointer (&modelview->transform, gsk_transform_unref);
job->modelview.end--;
job->modelview->len--;
}
g_clear_object (&job->driver);
g_clear_pointer (&job->region, cairo_region_destroy);
modelviews_clear (&job->modelview);
clips_clear (&job->clip);
g_clear_pointer (&job->modelview, g_array_unref);
g_clear_pointer (&job->clip, g_array_unref);
g_free (job);
}
+2 -1
View File
@@ -35,4 +35,5 @@ 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);
+5 -1
View File
@@ -36,9 +36,14 @@ 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;
@@ -48,7 +53,6 @@ typedef struct _GskGLTextureAtlas
* But are now unused.
*/
int unused_pixels;
} GskGLTextureAtlas;
typedef struct _GskGLTextureAtlasEntry
+1
View File
@@ -36,6 +36,7 @@ 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;
+15
View File
@@ -0,0 +1,15 @@
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);
}
+62
View File
@@ -0,0 +1,62 @@
// 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);
}
+25
View File
@@ -0,0 +1,25 @@
// 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);
}
+2
View File
@@ -1,3 +1,5 @@
#extension GL_OES_standard_derivatives : enable
#ifndef GSK_LEGACY
precision highp float;
#endif
+16 -12
View File
@@ -19,10 +19,8 @@
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
@@ -65,6 +63,9 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
@@ -83,7 +84,11 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
@@ -155,13 +160,6 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
@@ -225,7 +223,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y + height < c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
@@ -325,7 +323,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
static int rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
@@ -336,13 +334,19 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
static int rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
+5 -13
View File
@@ -1,15 +1,9 @@
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// stb_rect_pack.h - v0.99 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
@@ -37,12 +31,9 @@
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
@@ -81,10 +72,11 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
+24 -181
View File
@@ -2330,6 +2330,30 @@ gsk_curve_get_crossing (const GskCurve *curve,
return get_class (curve->op)->get_crossing (curve, point);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
/* }}} */
/* {{{ Closest point */
static gboolean
project_point_onto_line (const GskCurve *curve,
const graphene_point_t *point,
@@ -2451,187 +2475,6 @@ gsk_curve_get_closest_point (const GskCurve *curve,
return find_closest_point (curve, point, threshold, 0, 1, out_dist, out_t);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
/* Compute the inverse of the arclength using bisection,
* to a given precision
*/
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
static inline void
_sincosf (float angle,
float *out_s,
float *out_c)
{
#ifdef HAVE_SINCOSF
sincosf (angle, out_s, out_c);
#else
*out_s = sinf (angle);
*out_c = cosf (angle);
#endif
}
static void
align_points (const graphene_point_t *p,
const graphene_point_t *a,
const graphene_point_t *b,
graphene_point_t *q,
int n)
{
graphene_vec2_t n1;
float angle;
float s, c;
get_tangent (a, b, &n1);
angle = - atan2f (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
_sincosf (angle, &s, &c);
for (int i = 0; i < n; i++)
{
q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
}
}
static int
filter_allowable (float t[3],
int n)
{
float g[3];
int j = 0;
for (int i = 0; i < n; i++)
if (0 < t[i] && t[i] < 1)
g[j++] = t[i];
for (int i = 0; i < j; i++)
t[i] = g[i];
return j;
}
/* find solutions for at^2 + bt + c = 0 */
static int
solve_quadratic (float a, float b, float c, float t[2])
{
float d;
int n = 0;
if (fabsf (a) > 0.0001)
{
if (b*b > 4*a*c)
{
d = sqrtf (b*b - 4*a*c);
t[n++] = (-b + d)/(2*a);
t[n++] = (-b - d)/(2*a);
}
else
{
t[n++] = -b / (2*a);
}
}
else if (fabsf (b) > 0.0001)
{
t[n++] = -c / b;
}
return n;
}
int
gsk_curve_get_curvature_points (const GskCurve *curve,
float t[3])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[4];
float a, b, c, d;
float x, y, z;
int n;
if (curve->op != GSK_PATH_CUBIC)
return 0; /* FIXME */
align_points (pts, &pts[0], &pts[3], p, 4);
a = p[2].x * p[1].y;
b = p[3].x * p[1].y;
c = p[1].x * p[2].y;
d = p[3].x * p[2].y;
x = - 3*a + 2*b + 3*c - d;
y = 3*a - b - 3*c;
z = c - a;
n = solve_quadratic (x, y, z, t);
return filter_allowable (t, n);
}
/* Find cusps inside the open interval from 0 to 1.
*
* According to Stone & deRose, A Geometric Characterization
* of Parametric Cubic curves, a necessary and sufficient
* condition is that the first derivative vanishes.
*/
int
gsk_curve_get_cusps (const GskCurve *curve,
float t[2])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[3];
float ax, bx, cx;
float ay, by, cy;
float tx[3];
int nx;
int n = 0;
if (curve->op != GSK_PATH_CUBIC)
return 0;
p[0].x = 3 * (pts[1].x - pts[0].x);
p[0].y = 3 * (pts[1].y - pts[0].y);
p[1].x = 3 * (pts[2].x - pts[1].x);
p[1].y = 3 * (pts[2].y - pts[1].y);
p[2].x = 3 * (pts[3].x - pts[2].x);
p[2].y = 3 * (pts[3].y - pts[2].y);
ax = p[0].x - 2 * p[1].x + p[2].x;
bx = - 2 * p[0].x + 2 * p[1].x;
cx = p[0].x;
nx = solve_quadratic (ax, bx, cx, tx);
nx = filter_allowable (tx, nx);
ay = p[0].y - 2 * p[1].y + p[2].y;
by = - 2 * p[0].y + 2 * p[1].y;
cy = p[0].y;
for (int i = 0; i < nx; i++)
{
float ti = tx[i];
if (0 < ti && ti < 1 &&
fabsf (ay * ti * ti + by * ti + cy) < 0.001)
t[n++] = ti;
}
return n;
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
File diff suppressed because it is too large Load Diff
+14
View File
@@ -22,6 +22,7 @@
#include "gskpathopprivate.h"
#include "gskpath.h"
#include "gskpathprivate.h"
#include "gskboundingboxprivate.h"
G_BEGIN_DECLS
@@ -187,6 +188,19 @@ int gsk_curve_get_curvature_points (const GskCurve
int gsk_curve_get_cusps (const GskCurve *curve,
float t[2]);
int gsk_curve_intersect (const GskCurve *curve1,
const GskCurve *curve2,
float *t1,
float *t2,
graphene_point_t *p,
GskPathIntersection *kind,
int n);
int gsk_curve_self_intersect (const GskCurve *curve,
float *t1,
graphene_point_t *p,
int n);
G_END_DECLS
+1
View File
@@ -17,6 +17,7 @@ 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;
+2 -1
View File
@@ -19,7 +19,8 @@ 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_STAGING = 1 << 12,
GSK_DEBUG_NO_GLYPHY = 1 << 13
} GskDebugFlags;
#define GSK_DEBUG_ANY ((1 << 13) - 1)
+1712
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -56,5 +56,27 @@ 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
+6 -11
View File
@@ -287,21 +287,15 @@ gsk_render_node_alloc (GskRenderNodeType node_type)
* Returns: (transfer full): the `GskRenderNode` with an additional reference
*/
GskRenderNode *
(gsk_render_node_ref) (GskRenderNode *node)
gsk_render_node_ref (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
return _gsk_render_node_ref (node);
}
g_atomic_ref_count_inc (&node->ref_count);
void
_gsk_render_node_unref (GskRenderNode *node)
{
if G_UNLIKELY (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
return node;
}
/**
* gsk_render_node_unref:
* @node: (transfer full): a `GskRenderNode`
@@ -312,11 +306,12 @@ _gsk_render_node_unref (GskRenderNode *node)
* freed.
*/
void
(gsk_render_node_unref) (GskRenderNode *node)
gsk_render_node_unref (GskRenderNode *node)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
_gsk_render_node_unref (node);
if (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
}
+55
View File
@@ -43,6 +43,10 @@
#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.
@@ -5460,6 +5464,8 @@ struct _GskTextNode
PangoFont *font;
gboolean has_color_glyphs;
gboolean embolden;
PangoMatrix matrix;
GdkRGBA color;
graphene_point_t offset;
@@ -5468,6 +5474,37 @@ 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)
{
@@ -5593,6 +5630,8 @@ 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;
@@ -5725,6 +5764,22 @@ 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 */
+30 -6
View File
@@ -33,7 +33,6 @@
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkmemoryformatprivate.h"
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssdataurlprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
@@ -3170,20 +3169,45 @@ append_texture_param (Printer *p,
g_hash_table_insert (p->named_textures, texture, new_name);
}
switch (gdk_memory_format_get_depth (gdk_texture_get_format (texture)))
switch (gdk_texture_get_format (texture))
{
case GDK_MEMORY_U8:
case GDK_MEMORY_U16:
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R8G8B8:
case GDK_MEMORY_B8G8R8:
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16:
case GDK_MEMORY_G8A8_PREMULTIPLIED:
case GDK_MEMORY_G8A8:
case GDK_MEMORY_G8:
case GDK_MEMORY_G16A16_PREMULTIPLIED:
case GDK_MEMORY_G16A16:
case GDK_MEMORY_G16:
case GDK_MEMORY_A8:
case GDK_MEMORY_A16:
bytes = gdk_texture_save_to_png_bytes (texture);
g_string_append (p->str, "url(\"data:image/png;base64,");
break;
case GDK_MEMORY_FLOAT16:
case GDK_MEMORY_FLOAT32:
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_FLOAT:
case GDK_MEMORY_A16_FLOAT:
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT:
case GDK_MEMORY_A32_FLOAT:
bytes = gdk_texture_save_to_tiff_bytes (texture);
g_string_append (p->str, "url(\"data:image/tiff;base64,");
break;
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
}
+4 -13
View File
@@ -21,9 +21,6 @@ extern GType gsk_render_node_types[];
#define GSK_IS_RENDER_NODE_TYPE(node,type) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type == (type))
#define GSK_RENDER_NODE_TYPE(node) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type)
struct _GskRenderNode
{
GTypeInstance parent_instance;
@@ -60,8 +57,6 @@ GType gsk_render_node_type_register_static (const char
gpointer gsk_render_node_alloc (GskRenderNodeType node_type);
void _gsk_render_node_unref (GskRenderNode *node);
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
@@ -92,15 +87,11 @@ gboolean gsk_container_node_is_disjoint (const GskRenderNode
gboolean gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
#define gsk_render_node_ref(node) _gsk_render_node_ref(node)
#define gsk_render_node_unref(node) _gsk_render_node_unref(node)
gboolean gsk_text_node_get_font_embolden (const GskRenderNode *node);
const PangoMatrix *
gsk_text_node_get_font_matrix (const GskRenderNode *node);
static inline GskRenderNode *
_gsk_render_node_ref (GskRenderNode *node)
{
g_atomic_ref_count_inc (&node->ref_count);
return node;
}
G_END_DECLS
+7
View File
@@ -20,6 +20,9 @@ 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([
@@ -29,6 +32,7 @@ gsk_public_sources = files([
'gskpath.c',
'gskpathbuilder.c',
'gskpathmeasure.c',
'gskpathops.c',
'gskpathparser.c',
'gskpathpoint.c',
'gskrenderer.c',
@@ -45,6 +49,7 @@ gsk_private_sources = files([
'gskcairoblur.c',
'gskcontour.c',
'gskcurve.c',
'gskcurveintersect.c',
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
@@ -54,6 +59,7 @@ 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',
@@ -194,6 +200,7 @@ gsk_deps = [
cairo_dep,
cairo_csi_dep,
libgdk_dep,
libglyphy_dep
]
libgsk_f16c = static_library('gsk_f16c',
-25
View File
@@ -80,15 +80,6 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
return info;
}
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8A8:
{
static const GskMemoryFormatInfo info[] = {
@@ -126,17 +117,6 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
return info;
}
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
@@ -344,7 +324,6 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
@@ -352,10 +331,6 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
case GDK_MEMORY_R8G8B8:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
case GDK_MEMORY_B8G8R8:
return GDK_MEMORY_R8G8B8;
+1 -3
View File
@@ -714,9 +714,7 @@ emit_text_changed (GtkAtSpiContext *self,
"org.a11y.atspi.Event.Object",
"TextChanged",
g_variant_new ("(siiva{sv})",
kind, start, end,
g_variant_new_string (text),
NULL),
kind, start, end, g_variant_new_string (text), NULL),
NULL);
}
+3 -12
View File
@@ -1614,10 +1614,7 @@ insert_text_cb (GtkEditable *editable,
return;
length = g_utf8_strlen (new_text, new_text_length);
char *inserted_text = g_utf8_substring (new_text, 0, length);
changed->text_changed (changed->data, "insert", *position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", *position - length, length, new_text);
}
static void
@@ -1632,10 +1629,6 @@ delete_text_cb (GtkEditable *editable,
return;
text = gtk_editable_get_chars (editable, start, end);
if (end < 0)
end = g_utf8_strlen(text, -1);
changed->text_changed (changed->data, "delete", start, end - start, text);
g_free (text);
}
@@ -1714,9 +1707,7 @@ insert_range_cb (GtkTextBuffer *buffer,
position = gtk_text_iter_get_offset (iter);
length = g_utf8_strlen (text, len);
char *inserted_text = g_utf8_substring (text, 0, length);
changed->text_changed (changed->data, "insert", position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", position - length, length, text);
update_cursor (buffer, changed);
}
@@ -1793,7 +1784,7 @@ buffer_changed (GtkWidget *widget,
if (changed->buffer)
{
g_object_ref (changed->buffer);
g_signal_connect_after (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "delete-range", G_CALLBACK (delete_range_cb), changed);
g_signal_connect_after (changed->buffer, "delete-range", G_CALLBACK (delete_range_after_cb), changed);
g_signal_connect_after (changed->buffer, "mark-set", G_CALLBACK (mark_set_cb), changed);
-3
View File
@@ -171,9 +171,6 @@ gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
case GTK_ACCESSIBLE_ROLE_OPTION:
return ATSPI_ROLE_OPTION_PANE;
case GTK_ACCESSIBLE_ROLE_PARAGRAPH:
return ATSPI_ROLE_PARAGRAPH;
case GTK_ACCESSIBLE_ROLE_PRESENTATION:
return ATSPI_ROLE_INVALID;
+2 -5
View File
@@ -12833,12 +12833,9 @@ gtk_tree_view_is_blank_at_pos (GtkTreeView *tree_view,
*column = real_column;
gtk_tree_model_get_iter (priv->model, &iter, real_path);
_gtk_tree_view_find_node (tree_view, real_path, &tree, &node);
if (node == NULL)
if (!_gtk_tree_view_find_node (tree_view, real_path, &tree, &node))
{
if (!path)
gtk_tree_path_free (real_path);
return TRUE;
g_assert_not_reached ();
}
/* Check if there's an expander arrow at (x, y) */
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-1
View File
@@ -209,7 +209,6 @@
#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>
-2
View File
@@ -832,7 +832,6 @@ 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 >
@@ -913,7 +912,6 @@ 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 },
+1 -1
View File
@@ -46,7 +46,7 @@ static gboolean
gtk_accessible_range_default_set_current_value (GtkAccessibleRange *accessible_range,
double value)
{
return TRUE;
return FALSE;
}
static void
-1
View File
@@ -1103,7 +1103,6 @@ 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 >
+1 -1
View File
@@ -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::rgba".
* informed about changes, listen to "notify::color".
*
* Returns: the color
*
+1 -4
View File
@@ -1362,8 +1362,6 @@ 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.
*
@@ -1450,8 +1448,7 @@ 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_PARAGRAPH GDK_AVAILABLE_ENUMERATOR_IN_4_14
GTK_ACCESSIBLE_ROLE_APPLICATION GDK_AVAILABLE_ENUMERATOR_IN_4_12
} GtkAccessibleRole;
/**
-1
View File
@@ -177,7 +177,6 @@ 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);
+2 -2
View File
@@ -4772,7 +4772,7 @@ gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
return;
}
g_object_ref (filter);
g_object_ref_sink (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 (impl->current_filter);
g_object_ref_sink (impl->current_filter);
gtk_drop_down_set_selected (GTK_DROP_DOWN (impl->filter_combo), filter_index);
+1 -1
View File
@@ -86,7 +86,7 @@ struct _GtkMenuTrackerItem
char *action_namespace;
char *action_and_target;
GMenuItem *item;
guint role : 4; /* GtkMenuTrackerItemRole */
GtkMenuTrackerItemRole role : 4;
guint is_separator : 1;
guint can_activate : 1;
guint sensitive : 1;
-1771
View File
File diff suppressed because it is too large Load Diff
-135
View File
@@ -1,135 +0,0 @@
/* 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
+1 -1
View File
@@ -70,7 +70,7 @@ typedef struct {
CachedSizeX cached_size_x;
CachedSizeY cached_size_y;
guint request_mode : 3; /* GtkSizeRequestMode */
GtkSizeRequestMode request_mode : 3;
guint request_mode_valid : 1;
struct {
guint n_cached_requests : 15;
+1 -1
View File
@@ -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_resize (widget);
gtk_widget_queue_draw (widget);
}
/**
+1 -9
View File
@@ -310,7 +310,6 @@ gtk_public_sources = files([
'gtkpopover.c',
'gtkpopovermenu.c',
'gtkpopovermenubar.c',
'gtkprintdialog.c',
'gtkprogressbar.c',
'gtkpropertylookuplistmodel.c',
'gtkrange.c',
@@ -550,7 +549,6 @@ gtk_public_headers = files([
'gtkpopover.h',
'gtkpopovermenu.h',
'gtkpopovermenubar.h',
'gtkprintdialog.h',
'gtkprogressbar.h',
'gtkrange.h',
'gtkrecentmanager.h',
@@ -855,27 +853,20 @@ 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'
]
@@ -1026,6 +1017,7 @@ 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