Compare commits

...

351 Commits

Author SHA1 Message Date
Matthias Clasen
0927c3638a Call malloc_trim after loading images
Not sure this is the best place to do it, but at least it is one
place where we tend to do large, temporary allocations.
2024-03-27 14:15:20 +01:00
Athmane MOKRAOUI
b1eed1c153 Add Kabyle translation 2024-03-26 11:34:22 +00:00
Martin
fac6f6c712 Update Slovenian translation 2024-03-24 23:19:54 +00:00
Martin
3f1fc798f0 Update Slovenian translation 2024-03-24 23:17:49 +00:00
Luca Bacci
e6a86f61dc Merge branch 'fix-issue-3749' into 'main'
GdkWin32: Always set WS_MINIMIZEBOX on GdkToplevel

Closes #3749

See merge request GNOME/gtk!7072
2024-03-22 17:57:06 +00:00
Matthias Clasen
2799632c02 Merge branch 'scalefix' into 'main'
GtkScale: improving symmetry and value positioning

Closes #5171

See merge request GNOME/gtk!6935
2024-03-22 16:18:48 +00:00
Luca Bacci
8ffa681e02 GdkWin32: Always set WS_MINIMIZEBOX on GdkToplevel
Regardless if server-side decorated or not. This way the shell knows
that the window can be minimized.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3749
2024-03-22 16:47:59 +01:00
Matthias Clasen
154035e76f Merge branch 'entry-progress' into 'main'
theme: Make sure progress in entries is visible

Closes #6201

See merge request GNOME/gtk!7071
2024-03-22 15:00:48 +00:00
Matthias Clasen
1d4c664bfa theme: Make sure progress in entries is visible
Give the trough a min height, so it doesn't shrink to nothing.

Fixes: #6201
2024-03-22 09:34:11 -04:00
Matthias Clasen
85a650afce Merge branch 'dnd-cursor-malaise' into 'main'
wayland: Guarantee dnd-move as a cursor name

See merge request GNOME/gtk!7070
2024-03-22 02:15:32 +00:00
Matthias Clasen
f6c4d3731c dnd: Go back to using dnd-move as move cursor
The move cursor in Adwaita is stuck with the 4-headed arrow image
which isn't suitable for a dnd cursor.

See https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/issues/286
2024-03-21 21:36:38 -04:00
Matthias Clasen
5e9070145e wayland: Guarantee dnd-move as a cursor name
We need to go back to using this, since move is widely abused
and thus can't change its image to one thats appropriate for dnd.
2024-03-21 21:35:45 -04:00
Matthias Clasen
81ced841dd Merge branch 'matthiasc/for-main' into 'main'
inspector: Show presentation time protocol

See merge request GNOME/gtk!7069
2024-03-21 12:35:33 +00:00
Matthias Clasen
9837a9dcfd inspector: Show presentation time protocol
We have a list of all the used Wayland protocols and their versions
in the inspector. Lets keep it up-to-date.
2024-03-21 07:29:58 -04:00
Matthias Clasen
1704ec3c7d Merge branch 'wip/chergert/presentation-time' into 'main'
gdk/wayland: implement client side of presentation-time

See merge request GNOME/gtk!6987
2024-03-21 11:28:19 +00:00
Matthias Clasen
c70a326055 Merge branch 'matthiasc/for-main' into 'main'
Sync cursor images with Adwaita

See merge request GNOME/gtk!7065
2024-03-21 02:37:35 +00:00
Christian Hergert
53616a73e9 gdk/wayland: use wp_presentation for more accurate frame timings
This attempts to improve the accuracy for the "presentation_time" of an
individual GdkFrameTimings. That information is currently filled in as soon
as we get a frame callback. However, if presentation-time wayland protocol
is available, that will be used to supliment a more accurate time which
may improve future presentation-time predictions within GdkFrameClockIdle.

The protocol states that all related and sub surfaces will receive the
same information so it is safe that this could be registered for more
than just the toplevel. The information becomes idempotent.
2024-03-20 14:45:58 -07:00
Jordan Petridis
2d3a3d6a78 Merge branch 'alatiera/ci-vulkan' into 'main'
flatpak-build.sh: Do not disable vulkan

See merge request GNOME/gtk!7066
2024-03-20 20:15:54 +00:00
Jordan Petridis
6ca9e5987b flatpak-build.sh: Do not disable vulkan
In a94d7abf0d we removed
the explicit disable from the manifest.

Now we should also have the CI build the vulkan render as well.
2024-03-20 21:18:13 +02:00
Matthias Clasen
2c1590001f Sync cursor images with Adwaita
Several cursor metaphors were changes in Adwaita. Update our docs
and the Cursors demo to match.
2024-03-20 13:19:12 -04:00
Matthias Clasen
82aee038e9 Merge branch 'alatiera/ci-vulkan' into 'main'
flatpak demos: Enable vulkan backend

See merge request GNOME/gtk!7064
2024-03-20 14:46:04 +00:00
Jordan Petridis
a94d7abf0d flatpak demos: Enable vulkan backend
glslc is now in the Sdk itself

https://gitlab.gnome.org/GNOME/gnome-build-meta/-/merge_requests/2640
2024-03-20 15:47:42 +02:00
Matthias Clasen
3b87903889 Merge branch 'wayland-min-version' into 'main'
wayland: Check some required globals

See merge request GNOME/gtk!7062
2024-03-20 02:57:06 +00:00
Matthias Clasen
191f826075 wayland: Only set buffer scale if we can
We check this in some other places, so be consistent.
2024-03-19 22:22:53 -04:00
Matthias Clasen
5d52c43074 wayland: Check all required globals for subsurfaces
Before trying to use subsurfaces, make sure we have both
a subcompositor and a viewporter.
2024-03-19 22:22:53 -04:00
Matthias Clasen
f6a67aeb20 wayland: Check some required globals
This may be largely cosmetics, since these are core protocols that
are unlikely to ever be missing. But lets check anyway.
2024-03-19 17:28:25 -04:00
Jordi Mas
370e2f0940 Update Catalan translation 2024-03-19 21:37:20 +01:00
Alexandre Franke
2ec9fc26d3 Update French translation 2024-03-19 13:06:37 +00:00
Matthias Clasen
c2d898d462 Merge branch 'fix-macos-typo' into 'main'
quartz: Fix a crash

See merge request GNOME/gtk!7059
2024-03-19 03:11:58 +00:00
Matthias Clasen
7c04231255 Merge branch 'macos-remove-shadows' into 'main'
macos: Drop shadow related code from macos backend

See merge request GNOME/gtk!7048
2024-03-19 02:38:38 +00:00
Arjan Molenaar
08216dcee9 macos: Drop shadow related code from macos backend 2024-03-19 02:38:37 +00:00
Matthias Clasen
9817df12ff quartz: Fix a crash
This was an oversight in 816f8807a3.
2024-03-18 21:51:24 -04:00
Matthias Clasen
5b0e8eb574 Merge branch 'fix-macos-typo' into 'main'
macos: Fix a typo in the appmenu handling code

See merge request GNOME/gtk!7055
2024-03-19 01:49:08 +00:00
Matthias Clasen
cecde85faa Merge branch 'drag-cursor-tweak' into 'main'
dnd: Use the default cursor during motion

Closes #6337 and #6511

See merge request GNOME/gtk!7058
2024-03-19 01:46:35 +00:00
Matthias Clasen
aa95b4f341 dnd: Use the default cursor during motion
When no action is selected, use the default cursor, and only
switch to one of the action-indicating cursors when we are over
a drop target.

Fixes: #6337
Fixes: #6511
2024-03-18 21:17:55 -04:00
Matthias Clasen
816f8807a3 macos: Fix a typo in the appmenu handling code
We were using APP_DATA in one place, and APP_MENU in the other.
Just stop using object data for this.
2024-03-18 18:49:55 -04:00
Martin
26d3c407b3 Update Slovenian translation 2024-03-18 17:36:52 +00:00
Matthias Clasen
a973e8ea8d Merge branch 'gl-offload-fixes' into 'main'
gl: Handle offloads in offscreen context better

Closes #6551

See merge request GNOME/gtk!7053
2024-03-18 15:22:22 +00:00
Matthias Clasen
b007597c58 Merge branch 'macos-application-demo' into 'main'
Revert "macos: fix weird menubar rendering."

Closes #6524

See merge request GNOME/gtk!7052
2024-03-18 14:40:45 +00:00
Matthias Clasen
1e83a44c93 gl: Handle offloads in offscreen context better
Back out of offloading below if we are in an offscreen context,
since the hole will get lost in the offscreen.

Fixes: #6551
2024-03-18 08:41:31 -04:00
Matthias Clasen
e1406d2e95 Merge branch 'matthiasc/for-main' into 'main'
gsk: Avoid some allocations

See merge request GNOME/gtk!7047
2024-03-18 12:26:37 +00:00
Matthias Clasen
259ad83de9 macos: Fix up app menu support
We were forgetting to add the newly loaded app menu to the
combined menubar. Pointed out by Dominik Reichardt in #6524.

Fixes: #6524
2024-03-18 07:50:30 -04:00
Daniel Rusek
2fe467983c Update Czech translation 2024-03-18 11:30:47 +00:00
Matthias Clasen
b4f5432d5a gtk4-demo: Clean up the application demo
This partially reverts ca1c570c21.
2024-03-17 22:29:22 -04:00
Matthias Clasen
4fe4523c49 Revert "macos: fix weird menubar rendering."
This reverts commit 75868dfee4.
2024-03-17 22:29:22 -04:00
Matthias Clasen
ee4a56ed4a settings: Mention the macOS implementation 2024-03-17 21:44:02 -04:00
Matthias Clasen
2408e227aa Add another xfail for clipped compare tests
These just keep happening.
2024-03-17 21:30:36 -04:00
Matthias Clasen
144cd2d91c gsk: Avoid some allocations
We can use a static font options object and allocate it only once.
2024-03-17 21:30:36 -04:00
Matthias Clasen
6abd9def55 Merge branch 'macos-popover-focus' into 'main'
macos: Fix IMContext for popovers

See merge request GNOME/gtk!7041
2024-03-17 16:55:52 +00:00
Martin
f5685cc0ae Update Slovenian translation 2024-03-17 10:28:21 +00:00
Martin
54bd03573e Update Slovenian translation 2024-03-17 10:26:36 +00:00
Matthias Clasen
bc81b33990 Merge branch 'matthiasc/for-main' into 'main'
Forgotten file

See merge request GNOME/gtk!7046
2024-03-17 03:05:56 +00:00
Matthias Clasen
de764d61ef Forgotten file 2024-03-16 22:26:22 -04:00
Matthias Clasen
68fa9bcf2e Merge branch 'matthiasc/for-main' into 'main'
4.14.1

See merge request GNOME/gtk!7045
2024-03-17 02:11:30 +00:00
Matthias Clasen
2f124bc712 Post-release version bump 2024-03-16 22:10:26 -04:00
Matthias Clasen
c648bb7b19 NEWS: Updates 2024-03-16 20:52:15 -04:00
Matthias Clasen
90956b15d9 docs: Small tweaks 2024-03-16 20:52:15 -04:00
Benjamin Otte
195ebf6848 Merge branch 'wip/otte/gl-map-buffer' into 'main'
Add GLBuffer implementation w/ persistent mapping

See merge request GNOME/gtk!7042
2024-03-17 00:27:51 +00:00
Benjamin Otte
0615b48318 Merge branch 'wip/otte/VYycQTm2HrM' into 'main'
gpu: Sort passes correctly

Closes #6318

See merge request GNOME/gtk!7044
2024-03-16 23:08:05 +00:00
Benjamin Otte
aff34e8d1b gpu: Sort passes correctly
In a very particular situation, it could happen that our renderpass
reordering did not work out.
Consider this nesting of renderpasses (indentation indicates subpasses):

pass A
  subpass of A
pass B
  subpass of B

Out reordering code would reorder this as:

subpass of B
subpass of A
pass A
pass B

Which doesn't sound too bad, the subpasses happen before the passes
after all.

However, a subpass might be a pass that converts the image for a texture
stored in the texture cache and then updates the cached image.
If "subpass of A" is such a pass *and* if "subpass of B" then renders
with exactly this texture, then "subpass of B" will use the result of
"subpass of A" as a source.

The fix is to ensure that subpasses stay ordered, too.

The new order moves subpasses right before their parent pass, so the
order of the example now looks like:

subpass of A
pass A
subpass of B
pass B

The place where this would happen most common was when drawing thumbnail
images in Nautilus, the GTK filechooser or Fractal.
Those images are usually PNG files, which are straight alpha. They are then
drawn with a drop shadow, which requires an offscreen for drawing as
well as those images as premultipled sources, so lots of subpasses happen.
If there is then a redraw with a somewhat tricky subregion, then the
slicing of the region code could end up generating 2 passes that each draw
half of the thumbnail image - the first pass drawing the top half and the
second pass drawing the bottom half.
And due to the bug the bottom half would then be drawn from the
offscreen before the actual contents of the offscreen would be drawn,
leading to a corrupt bottom part of the image.

Test included.

Fixes: #6318
2024-03-16 23:44:59 +01:00
Matthias Clasen
c05bb504ff Merge branch 'accessible-leaks' into 'main'
Fix leaks of GtkAccessible and GtkATContext

See merge request GNOME/gtk!7031
2024-03-16 21:39:43 +00:00
Benjamin Otte
47307dc7c1 vulkan: Prefer cached buffer memory
We write the buffers in small chunks, and we even sometimes read it. So
prefer it when it's cached.

Speeds up the text benchmarks by a factor of 3x on my dedicated GPU.
2024-03-16 22:32:49 +01:00
Matthias Clasen
16ea91c1fe Merge branch 'macos-fullscreen-resize' into 'main'
macos: Cleanup fullscreen state

See merge request GNOME/gtk!7043
2024-03-16 21:27:29 +00:00
Benjamin Otte
96b800fa0c gl: Add buffer implementation using persistent mapping
If glBufferStorage() is available, we can replace our usage of
glBufferSubData() with persistently mapped storage via
glMappedBufferRange().

This has 1 disadvantage:

1. It's not supported everywhere, it requires GL 4.4 or
   GL_EXT_buffer_storage. But every GPU of the last 10 years should
   implement it. So we check for it and keep the old code.
   The old code can also be forced via GDK_GL_DISABLE=buffer-storage.

But it has 2 advantages:

1. It is what Vulkan does, so it unifies the two renderers' buffer
   handling.

2. It is a significant performance boost in use cases with large vertex
   buffers. Those are pretty rare, but do happen with lots of text at a
   small font size. An example would be a small font in a maximized VTE
   terminal or the overview in gnome-text-editor.

A custom benchmark tailored for this problem can be created with:

  tests/rendernode-create-tests 1000000 text.node

This creates a node file called "text.node" that draws 1 million text
nodes.
(Creating that test takes a minute or so. A smaller number may be useful
on less powerful hardware than my Intel Tigerlake laptop.)
The difference can then be compared via:

  tools/gtk4-rendernode-tool benchmark --runs=20 text.node
and
  GDK_GL_DISABLE=buffer-storage tools/gtk4-rendernode-tool benchmark --runs=20 text.node

For my laptop, the difference is:
before: 1.1s
after:  0.8s

Related: !7021
2024-03-16 20:55:26 +01:00
Benjamin Otte
e7a2baf78c gpu: Remove unused arguments
It's not just unused, it's also wrong.

We are reading from the buffer when reallocating the vertex buffer
and memcpy()ing the old into the new buffer - at that point we read from
it.
2024-03-16 19:46:37 +01:00
Matthias Clasen
438d86fcf5 gsk: Move the buffer upload counter
Move the sysprof counter for buffer uploads to the generic
code, so it works for both ngl and Vulkan. This partially
reverts commit ecf1b7c18a.
2024-03-16 19:39:16 +01:00
Arjan Molenaar
4fd848c9de macos: Retrieve NSEvents based on event properties
We cannot depend on the exact event, since some events (e.g. for popups)
are rewritten. Therefore we need to determine the NSEvent based on
heuristics. The usual suspects are event type, device and timestamp.

This allows us to fix IMContext for popups.
2024-03-16 17:25:38 +01:00
Matthias Clasen
a23a7d4149 Merge branch 'maze-demo' into 'main'
demos: Make the maze demo non-resizable

Closes #6549

See merge request GNOME/gtk!7040
2024-03-16 14:41:27 +00:00
Matthias Clasen
1cbdf88b0f Merge branch 'debug-cleanup' into 'main'
gsk: Fix a typo

See merge request GNOME/gtk!7039
2024-03-16 14:41:16 +00:00
Benjamin Otte
0a0feef57d Merge branch 'wip/otte/gdk-gl-disable' into 'main'
Rework GL feature handling

See merge request GNOME/gtk!7038
2024-03-16 14:25:11 +00:00
Matthias Clasen
2701a2bfdd demos: Make the maze demo non-resizable
It isn't playable if the entrance/exit don't reach the edge
of the window.

Fixes: #6549
2024-03-16 10:08:37 -04:00
Benjamin Otte
2aea75f426 testsuite: Run the plain test without any args
Never do nothing.
2024-03-16 14:53:22 +01:00
Matthias Clasen
b1fb7cd4ae gsk: Drop unused debug flags
The 'surface', 'sync' and 'opengl' flags are not used anywhere.
2024-03-16 09:44:57 -04:00
Matthias Clasen
33ffe28236 docs: Clarify GSK_DEBUG=vulkan
Make it clearer what this debug flag does.
2024-03-16 09:44:57 -04:00
Matthias Clasen
fd90b56df6 gsk: Move and clarify a debug message
Move the only error message in the OPENGL category to RENDERER,
and make it clearer what and how.
2024-03-16 09:44:57 -04:00
Benjamin Otte
43373e6350 gpu: Rename env var GSK_GPU_SKIP to GSK_GPU_DISABLE
See previous commits.
2024-03-16 14:11:08 +01:00
Benjamin Otte
afd5ea53d8 vulkan: Rename env var from GDK_VULKAN_SKIP to GDK_VULKAN_DISABLE
It's a better name.
2024-03-16 14:03:36 +01:00
Benjamin Otte
f725bdad25 gl: Move GL_ARB_base_instance check
It's a GLContext feature check, not a GpuRenderer thing.

So put it there.
2024-03-16 13:52:28 +01:00
Benjamin Otte
cfbe3709bf gpu: Respect the GDK_GL_DISABLE flag
It's now possible to disable sync support.
2024-03-16 13:52:21 +01:00
Benjamin Otte
4e453acd4f gl: Remove the BGRA feature
Nobody is using it anymore now that we have format tracking for all
formats.
2024-03-16 13:44:02 +01:00
Benjamin Otte
3a04542146 gl: Add GDK_GL_DISABLE env var
This allows disabling certain GL features for testing, same as with
Vulkan.
2024-03-16 13:44:02 +01:00
Benjamin Otte
d6a1eb1b2f gl: Split out function
This splits feature checks into its own function.

Which in turn allows splitting the check from the actual reaction to the
flags.
2024-03-16 13:44:02 +01:00
Benjamin Otte
802110bfe5 vulkan: Change function prototype
The function cannot return an error, so don't make that possible.
2024-03-16 13:44:02 +01:00
Benjamin Otte
141769fb46 gl: Turn has_foo flags into GdkGLFeatures
The goal is to have it mirror GdkVulkanFeatures, and in particular
having an environment variable to turn individual flags off.
2024-03-16 13:44:02 +01:00
Benjamin Otte
0fdb6a9243 gl: Remove an unnecessary make_current()
This function is called only from make_current() after all, so the
context is already current.
2024-03-16 13:44:02 +01:00
Benjamin Otte
d007d136c5 Merge branch 'wip/otte/merge-ops' into 'main'
Speed up stuff

See merge request GNOME/gtk!7036
2024-03-16 09:43:06 +00:00
Matthias Clasen
cb374efb9a Merge branch 'matthiasc/for-main' into 'main'
gdk: Describe egl formats more precisely

See merge request GNOME/gtk!7037
2024-03-16 02:12:16 +00:00
Matthias Clasen
8334d21c87 gdk: Describe egl formats more precisely
Mention the presence of a depth of stencil buffer.

Related: #6542
2024-03-15 21:52:23 -04:00
Matthias Clasen
6e132463f1 Merge branch 'matthiasc/for-main' into 'main'
glcontext: Don't call get_instance_private (NULL)

See merge request GNOME/gtk!7035
2024-03-15 21:59:49 +00:00
Arjan Molenaar
3f8f6f6792 macos: Let host determine window sizes
Clean up lastUnfullscreenFrame attribute, as we do not really
need it. The application knows what to resize to.
2024-03-15 21:55:44 +01:00
Benjamin Otte
93cdcc5e88 gpu: Merge multiple ops into one ShaderOp
When ops get allocated that use the same stats as the last op, put them
into the same ShaderOp. This reduces the number of ShaderOps we need to
record, which has 3 benefits:

1. It's less work when iterating over all the ops.
   This isn't a big win, but it makes submit() and print() run a bit
   faster.
2. We don't need to manage data per-op.
   This is a large win because we don't need to ref/unref descriptors
   as much anymore, and refcounting is visible on profiles.
3. We save memory.
   This is a pretty big win because we iterate over ops a lot, and when
   the array is large enough (I've managed to write testcases that makes
   it grow to over 4GB) it kills all the caches and that's bad.

The main benefit of all this are glyphs, which used to emit 1 ShaderOp
per glyph and can now end up with 1 ShaderOp for multiple text nodes,
even if those text nodes use different fonts or colors - because they
can all share the same ColorizeOp.
2024-03-15 20:25:02 +01:00
Matthias Clasen
d51912c0b4 gsk: Add gsk_gpu_frame_get_last_op
This function will be used in the future to find the previous
op during node processing, so we can make optimization decisions
based on that.
2024-03-15 20:25:02 +01:00
Benjamin Otte
bad6e1e102 gpu: Change the way we merge draw calls
With potentially multiple ops per ShaderOp, we may encounter situations
where 1 ShaderOp contains more ops than we want to merge. (With
GSK_GPU_SKIP=merge, we don't want to merge at all.)

So we still merge the ShaderOps (now unconditionally), but we then run
a loop that potentially splits the merged ops again - exactly at the
point we want to.

This way we can merge ops inside of ShaderOps and merge ShaderOps, but
still have the draw calls contain the exact number of ops we want.
2024-03-15 20:25:02 +01:00
Benjamin Otte
28a8dc5a14 gpu: Add GskGpuShaderOp.n_ops
This just introduces the variable and sets it to 1 everywhere.

The ultimate goal is to allow one ShaderOp to collect multiple ops into
one, thereby saving memory in the ops array and leading to faster
performance.
2024-03-15 19:49:17 +01:00
Benjamin Otte
975cdd8c30 gpu: Remove unused return value from function
Technically, an alloc() function should return what it allocated. But
the return value is never used.

Maybe we should rename the function?
2024-03-15 19:49:17 +01:00
Benjamin Otte
153b78e2bc gpu: Add a ShaderOp.print_instance vfunc
... and add gsk_shader_op_print() to do the generic stuff.
2024-03-15 19:49:17 +01:00
Benjamin Otte
de2b10e46c gpu: Set variable to NULL after freeing
Saw this while reviewing code.
2024-03-15 19:49:17 +01:00
Matthias Clasen
7cf4414f4a ci: Drop some unnecessary packages
We don't use at, at-spi or the docbook stylesheets.
2024-03-15 13:06:54 -04:00
Matthias Clasen
a9dfec8478 glcontext: Don't call get_instance_private (NULL)
ubsan does not like this.

See a9175e0c03 for a detailed explanation.
2024-03-15 13:06:34 -04:00
Matthias Clasen
60ddf7c421 Merge branch 'wip/smcv/no-zink-when-screen-scraping' into 'main'
testsuite: Force Mesa to use software GL when asserting about stderr

Closes #6478

See merge request GNOME/gtk!6949
2024-03-15 17:05:12 +00:00
Tim Sabsch
1922174c9f Update German translation 2024-03-14 20:36:56 +00:00
Changwoo Ryu
3c39c5259e Update Korean translation 2024-03-14 10:57:06 +00:00
Matthias Clasen
f5a6d93939 Merge branch 'wip/otte/who-framed-roger-rabbit' into 'main'
Don't reuse frames while they're in use

See merge request GNOME/gtk!7030
2024-03-14 10:21:34 +00:00
Benjamin Otte
30dddf2412 gpu: Refactor waiting for frames
Instead of having renderer API to wait for any number of frames, just
have gsk_gpu_frame_wait() to wait for a single frame.

This unifies behavior on Vulkan and GL, because unlike Vulkan, GL does
not allow waiting for multiple fences.

To make up for it, we replace waiting for multiple frames with finding
the frame with the earliest timestamp and waiting for that one.

Also implement wait() for GL.
2024-03-14 06:06:33 +01:00
Elliott Sales de Andrade
19a9215e4f Fix leaks of GtkAccessible and GtkATContext
These variables are all assigned from function calls that are transfer
full, so they need an unref.
2024-03-14 00:50:17 -04:00
Benjamin Otte
b43950d0f7 gpu: Don't reuse frames while they're in use
This copies the Vulkan idea of using a fence at the end of command
submission and waiting until it gets signaled before reusing the frame.

This frees up the GL driver from doing the work of making buffers etc
reusable and instead allocates new ones when they're still in use and is
a pretty massive performance win.
2024-03-14 04:53:12 +01:00
Matthias Clasen
6e5a183c98 Merge branch 'matthiasc/for-main' into 'main'
gtk-demo: Skip gl shader when necessary

Closes #6538

See merge request GNOME/gtk!7029
2024-03-14 01:29:32 +00:00
Matthias Clasen
d224110b48 gtk-demo: Skip the transitions demo when necessary
This demo uses GL shader nodes which only work with the GL renderer,
therefore skip the demo unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:17 -04:00
Matthias Clasen
8f356c2e8c gtk-demo: Skip gl shader when necessary
GL shader nodes only work with the GL renderer, therefore skip
the Shader in the list unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:10 -04:00
Matthias Clasen
139ed2c900 Merge branch 'textview-cursor-anchor' into 'main'
textview: Fix cursor/anchor mixup when retrieving surrounding text

Closes #6460

See merge request GNOME/gtk!6929
2024-03-14 00:07:41 +00:00
Matthias Clasen
32e21d5402 Merge branch 'speedup-inner-loop' into 'main'
Simplify our inner loop

See merge request GNOME/gtk!7026
2024-03-13 12:41:43 +00:00
Marek Kasik
fb3d8b8523 printing: Avoid accessing freed printers
Print backend can be disposed together with all its printers
as a reaction to user stopping enumeration of printers.
Adding a weak pointer help us to detect that the backend
was disposed and hence the backend and its printers should not
be used anymore.

Fixes #6265
2024-03-13 11:17:42 +01:00
Matthias Clasen
380523b41b gsk: Eschew more divisions
Pull out a pango_scale_inv constant, and use it.
2024-03-13 01:26:14 -04:00
Matthias Clasen
2fda256bb0 gsk: Avoid some unnecessary calls
Most of the time, the image we get for the glyphs will be the
same (the atlas), so avoid adding it to the descriptor set over
and over, and check first if have to. This matches what the
pattern variant of this function already does.
2024-03-13 01:03:32 -04:00
Matthias Clasen
c71a66b6f6 gsk: Simplify our inner loop
Pull out the if-else and precompute things before the loop.
2024-03-13 01:03:31 -04:00
Matthias Clasen
cb92778478 gsk: Drop the glyph-align flag
It wasn't doing anymore what it was designed for, and we are not
sure that we need it.
2024-03-13 01:00:49 -04:00
Matthias Clasen
ab67936a64 Merge branch 'matthiasc/for-main' into 'main'
Drop an unused header

See merge request GNOME/gtk!7025
2024-03-13 04:44:07 +00:00
Matthias Clasen
0ae2c1a8a7 Drop an unused header
This came in with a GskPath-related merge, but it isn't used
anywhere. So drop it for now.
2024-03-12 22:14:31 -04:00
Matthias Clasen
4e166f39fe Merge branch 'matthiasc/for-main' into 'main'
Some small fixes and improvements

See merge request GNOME/gtk!7022
2024-03-12 20:52:48 +00:00
Matthias Clasen
5f79958716 gsk: Simplify some code
Just initialize the rect directly. This matches better what the
pattern variant of this method does, and it also has the nice
side-effect of eliminating the handling of negative scales in
gsk_rect_scale, which we don't need here, since our scales are

always positive.
2024-03-12 16:13:42 -04:00
Matthias Clasen
aee0af34af filechooser: Assert that a string isn't NULL
It shouldn't ever be NULL, but lets make that explicit. since I've
been seeing crash reports that look like people are getting NULL
here.
2024-03-12 14:58:13 -04:00
Matthias Clasen
7e32eb2e98 entry: Add some tests for editable implementation
Test some of the editable api that is used in the filechooser
entry, since people are seeing crashes there.
2024-03-12 14:58:13 -04:00
Matthias Clasen
7ea7d5c390 Merge branch '6520_dont_drag_hidden_paned_handle' into 'main'
paned: don't claim drag-begin on invisible handle

Closes #6520

See merge request GNOME/gtk!7016
2024-03-12 15:46:53 +00:00
Matthias Clasen
e3e9dda429 Merge branch 'macos_ci' into 'main'
Maintenance update for macOS Intel CI

See merge request GNOME/gtk!7005
2024-03-12 15:45:59 +00:00
Matthias Clasen
a3ab25bf1d Merge branch 'wip/chergert/defer-cache-cleanup' into 'main'
gtk/textview: defer GtkTextLineDisplay finalization

See merge request GNOME/gtk!7019
2024-03-12 15:42:30 +00:00
Artur S0
095dec9238 Update Russian translation 2024-03-12 13:25:35 +00:00
Daniel Rusek
0e34365139 Update Czech translation 2024-03-12 12:40:43 +00:00
Matthias Clasen
88a62564f1 Merge branch 'matthiasc/for-main' into 'main'
Matthiasc/for main

See merge request GNOME/gtk!7020
2024-03-12 12:14:27 +00:00
Matthias Clasen
6ac94dc5c3 Post-release version bump 2024-03-12 08:12:52 -04:00
Matthias Clasen
5a9a0874bd 4.14.0 2024-03-12 07:52:13 -04:00
Matthias Clasen
91992111c3 Merge branch 'matthiasc/for-main' into 'main'
gsk: Rework font reloading again

See merge request GNOME/gtk!7018
2024-03-12 11:47:20 +00:00
Daniel Mustieles
120d874805 Update Spanish translation 2024-03-12 08:35:58 +00:00
Matthias Clasen
9454bad891 gsk: Rework font reloading again
Make a single gsk_reload_font helper that can tweak both
scale and font options, so we can ensure that our scaled
font has hint-metrics turned off (pango pays attention to
hint metrics when sizing and rendering hex boxes, and that
hurts us.
2024-03-12 00:45:14 -04:00
Christian Hergert
9cb410fd9b gtk/textview: defer GtkTextLineDisplay finalization
Defer the finalization of our GtkTextLineDisplay until we've completed
processing the current frame. Otherwise we risk doing additional work that
could cause us to miss our frame deadline.
2024-03-11 21:05:35 -07:00
Matthias Clasen
0f3fbed13c Merge branch 'wip/otte/for-main' into 'main'
Don't offscreen subsurface nodes

Closes #6499

See merge request GNOME/gtk!7009
2024-03-11 23:33:24 +00:00
Matthias Clasen
43ee9746bd Merge branch 'matthiasc/for-main' into 'main'
gsk: Avoid some roundf calls

See merge request GNOME/gtk!7017
2024-03-11 23:21:27 +00:00
Matthias Clasen
7283c5c22f gsk: Avoid some roundf calls
It seems that gcc has a hard time using intrinsics for round,
so help it out by using floor (x + .5).
2024-03-11 17:41:39 -04:00
Matthias Clasen
8b71fe4af6 Add an xfail for a rounded-clip test
This needs some changes in how we prevent offscreens from getting
too big. Filed as #6532.
2024-03-11 17:08:33 -04:00
René de Hesselle
b627fb5970 ci: Install ninja from wheel for Big Sur runner
This avoids building it on the Big Sur Intel runner (because of
Python 3.8) which would require us to provide cmake.
2024-03-11 21:30:37 +01:00
Matthias Clasen
be3ad1ef99 Merge branch 'wip/chergert/fix-6529' into 'main'
gtk/imcontext: fix ABI break via activate_osk_with_event

Closes #6529

See merge request GNOME/gtk!7015
2024-03-11 20:15:35 +00:00
g.willems
54264a9f78 paned: don't claim drag-begin on invisible handle
Paned handles are hidden when any of its children are hidden too,
but drag events were still accepted around the (virtual) handle position.

Instead, deny drag-begin when handle is hidden.

Fixes #6520
Closes #6520
2024-03-11 20:39:47 +01:00
Matthias Clasen
65380c66bd Merge branch 'matthiasc/for-main' into 'main'
label: Don't forget to clear select info

See merge request GNOME/gtk!7012
2024-03-11 19:35:51 +00:00
Matthias Clasen
8c96991ce0 Merge branch 'text-view-cursor-blink' into 'main'
textview: Match cursor blink behavior of GtkText

Closes #6515

See merge request GNOME/gtk!7014
2024-03-11 19:13:09 +00:00
Christian Hergert
07a44993ac gtk/imcontext: fix ABI break via activate_osk_with_event
Fixes #6529
2024-03-11 12:06:22 -07:00
Matthias Clasen
60d2d25463 Merge branch 'wip/public-activate-osk' into 'main'
gtkimcontext: Make gtk_im_context_activate_osk() public

See merge request GNOME/gtk!7013
2024-03-11 17:59:42 +00:00
Carlos Garnacho
907f99b176 gtkimcontextwayland: Drop the implicit gesture
Expect all users to call gtk_im_context_activate_osk() to get
on-screen keyboard features.
2024-03-11 18:04:16 +01:00
Carlos Garnacho
ce6aa73c64 gtkimcontext: Make gtk_im_context_activate_osk() public
Make this API public so that foreign "text" widgets (e.g. VteTerminal)
have a chance to integrate this logic into their own event controllers,
without having to craft the behavior of their own gestures around the
built-in IM gesture.

In order to make it most useful for other backends, a GdkEvent argument
and a boolean return value were added. This might be useful information
for other platforms than Wayland, e.g. all investigation seems to hint
that on Windows only the a11y keyboard is available programmatically
via app launching, so the IM method implementation would need to set
up its own policies for showing up the OSK (e.g. on touch events).
2024-03-11 18:04:14 +01:00
Matthias Clasen
257bef85d0 textview: Match cursor blink behavior of GtkText
This makes the conditions in cursor_blinks() more similar to
what GtkText does, and fixes adds the same notify handler for
has-focus, so we start blinking when requires. Crucially, we
also no longer try to blink when unmapped, which should fix
a epiphany crash.

Fixes: #6515
2024-03-11 11:34:40 -04:00
Matthias Clasen
a48df87a85 label: Don't forget to clear select info
This was showing up as crashes in the testsuite, where a later
test runs the mainloop, and that causes Wayland to claim the
primary selection on a widget that is already disposed.
2024-03-11 08:31:41 -04:00
Matthias Clasen
fe4cd7cf0f Merge branch 'matthiasc/for-main' into 'main'
Add more offload tests

See merge request GNOME/gtk!7010
2024-03-11 02:31:13 +00:00
Matthias Clasen
229b34d478 Add more offload tests
These test various clip scenarios.
2024-03-10 22:08:44 -04:00
Benjamin Otte
1985f2c9ad gpu: Make intersecting rounded rect with NONE clip always succeed
This is a tricky topic, because it can make the clip bounds grow, so
previously we were trying to be careful.

However, this can cause perfectly trivial intersections to fail that are
caused by redraw diff regions.
And in the worst case, that means we offscreen in places where we
absolutely do not want to offscreen - in subtrees with subsurface nodes.

Fixes #6499
2024-03-11 01:39:40 +01:00
Benjamin Otte
01d57a7566 gpu: Initial clip is always NONE
We scissor the initial clip (which is why it's an integer rect that is
assigned to the scissor). And if we scissor, the result is a NONE clip.
2024-03-11 01:39:40 +01:00
Benjamin Otte
7a4b2c10c7 gpu: contained clip is a rectangular clip, too
So we can treat it like rect clip and promote it to NONE after a
successful scissor.
2024-03-11 01:39:40 +01:00
Benjamin Otte
208b2d37b6 gpu: Clarify clip types
CLIP_TYPE_NONE is valid if the clip is implemented by the scissor rect.

We always have a scissor rect and there's no way to draw outside of it.

In theory that means we can reset the clip to NONE at any point we
wish if we know nodes are contained inside a certain pixel-aligned
rectangle we can clip.
In practice that's probably quite hard...
2024-03-11 01:39:40 +01:00
Benjamin Otte
ef98912779 nodeparser: Print subsurface nodes properly
The nodes actually end.

Tests included.
2024-03-11 01:39:40 +01:00
Matthias Clasen
b1e3b18ede Merge branch 'matthiasc/for-main' into 'main'
ci: Add more xfails

See merge request GNOME/gtk!7007
2024-03-10 23:57:42 +00:00
Matthias Clasen
0194cadbc0 ci: Add more xfails
The gradient tests are prone to rounding errors when clipped,
so fail them.
2024-03-10 16:53:12 -04:00
Matthias Clasen
b4dfc4adfc NEWS: Updates 2024-03-10 13:45:57 -04:00
Ask Hjorth Larsen
fd556ec377 Update Danish translation 2024-03-10 17:33:33 +00:00
Matthias Clasen
1dbc1d67f5 Merge branch 'wip/otte/correct-fps' into 'main'
Fix fps display

See merge request GNOME/gtk!7003
2024-03-10 17:31:46 +00:00
Balázs Úr
8790c83a76 Update Hungarian translation 2024-03-10 15:56:09 +00:00
Brage Fuglseth
6b202fb838 Update Norwegian Bokmål translation 2024-03-10 13:15:47 +00:00
Fran Dieguez
f69476435f Update Galician translation 2024-03-10 10:34:28 +00:00
Benjamin Otte
8df6e2cdaf frameclock: Make timings history dynamic
Keep at least 1 second of frame timings.

This is necessary for 2 reasons - a real one and a fun one.

First, with the difference in monitor refresh rates, we can have 48Hz
latops as well as 240Hz high refresh rate monitors. That's a factor of
4, and tracking frame rates in both situations reliably is kind of hard
- either we track over too many frames and the fps take a lot of time to
adjust, or we track too little time and the fps fluctuate wildly.

Second, when benchmarking with GDK_DEBUG=no-vsync with a somewhat fast
renderer (*cough*Vulkan*cough*) frame rates can go into insane dimensions
and only very few frames are actually getting presentation times
reported. So to report accurate frame rates in those cases, we need a
*very* large history that can be 1000s of times larger than the usual
history. And that's just a waste for normal usage.
2024-03-10 10:27:36 +01:00
Benjamin Otte
2861ab38ac frameclock: Report accurate fps instead of too low
Previously, our reported fps numbers could be too low when the start
timings weren't complete. In that case we would use the frame time, but
the frame time is the time when the frame was rendered, which is quite a
few milliseconds before it is presented.

So in that case we would not report the difference in presentation
times, but the difference from start of rendering. However, those times
are way more variable and can smear over the whole frame because they
depend on when we received the frame callbacks to high priority GSources
as well as our own render time predictions.

This happened in particular with GDK_DEBUG=no-vsync and could report
number that are off by a factor of 2.

Now we skip any incomplete frames, because those frames never have
presentation times reported. This makes it theoretically more likely to
not being able to report fps at all, but I'd rather have no fps than fps
off by a factor of 2.
2024-03-10 10:27:36 +01:00
Benjamin Otte
23c2122c13 inspector: Handle more digits in fps overlay
The fps used to get garbled when hitting >=10,000fps. That's quite
unlikely to happen for long periods, but it can happen for short bursts
(like after alt-tabbing).

So just handle more digits to make the display survive those corner cases.
2024-03-10 10:27:36 +01:00
Benjamin Otte
5b83ffa4a0 inspector: Make background width match fps number
Previously, we drew the same width no matter how many digits the fps
number had, which left a lot of empty space.

But we can use some quite simple math to avoid that by just shrinking
the background by the width of the non-rendered glyphs.
2024-03-10 10:27:35 +01:00
Matthias Clasen
cf8e3157a7 Merge branch 'matthiasc/for-main' into 'main'
Add another path fill test

Closes #4553 and #5423

See merge request GNOME/gtk!7001
2024-03-09 18:21:19 +00:00
Matthias Clasen
7323172755 ci: Add xfails for gl rotation+opacity problems
These are the topic of #6525. Lets xfail them for now.
2024-03-09 13:02:56 -05:00
Matthias Clasen
cfee8f4b11 tests: Cosmetics 2024-03-09 12:43:33 -05:00
Matthias Clasen
7ae099c94c inspector: Tweak the size groups page
Make the page scroll, and modernize it slightly. Also, fix a
case of missing top margin.

Fixes: #4553
2024-03-09 12:43:33 -05:00
Matthias Clasen
42298d8ab1 inspector: Deal with long action names
Make the action list scroll horizontally, and make the name
column resizable.

Fixes: #5423
2024-03-09 12:43:33 -05:00
Matthias Clasen
68912698f1 inspector: Drop the Window Scale spin
We don't really expect backends to make this settable, and
fractional scaling makes this more complicated anyway. The
scale values can be seen on the General tab, for the monitor,
and on the surface for each toplevel.
2024-03-09 12:43:33 -05:00
Matthias Clasen
c8c56f8d42 inspector: Use GtkFontDialogButton
A small step towards respecting our own deprecations. While we
are at it, make the control only select the font family, since
that is the intention of the font setting. Font style and size
are under the control of the css, and we have a font scale slider
right below to influence font size globally.
2024-03-09 12:43:33 -05:00
Matthias Clasen
7f48b5a05c inspector: Show the linux dmabuf Wayland protocol
This was overlooked when dmabuf support was added.
2024-03-09 12:43:33 -05:00
Matthias Clasen
1e5e977b37 gsk: Minor reshuffling
Hide the temporary unhinted font object behind the private API.
There might be a way to implement this without instantiating a
font, at some point.
2024-03-09 12:43:33 -05:00
Matthias Clasen
62d44b6bc7 wayland: Add window sizes to debug spew
This may help for tracking down issues.
2024-03-09 12:43:33 -05:00
Matthias Clasen
862afeffe0 Add another path fill test
This uses the other fill rule.
2024-03-09 07:03:55 -05:00
Matthias Clasen
92f9195015 Merge branch 'matthiasc/for-main' into 'main'
Update the docs for gtk-xft-rgba

See merge request GNOME/gtk!7000
2024-03-09 04:50:09 +00:00
Matthias Clasen
fc6e08082b tests: Make compare-render less repetitive
Only run the unmodified comparison if --plain is passed
on the commandline.
2024-03-08 22:27:14 -05:00
Matthias Clasen
af7516b797 Update the docs for gtk-xft-rgba
Clarify that this setting has no effect.
2024-03-08 21:37:10 -05:00
Matthias Clasen
3f1821e372 Merge branch 'matthiasc/for-main' into 'main'
gsk: Make uber shader handle fonts the same

See merge request GNOME/gtk!6995
2024-03-09 02:19:25 +00:00
Matthias Clasen
b569470b87 Stop setting rgb antialiasing in font options
We don't support subpixel antialiasing, so setting font options
to that effect won't do any good.
2024-03-08 20:44:42 -05:00
Matthias Clasen
f1a3235039 Add tests for uber rendering
Add a --colorflip option to the compare-render test. This applies
a color matrix to the node, which has the intended side-effect of
convincing the Vulkan renderer to use its uber shader, so we get
test results comparing the uber output to its non-uber siblings.
2024-03-08 20:44:42 -05:00
Matthias Clasen
34e90005af Don't forget to unrealize the renderer
This causes a critical warning.
2024-03-08 20:44:42 -05:00
Matthias Clasen
4f1cc8ec6d gsk: Make uber shader handle fonts the same
The code converting text nodes for the uber shader was missing
some of the recent font handling improvements. Make things match.

Related: #6514
2024-03-08 20:44:42 -05:00
Matthias Clasen
5242205a65 gsk: Ignore transforms for font handling
We were turning off hinting and subpixel positioning if the
transform isn't 2D affine. The idea behind this was that transforms
likely indicate animations, and for animations, this may reduce
jitter. But the heuristic of transform==animation is not very
reliable, and we pay for this with a jump from hinted to unhinted
at the beginning and end of it. Also, the heuristic does not even
work for the most relevant 'animation' we have today: scrolling.

So, lets drop this for now. We can revisit it later.
2024-03-08 20:44:42 -05:00
Matthias Clasen
59633a6781 Add an xfail
This is causing sporadic ci failures, so file an issue and xfail it.
2024-03-08 20:44:42 -05:00
Matthias Clasen
d82316edda Merge branch 'cache-get-hinted-font' into 'main'
gsk: cache sequentially requested hinted fonts

See merge request GNOME/gtk!6999
2024-03-09 01:10:18 +00:00
Matthias Clasen
0815640b22 Merge branch 'mark-for-dropped-frames' into 'main'
gdk/frameclock: add mark when we discover frames may drop

See merge request GNOME/gtk!6998
2024-03-09 01:03:13 +00:00
Matthias Clasen
26de2eae20 Merge branch 'ngl-buffer-upload-counter' into 'main'
add counter for ngl buffer uploads

See merge request GNOME/gtk!6997
2024-03-08 23:50:03 +00:00
Matthias Clasen
8fa358c4d4 Merge branch 'avoid-extraneous-uploads' into 'main'
gsk/gpu: avoid unnecessary buffer uploads

See merge request GNOME/gtk!6996
2024-03-08 23:48:52 +00:00
Christian Hergert
fc72449228 gsk: cache sequentially requested hinted fonts
When getting the hinted version of fonts, they often come in sequentially.
This helps reduce overhead in many sequential gtk_text_node_new() on with
fractional scaling as you see from GtkSourceView.
2024-03-08 15:40:26 -08:00
Christian Hergert
84a304e66e gdk/frameclock: add mark when we discover frames may drop
If we discover that some number of frames have passed that perhaps should
not have, leave a mark for the profiler.
2024-03-08 14:41:59 -08:00
Christian Hergert
ecf1b7c18a gsk/gpu: add counter for ngl buffer uploads
It's helpful to know how much we're uploading from Sysprof captures.
2024-03-08 14:17:31 -08:00
Christian Hergert
a7c5b53f46 gsk/gpu: avoid unnecessary buffer uploads
Some maps are used for read only and do not require uploading contents
back to the GPU afterwards. In other cases, we can often upload less than
the fully allocated buffer size.
2024-03-08 13:55:57 -08:00
Rūdolfs Mazurs
09736dde93 Update Latvian translation 2024-03-08 21:02:45 +00:00
Matthias Clasen
66c00dc9f3 Merge branch 'docs-iconcache' into 'main'
docs/iconcache.txt: fix ICON_FLAGS

Closes #6489

See merge request GNOME/gtk!6993
2024-03-08 16:20:55 +00:00
Kirill Primak
3eacf8bd39 docs/iconcache.txt: fix ICON_FLAGS
The documented icon flags didn't match the actual constants used by GTK when
reading and updating icon theme cache files. Fix the values of flags in the
documentation.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/6489
2024-03-08 18:42:11 +03:00
Matthias Clasen
34e9ef9e78 Merge branch 'fix-foreign-check' into 'main'
Fix xdg-foreign check

See merge request GNOME/gtk!6994
2024-03-08 14:20:50 +00:00
Ivan Molodetskikh
a5955106ea Fix xdg-foreign check
It was checking for xdg-foreign v1 instead of "v1 or v2".
2024-03-08 17:28:35 +04:00
Andika Triwidada
ea0cfed735 Update Indonesian translation 2024-03-07 08:44:46 +00:00
Matthias Clasen
f312d1ee6a Merge branch 'gtk-at-spi-context-typo' into 'main'
Fix documentation typo

See merge request GNOME/gtk!6991
2024-03-07 04:30:53 +00:00
Robert Ancell
69b6f4cf4f Fix documentation typo 2024-03-07 15:17:33 +13:00
Matthias Clasen
d7e1c377fe Merge branch 'matthiasc/for-main' into 'main'
ci: Update xfails

See merge request GNOME/gtk!6990
2024-03-07 01:56:05 +00:00
Matthias Clasen
cc17577763 Merge branch 'fix-emoji-pres' into 'main'
emoji: Fix presentation selector handling

See merge request GNOME/gtk!6986
2024-03-07 00:23:41 +00:00
Matthias Clasen
ef4ae61c66 ci: Update xfails
A number of the xfails that were added for the new renderers have
been fixed.
2024-03-06 19:03:43 -05:00
Matthias Clasen
e04ea3f311 Merge branch 'fix-mis-scaled-text' into 'main'
gsk: Fix mis-scaled text rendering

Closes #6504

See merge request GNOME/gtk!6977
2024-03-06 23:22:42 +00:00
Matthias Clasen
77a2cd4d8d gsk: Fix mis-scaled text rendering
This was happening when rotated text was partially redrawn.

A test that failed before this change is included.

Fixes: #6504
2024-03-06 17:52:35 -05:00
Matthias Clasen
0986981d1a gpu: Empty clip is still empty after transform
When transforming an empty clip, it stays empty.

Previously, we were setting it to CONTAINED, but that's wrong, because
the bounds are not contained in the clip, the clip is contained in the bounds.

This reverts part of commit a51c6aed47.

Related: !6692
2024-03-06 17:52:22 -05:00
Benjamin Otte
913f850f83 Merge branch 'wip/otte/for-main' into 'main'
Update "snapshot: linear-gradients cannot be affine-transformed"

See merge request GNOME/gtk!6989
2024-03-06 22:44:48 +00:00
Benjamin Otte
ed31da3730 Update "snapshot: linear-gradients cannot be affine-transformed"
This is a better fix for commit 7ed6c39862.

The linear-gradient-nonorthogonal-linear-gradient test tests this.

Related: !6692
2024-03-06 22:35:30 +01:00
Benjamin Otte
428ff6c4ab Merge branch 'wip/otte/for-main' into 'main'
snapshot: Fix wrong nodes with transformed shadows

See merge request GNOME/gtk!6988
2024-03-06 21:06:49 +00:00
Benjamin Otte
53786841cc snapshot: Fix wrong nodes with transformed shadows
Test included.

The test is disabled for Cairo because the Cairo blurring code can't
deal with scaling, which makes things come out wrong for the test that
checks that we do the right thing with the blur radius when scaling.

Related: !6977
2024-03-06 21:52:16 +01:00
Vincent Chatelain
8f8ece44a8 Update French translation 2024-03-06 19:00:59 +00:00
Anders Jonsson
41a892b958 Update Swedish translation 2024-03-06 17:50:54 +00:00
Baurzhan Muftakhidinov
b494ed5876 Update Kazakh translation 2024-03-06 03:10:20 +00:00
Josh Brobst
7b589f991d emoji: Fix presentation selector handling
The emoji presentation selector (FE0F) was being appended to every emoji
sequence inserted by GtkEmojiChooser and GtkEmojiCompletion, often
leading to invalid sequences. Modify the emoji data to include FE0F
only when necessary, and change skin tone handling to account for cases
where the generic (no tone) variation needs a presentation selector.
2024-03-05 18:44:55 -05:00
Christian Hergert
d83faf82d7 Merge branch 'macos-move-maximized' into 'main'
macos: Fix moving maximized windows

Closes #6436

See merge request GNOME/gtk!6914
2024-03-05 21:53:26 +00:00
Matthias Clasen
cd46016238 Merge branch 'preserve-font-dpi' into 'main'
gsk: Preserve dpi when modifying fonts

Closes #6508

See merge request GNOME/gtk!6985
2024-03-05 21:43:00 +00:00
Matthias Clasen
f2a3218455 Merge branch 'wip/chergert/fix-textviewchild-double-draw' into 'main'
textview: only snapshot GtkTextViewChild once

See merge request GNOME/gtk!6984
2024-03-05 21:37:37 +00:00
Matthias Clasen
85b1959714 Merge branch 'wip/fl/macos-cursor-from-texture' into 'main'
gdk: Implement cursor from texture on MacOS

See merge request GNOME/gtk!6981
2024-03-05 21:34:30 +00:00
Matthias Clasen
b23600ae4b gsk: Preserve dpi when modifying fonts
When scaling a font or changing font options, we need to be
careful to preserve the dpi as well, otherwise the rendering
might leak out of the node bounds, leading to spectacular
glitches.

Fixes: #6508
2024-03-05 16:22:26 -05:00
Christian Hergert
bdc43b8fca textview: only snapshot GtkTextViewChild once
This was causing double snapshotting of textview children because the
parent snapshot will also iterate and snapshot children.
2024-03-05 11:41:11 -08:00
Matthias Clasen
da2ef6911f Merge branch 'ebassi/accessible-text-util' into 'main'
Rename GtkAccessibleText private header

See merge request GNOME/gtk!6982
2024-03-05 13:23:11 +00:00
Emmanuele Bassi
0626246367 a11y: Add utilify method for text attributes
Simplify the AT-SPI implementation by having a convenience function to
extract the text attributes of a GtkAccessibleText, with or without the
default attributes.
2024-03-05 12:23:17 +00:00
Matthias Clasen
0edfafdfdf Merge branch 'macos-maximized-window' into 'main'
macos: Fix window state of initially maximized windows

Closes #5898

See merge request GNOME/gtk!6882
2024-03-05 11:35:49 +00:00
Bruce Cowan
1863b79fb3 Update British English translation 2024-03-05 11:35:24 +00:00
Emmanuele Bassi
9aa90f8df0 Rename GtkAccessibleText private header
Follow the existing naming convention, and drop the hyphen.
2024-03-05 11:00:20 +00:00
Fabio Lagalla
8080d9e7c1 gdk: Implement cursor from texture on MacOS
This is done with a NSCursor whose content is an NSImage. Image pixels are filled by a NSBitmap, and the format is premultiplied RGBA. So we can just use the texture downloader with GDK_MEMORY_R8G8B8A8_PREMULTIPLIED format.
2024-03-05 10:26:27 +01:00
Matej Urbančič
f432ee775f Update Slovenian translation 2024-03-04 21:51:10 +00:00
Matthias Clasen
77f9cb11a9 Merge branch 'wip/chergert/for-main' into 'main'
gsk/gpu: add profiler node for shader loading

See merge request GNOME/gtk!6978
2024-03-04 21:36:37 +00:00
Asier Sarasua Garmendia
d92e3cb864 Update Basque translation 2024-03-04 19:58:53 +00:00
Matthias Clasen
733fa156b9 Merge branch 'ebassi/accessible-text-default-attrs' into 'main'
a11y: Add GtkAccessibleText.get_default_attributes

See merge request GNOME/gtk!6973
2024-03-04 19:54:33 +00:00
Christian Hergert
d181d53762 gsk/gpu: add profiler node for shader loading
This is helpful when tracking down why a frameclock cycle took so long. In
quick recordings it seems to often correlate with a shader compile.
2024-03-04 11:54:13 -08:00
Emmanuele Bassi
644e6f8ebe Consolidate TextView/TextBuffer attribute serialization
Use dictionaries of string pairs instead of abusing GVariant; we can
convert the dictionary into a GVariant when we send the data over the
wire.
2024-03-04 19:13:29 +00:00
Matthias Clasen
0b4c695d65 Merge branch 'hinting-proper-positioning' into 'main'
gsk: Handle hinted fonts better

Closes #6502

See merge request GNOME/gtk!6966
2024-03-03 23:27:00 +00:00
Matthias Clasen
448287bd58 Merge branch 'camelCaseNick/a11y-text-contents-at' into 'main'
a11y: implement get_contents_at for Gtk.Text, Gtk.TextView, Gtk.Inscription

See merge request GNOME/gtk!6971
2024-03-03 23:03:13 +00:00
Benjamin Otte
5e6aff69c6 Merge branch 'wip/otte/for-main' into 'main'
demos: shadertoy only handles GL

See merge request GNOME/gtk!6976
2024-03-03 22:38:22 +00:00
Benjamin Otte
d88e616711 demos: shadertoy only handles GL
If somebody wants to add GLES support, go for it.

For now we enforce GL.
2024-03-03 22:20:44 +00:00
Aurimas Černius
0e5c94a094 Update Lithuanian translation 2024-03-03 20:47:02 +00:00
Brage Fuglseth
bb0aeec99c Update Norwegian Bokmål translation 2024-03-03 20:08:02 +00:00
Matthias Clasen
880e3ef289 Add tests for glyph positioning
These tests check that we round glyph positions to integral device
pixel coordinates when hinting is enabled, and to device subpixel
positions if it isn't.
2024-03-03 14:28:19 -05:00
Sabri Ünal
94a09263d7 Update Turkish translation 2024-03-03 18:22:30 +00:00
Markus Göllnitz
ab9106ac89 testsuite: test for implementation of accessible_text_get_contents_at
Signed-off-by: Markus Göllnitz <camelcasenick@bewares.it>
2024-03-03 19:13:40 +01:00
Markus Göllnitz
ff6451a77e a11y: implement get_contents_at for Gtk.TextView
Signed-off-by: Markus Göllnitz <camelcasenick@bewares.it>
2024-03-03 19:13:40 +01:00
Matthias Clasen
4f2d63b8ac gsk: Handle hinted fonts better
Enforce the following rules:
- No hinting or subpixel positioning in transformed context
- glyph-align determines if we use integral or fractional
  device pixel positions
- For hinting, always use an integral y position (the hinter
  assumes integral positions, and only operates vertically).
2024-03-03 13:08:29 -05:00
Matthias Clasen
81c97f0910 gsk: Add a private helper
Add a function to get the hint style of a font.
2024-03-03 13:08:29 -05:00
Matthias Clasen
d1b52cc292 gsk: Preserve the antialiasing setting of the font
When we get an unhinted font for text node extents, don't change
the antialiasing setting. It doesn't affect the extents we get
here, but if we later need an unhinted font for rendering, the
one we create this way will be the right one, so it will already
exist.
2024-03-03 13:08:29 -05:00
Matthias Clasen
ddedb39329 gsk: Tweak gsk_get_hinted_font slightly
Make it possible to preserve some of the fonts original options.
2024-03-03 13:08:29 -05:00
Matthias Clasen
d45987e637 Merge branch 'fallback-to-gl+llvmpipe' into 'main'
Don't fall back to cairo for software rendering

See merge request GNOME/gtk!6975
2024-03-03 17:54:07 +00:00
Matthias Clasen
b95eceea60 Don't fall back to cairo for software rendering
The experience with gl+llvmpipe is not great, in particular on
fractional scales. But it is less broken than cairo in that
situation.
2024-03-03 12:28:20 -05:00
Emmanuele Bassi
2774e80fc4 a11y: Ensure that attributes are unique before sending them
The default attributes are overridden by the run attributes.
2024-03-03 17:08:39 +00:00
Matthias Clasen
7c207c4868 Merge branch 'matthiasc/for-main' into 'main'
Improve subpixel positioning tests

See merge request GNOME/gtk!6974
2024-03-03 16:33:46 +00:00
Matthias Clasen
c6c8abcf21 Improve subpixel positioning tests
We want to test subpixel positioning, so turn off hinting, since
hinting and subpixel positioning are opposing forces.

This does not currently change test outcomes, but it will prevent
the tests from breaking in the future when we make changes to
improve hinting.
2024-03-03 11:19:04 -05:00
Emmanuele Bassi
a59c967675 a11y: Implement AtspiText.GetDefaultAttributes
The new GtkAccessibleText.get_default_attributes() vfunc gives us the
ability to implement this AT-SPI method.
2024-03-03 15:17:53 +00:00
Emmanuele Bassi
c3329f5fcc a11y: Implement AtspiText.GetAttributeRun for AccessibleText
GetAttributeRun works like GetAttributes, but it allows including the
default text attributes.

See: !6971, GNOME/orca#477
2024-03-03 15:17:53 +00:00
Emmanuele Bassi
4f06e46759 a11y: Implement get_default_attributes for TextView 2024-03-03 15:17:53 +00:00
Emmanuele Bassi
7e522a8c55 a11y: Implement get_default_attributes for Text 2024-03-03 15:17:52 +00:00
Emmanuele Bassi
d9447fd2e7 a11y: Implement get_default_attributes for Label 2024-03-03 15:17:52 +00:00
Emmanuele Bassi
95214f3697 a11y: Implement get_default_attributes for Inscription 2024-03-03 15:17:52 +00:00
Emmanuele Bassi
fe64c998f8 a11y: Add GtkAccessibleText.get_default_attributes
Accessible text attributes come in two flavours:

- the run attributes, which apply to a text from a given offset
- the default attributes, which apply to the whole text

The default attributes are used to gather the initial values for every
text attribute, while the run attributes operate additively.

We currently have a getter for the former, but we lack one for the
latter.
2024-03-03 15:17:52 +00:00
Markus Göllnitz
84582ad762 a11y: implement get_contents_at for Gtk.Inscription
Signed-off-by: Markus Göllnitz <camelcasenick@bewares.it>
2024-03-03 15:52:26 +01:00
Matthias Clasen
fcc7a58058 Merge branch 'gst-cmp-float' into 'main'
gstreamer: Use G_APPROX_VALUE to compare floats

See merge request GNOME/gtk!6972
2024-03-03 14:16:47 +00:00
Matthias Clasen
8a48becb7e Cosmetics 2024-03-03 08:56:32 -05:00
Robert Mader
465446430e gstreamer: Use G_APPROX_VALUE to compare floats
Mainly to silence compiler warnings.
2024-03-03 14:35:27 +01:00
Luming Zh
4060c43ae7 Update Chinese (China) translation 2024-03-03 11:17:20 +00:00
Markus Göllnitz
4ec9a2a330 a11y: implement get_contents_at for Gtk.Text
There are users of GetStringAtOffset, such as Orca.

Signed-off-by: Markus Göllnitz <camelcasenick@bewares.it>
2024-03-03 04:37:01 +01:00
Matthias Clasen
90c017a762 Merge branch 'matthiasc/for-main' into 'main'
Grr, vulkan

See merge request GNOME/gtk!6970
2024-03-03 03:03:19 +00:00
Matthias Clasen
e011434223 Update tests for version number bump 2024-03-02 22:02:36 -05:00
Matthias Clasen
b1ccb4103d Grr, vulkan
The can always make it worse with another define.
2024-03-02 21:47:49 -05:00
Matthias Clasen
8033809f8b Merge branch 'matthiasc/for-main' into 'main'
vulkan: Add another error code

See merge request GNOME/gtk!6969
2024-03-03 01:26:44 +00:00
Matthias Clasen
66ba1f76ba vulkan: Add another error code
Handle VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR.
2024-03-02 20:20:16 -05:00
Matthias Clasen
0ca822c716 Merge branch 'matthiasc/for-main' into 'main'
4.13.9

See merge request GNOME/gtk!6968
2024-03-03 00:57:14 +00:00
Matthias Clasen
4ac288c1b4 Post-release version build 2024-03-02 19:56:09 -05:00
Matthias Clasen
64316ab185 4.13.9 2024-03-02 19:30:26 -05:00
Matthias Clasen
4d90a693ae Merge branch 'scaled-font' into 'main'
gsk: Use a scaled font for glyph rendering

See merge request GNOME/gtk!6936
2024-03-03 00:23:43 +00:00
Matthias Clasen
0c5f943783 Merge branch 'matthiasc/for-main' into 'main'
NEWS: Updates

See merge request GNOME/gtk!6967
2024-03-02 23:54:29 +00:00
Matthias Clasen
42fc165b94 Add glyph hinting tests
Add tests that demonstrate different rendering with and without
hinting, to prove that hinting has an effect.
2024-03-02 18:41:06 -05:00
Matthias Clasen
20a4e3f351 Add glyph antialiasing test
This test checks that the antialias font option has the indended
effect.
2024-03-02 18:41:02 -05:00
Matthias Clasen
f3f90e1d71 Add a glyph scaling test
The glyph in this test has extents that will be made smaller
by hinting, which poses some challenge for our renderers.

The scaled glyph rendering is too big for the 'small texture'
text setup, so we allow the test to fail there.
2024-03-02 18:39:14 -05:00
Matthias Clasen
b018da2acd gsk: Accept font options in node files
The goal is to fix all the context that influences the rendering
of text nodes in the node file. This will help with better font
testing.

The newly accepted properties are

hint-style: none/slight/full
antialias: none/gray

We are omitting font options and values that aren't supported
in GSK or have no influence on the rendering.

Note that these settings will get incorporated in the PangoFont
that gets set on the resulting text node.

Parser tests included.
2024-03-02 18:39:14 -05:00
Matthias Clasen
ab5f3f59ce gsk: Use unhinted extents for text nodes
We need precise bounds. And while hinting might shift the rendering
around from these bounds by a fraction of a pixel, we account for
this in the places where it matters: when determining diff regions,
when sizing offscreens, and when determining the size of atlas
regions for glyphs.
2024-03-02 18:39:14 -05:00
Matthias Clasen
0127217e10 gsk: Add a way to get a (un)hinted font
Add a function to change the cairo font options of a font to
to the given values while keeping everything else the same.

We use pango api for this if available.

Note that this is not a fully general api, but tailored to the
needs of GSK. We don't allow setting hint-metrics (because it
only influences layout, not rendering) or subpixel-mode (since
we don't have component alpha available).
2024-03-02 18:39:14 -05:00
Matthias Clasen
16a476fe22 gsk: Stop passing scale to glyph upload op
It is always 1.0 now, so there is no point. Instead of the scale,
print the font when doing verbose logging.
2024-03-02 18:39:14 -05:00
Matthias Clasen
c8ca6930c5 gsk: Use a scaled font for glyph rendering
This changes the approach we take to rendering glyphs in the
presence of a scale transform: Instead of scaling the extents
and rendering to an image surface with device scale, simply
create a scaled font and use it for extents and rendering.

This avoids clipping problems with scaling of extents in
the presence of hinting.
2024-03-02 18:39:14 -05:00
Matthias Clasen
c4f33f36de gsk: Add a way to get a scaled font
Add a function to change the size of a font while keeping everything
else the same. We use pango api for this if available.
2024-03-02 18:39:14 -05:00
Matthias Clasen
0543c48862 NEWS: Updates 2024-03-02 18:27:33 -05:00
Yaron Shahrabani
fcb17a86e6 Update Hebrew translation 2024-03-02 22:15:37 +00:00
Yuri Chornoivan
5633b5b637 Update Ukrainian translation 2024-03-02 20:40:15 +00:00
Artur S0
f7eaf69d67 Update Russian translation 2024-03-02 19:55:29 +00:00
Piotr Drąg
32411943ea Update Polish translation 2024-03-02 17:08:11 +01:00
Jiri Grönroos
58fa5d7617 Update Finnish translation 2024-03-02 16:03:12 +00:00
Ekaterine Papava
f9ee1967f4 Update Georgian translation 2024-03-02 15:53:04 +00:00
Danial Behzadi
6a376f0a30 Update Persian translation 2024-03-02 15:32:03 +00:00
Piotr Drąg
66826c26db Update POTFILES.in 2024-03-02 16:19:28 +01:00
Matthias Clasen
8d1e37789e Merge branch 'broken-hexboxes' into 'main'
gsk: problems with hex boxes

See merge request GNOME/gtk!6963
2024-03-02 00:04:29 +00:00
Matthias Clasen
6c39a5946e Merge branch 'wip/chergert/for-main' into 'main'
gdk/gdkglcontext: include duration of eglSwapBuffers

See merge request GNOME/gtk!6964
2024-03-02 00:03:58 +00:00
Christian Hergert
2a98928286 gdk/gdkglcontext: include duration of eglSwapBuffers 2024-03-02 00:03:57 +00:00
Matthias Clasen
c7806eb908 gsk: Fix handling of hex boxes
The pango code that is drawing hex boxes, invisible glyphs, etc,
is depending on the width being set in the PangoGlyphInfo. Once
we set that, everything falls into place.

Testcase included.
2024-03-01 16:51:58 -05:00
Matthias Clasen
9015734e65 Merge branch 'matthiasc/for-main' into 'main'
gsk: Make glyph parsing more flexible

See merge request GNOME/gtk!6962
2024-03-01 17:49:46 +00:00
Matthias Clasen
f5159e1ecb gsk: Make glyph parsing more flexible
It is a bit annoying that one has to specify the glyph width
when specifying glyphs numerically for a text node, since this
information really is part of the font.

Make the parser more flexible, and allow to specify just the glyph
ids, without an explicit width. In this case, the width will be
determined from the font.

With this, glyphs can now be specified in any of the follwing
ways:

glyphs: "ABC";              (ASCII)
glyphs: 23, 45, 1001;       (Glyph IDs)
glyphs: 23 10, 100 11.1;    (Glyph IDs and advance widths)
glyphs: 23 10 1 2 color;    (with offsets and flags)

Tests have been updated to cover these variants.
2024-03-01 11:22:28 -05:00
Matthias Clasen
aec2f50d82 testsuite: Add a forgotten test 2024-03-01 09:23:41 -05:00
Matthias Clasen
74860f7602 Merge branch 'debug-flags-ubsan' into 'main'
gdkdisplay: Don’t call _get_instance_private(NULL)

See merge request GNOME/gtk!6961
2024-03-01 13:10:30 +00:00
Philip Withnall
a9175e0c03 gdkdisplay: Don’t call _get_instance_private(NULL)
While it’s documented as being safe, it triggers warnings from ubsan.
While we work out the best way to deal with that inside the
implementation of `G_ADD_PRIVATE` in GLib, let’s pragmatically just
short-circuit the code which triggers the warning here. This is helpful
because `gdk_display_get_debug_flags()` is called from a number of
locations within GTK, so is likely to be hit if anyone is running a UI
app under ubsan.

See https://gitlab.gnome.org/GNOME/glib/-/issues/3267#note_2033550

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: https://gitlab.gnome.org/GNOME/glib/-/issues/3267
2024-03-01 12:16:31 +00:00
Matthias Clasen
e1c56555af Merge branch 'camelCaseNick/editable-accessible-crash' into 'main'
a11y: support multiple levels of editable delegations in AT-SPI text

See merge request GNOME/gtk!6960
2024-03-01 04:12:23 +00:00
Matthias Clasen
24120c8fd0 Merge branch 'matthiasc/for-main' into 'main'
testsuite: Plug some leaks

See merge request GNOME/gtk!6959
2024-03-01 03:56:06 +00:00
Markus Göllnitz
f284331f79 a11y: support multiple levels of editable delegations in AT-SPI text
Gtk.Editable.get_delegate is allowed to return another
delegating Gtk.Editable. However, the AT-SPI text
implementationn for Gtk.Editables does not handle
delegate chaining.

In the wild, you will find a Gtk.Text as the delegate of
a Gtk.SpinButton, that is in turn the delegate of an
Adw.SpinRow in libadwaita.

Note: This does not handle the more dangerous possibility
of a delegate loop when built with G_DISABLE_ASSERT,
otherwise stops after the arbitrarily chosen number of
six steps of delegation.

Signed-off-by: Markus Göllnitz <camelcasenick@bewares.it>
2024-03-01 04:14:58 +01:00
Matthias Clasen
a82de96e1a Add a testsuite for nodeparser tests
This helps when changing the node parser.
2024-02-29 21:59:04 -05:00
Matthias Clasen
eba9b116ed Merge branch 'camelCaseNick/text-accessible-segv' into 'main'
a11y: handle no selection ranges for AT-SPI text

Closes #6488

See merge request GNOME/gtk!6958
2024-02-29 03:52:10 +00:00
Markus Göllnitz
1f89b3c7df a11y: handle no selection ranges for AT-SPI text 2024-02-29 03:52:10 +00:00
Matthias Clasen
c739b9fe7f Merge branch 'wip/kabus/misc-leaks2' into 'main'
general: Fix leaks

See merge request GNOME/gtk!6951
2024-02-28 12:35:02 +00:00
Matthias Clasen
556b729b97 Merge branch 'matthiasc/for-main' into 'main'
gsk: Serialize fonts with absolute size

See merge request GNOME/gtk!6953
2024-02-28 12:08:59 +00:00
Matthias Clasen
9fd5558acd Update nodeparser tests
The node serialization code now prints fonts with pixel sizes.
Update affected tests.
2024-02-27 23:46:33 -05:00
Matthias Clasen
b7422c0f62 nodeparser: Change default font
Use Cantarell 15px instead of Cantarell 11, ot make roundtrip
tests easier to read.
2024-02-27 23:45:46 -05:00
Emmanuele Bassi
ace684c7ab Merge branch 'wip/chergert/for-main' into 'main'
a11y/atspi: make TextCaretMoved match GTK 3 / ATK

See merge request GNOME/gtk!6956
2024-02-28 01:15:53 +00:00
Christian Hergert
752e704e99 accessibletext: handle NULL gracefully from get_contents_at()
This fixes a g_critical() internally with GtkTextView when running orca.
2024-02-27 16:40:48 -08:00
Christian Hergert
8c7e13746b a11y/atspi: make TextCaretMoved match GTK 3 / ATK
When testing VTE on GTK 3 using ATK, the variant parameter is <0> instead
of <''> on the wire. Make that match to increase the chances that tooling
will hit the same expectations.
2024-02-27 16:35:29 -08:00
Matthias Clasen
c2311c7154 gsk: Serialize fonts with absolute size
This is more often what we want. Our testcases tend to have
pixel sizes, and we want to preserve then when resaving the
test files.
2024-02-27 14:10:10 -05:00
Khalid Abu Shawarib
44fa748826 general: Fix leaks 2024-02-27 22:01:41 +03:00
Matthias Clasen
dfed398371 Merge branch 'gtk4-edge-tiling-resize-fix' into 'main'
[gtk4/wayland] Infer edge constraints from tiled edges.

See merge request GNOME/gtk!6745
2024-02-27 17:39:04 +00:00
Matthias Clasen
962ba49a8e Merge branch 'wip/chergert/for-main' into 'main'
textview: always set n_ranges out parameter

See merge request GNOME/gtk!6950
2024-02-27 02:19:40 +00:00
Christian Hergert
5811e443f8 textview: always set n_ranges out parameter 2024-02-26 17:49:03 -08:00
Aurimas Černius
f55e1392d4 Update Lithuanian translation 2024-02-26 20:56:00 +00:00
Daniel Mustieles
0fbe5ba40c Update Spanish translation 2024-02-26 15:25:40 +00:00
Matthias Clasen
980ea63d78 Merge branch 'video-cursor-timeout' into 'main'
video: Install the hide cursor timeout later

Closes #6264

See merge request GNOME/gtk!6948
2024-02-26 14:45:02 +00:00
Simon McVittie
85cf995af7 testsuite: Force Mesa to use software GL when asserting about stderr
In an autobuilder environment, there will typically be no hardware GPU
available, so Mesa will fall back from hardware to Zink to software
rendering. Unfortunately, Zink logs to stderr during loading if no
hardware GPUs are available. This particular test asserts that stderr
has desired contents, which means Zink's extra output causes the test
to fail. We can bypass this by disabling use of Zink.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6478
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-02-26 13:23:11 +00:00
Matthias Clasen
dcc3533363 video: Install the hide cursor timeout later
We were installing the timeout in root, but removing it in unmap,
which could lead to trouble if we ever dispose a GtkVideo widget
without mapping it.

Fixes: #6264
2024-02-26 08:17:27 -05:00
Matthias Clasen
28964aa0a4 Merge branch 'search-entry-input-hints-property-since-marker' into 'main'
Add missing `Since` marker to `GtkSearchEntry:input-hints`

See merge request GNOME/gtk!6947
2024-02-26 12:26:33 +00:00
Matthias Clasen
7fd8a0ac99 Merge branch 'michaelweghorn/fix_at_spi_socket_doc' into 'main'
a11y: Fix gtk_at_spi_socket_new doc

See merge request GNOME/gtk!6946
2024-02-26 12:21:34 +00:00
Sebastian Dröge
d919ed4e4b Add missing Since marker to GtkSearchEntry:input-hints 2024-02-26 11:09:50 +02:00
Matej Urbančič
61ec6fb5eb Update Slovenian translation 2024-02-26 09:00:38 +00:00
Michael Weghorn
237eb8bb90 a11y: Fix gtk_at_spi_socket_new doc 2024-02-26 07:52:19 +01:00
Matthias Clasen
ff57cd9331 Merge branch 'gtk-jan2024_docs_tweaks' into 'main'
docs: Clarify child objects in GtkBuilder

See merge request GNOME/gtk!6945
2024-02-26 03:05:22 +00:00
Matthias Clasen
c97d02f487 docs: Mention child properties in builder docs
Clarify that there is no need for <child> if we have a property.
2024-02-25 21:46:11 -05:00
Matthias Clasen
36ced69ebf Merge branch 'matthiasc/for-main' into 'main'
Make one of the tests more robust

See merge request GNOME/gtk!6944
2024-02-26 01:36:15 +00:00
Matthias Clasen
427a52a9ad Make one of the tests more robust
The text-mixed-color-nocairo test was using a 20pt font, which
results in 16.6 pixels, which is prone to triggering rounding
errors and problems with fractional node bounds. Make it use
20px instead.
2024-02-25 20:03:35 -05:00
Matthias Clasen
9b5aee0d1b Cosmetics 2024-02-25 18:20:22 -05:00
Logan Rathbone
882387a62a docs: Cross-reference GtkExpression binding method in GtkBuilder docs
The GtkBuilder docs previously only explained the GBinding methodology.
2024-02-24 13:54:35 -05:00
Logan Rathbone
73f7370ead docs: Clarify GtkExpression usage in .ui files 2024-02-24 13:54:35 -05:00
Logan Rathbone
8e9241f3ba docs: Remove unnecessary fetching of adjustment in :output code example 2024-02-24 13:54:35 -05:00
Logan Rathbone
3c67931f5f docs: Clarify child objects in GtkBuilder
Also, document the GListStore special case.
2024-02-24 13:54:34 -05:00
Gergo Koteles
34028ea31e GtkScale: move value in line with the through.
The value is between the through and the markups, and appears scattered.

Move it in line with the through.

Fixes: #5171
2024-02-23 02:04:24 +01:00
Gergo Koteles
4244314a40 GtkScale: add symmetry border to the scales without markups
The scales with marks require css adjustments for center positioning.

Add border to the other side to make it symmetrical.

Fixes: #5171
2024-02-23 01:58:47 +01:00
Sebastian Keller
575bd64698 textview: Fix cursor/anchor mixup when retrieving surrounding text
Previously the code for calculating the cursor and anchor for the
flipped case was mixed up with the logic for the non-flipped case.

Additionally make the code more readable by making the anchor/selection
bound the start and the cursor/insert the end of a selection. Thus a
selection made from left to right goes from start to end. Selections
from right to left, i.e. end to start are considered flipped.

Also update the test to use the correct cursor/anchor and change some
variable names to make it more readable.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/6460
2024-02-22 20:49:10 +01:00
Arjan Molenaar
ee06ac3ad2 macos: determine zoomed state via NSWindow isZoomed
With our custom logic out of the way, this just works.
Maximized state is also update on move, since a moved maximized
window is no longer considered maximized in macOS land.
2024-02-18 14:33:26 +01:00
Arjan Molenaar
19a8870f76 macos: use native zoom/unzoom logic
In macOS, when moving a maximized window, it's not automatically
restored to its default size.

In addition, GdkMacosWindow should not check surface layout properties,
since those properties are lagging, e.i. are set after the (native)
window state has been updated.
2024-02-18 14:33:26 +01:00
Arjan Molenaar
99a3a7e94e macos: deduplicate compute_size logic
It's used in `present` currently. Need to figure out if it really
belongs there: in Wayland no size computation is done in the
`present` handler.
2024-02-17 22:47:47 +01:00
Arjan Molenaar
a516441513 macos: Fix window state of initially maximized windows
GdkSurface maintains state that shadows the actual window state.
This state is not always updated in the macos backend.

In our case, when a window is initially maximized, `setFrame:display:`
was called and `inMaximizeTransition` was set.  However,
`windowDidEndLiveResize:` was never called and `inMaximizeTransition`
was never unset, making the application think the window is still
maximized.

Additionally, `windowShouldZoom:toFrame:` is only called when the window
is maximized, not when it's unmaximized.

By checking and setting the state in `windowDidResize:` we can at least
be sure that the internal maximized state is only set if the window
takes up all desktop space: the screen's visible frame.
2024-02-17 21:04:50 +01:00
Emilio Cobos Álvarez
2f5278a139 [gtk4/wayland] Infer edge constraints from tiled edges.
This is the Gtk4 version of !6742, which fixes the same bug as described
there.
2024-01-12 22:40:22 +01:00
298 changed files with 27468 additions and 13088 deletions

View File

@@ -219,11 +219,13 @@ macos:
- if: $RUNNER == "macosintel"
variables:
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
NINJA_PKG: $CI_API_V4_URL/projects/30745/packages/generic/ninja_macos/v1.11.1.1+9/ninja-1.11.1.1-cp38-cp38-macosx_11_0_x86_64.whl
when: manual
allow_failure: true
- if: $RUNNER == "macosarm"
variables:
SDKROOT: /opt/sdks/MacOSX11.3.sdk
NINJA_PKG: ninja==1.11.1.1
stage: build
parallel:
matrix:
@@ -246,7 +248,7 @@ macos:
- curl -L $CI_API_V4_URL/projects/30437/packages/generic/pkgconfig/v0.29.2+10/pkg-config-0.29.2+10_$(uname -m).tar.xz | tar -C .venv -xJ
- curl -L $CI_API_V4_URL/projects/30438/packages/generic/bison/v3.8.2+3/bison-3.8.2+3_$(uname -m).tar.xz | tar -C .venv -xJ
- source .venv/bin/activate
- pip3 install meson==1.3.2 ninja==1.11.1.1
- pip3 install meson==1.3.2 $NINJA_PKG
# We're not setting up ccache here on purpose as it accelerates the build
# so much that it triggers race conditions in the gobject-introspection
# subproject.

View File

@@ -2,8 +2,6 @@ FROM fedora:39
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
@@ -18,7 +16,6 @@ RUN dnf -y install \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
docbook-style-xsl \
elfutils-libelf-devel \
expat-devel \
fribidi-devel \

View File

@@ -19,7 +19,6 @@ flatpak build ${builddir} meson \
--buildtype=debugoptimized \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dvulkan=disabled \
-Dbuild-tests=false \
-Dbuild-testsuite=false \
-Dbuild-examples=false \

147
NEWS
View File

@@ -1,11 +1,154 @@
Overview of Changes in 4.13.9, xx-xx-xxxx
Overview of Changes in 4.14.2, xx-xx-xxxx
=========================================
Overview of Changes in 4.14.1, 16-03-2024
=========================================
* GtkTextView:
- Fix a mixup of cursor and anchor when retrieving surrounding text
in input methods
* Printing:
- Avoid accessing freed printers
* Accessibility:
- Fix memory leaks
* GDK:
- Rename the GDK_VULKAN_SKIP environment variable to GDK_VULKAN_DISABLE
- Add a GDK_GL_DISABLE environment variable
* GSK:
- Rename the GSK_GPU_SKIP environment variable to GSK_GPU_DISABLE
- Speed up handling of repeated ops, which should help for text
- Speed up the inner loop of text node conversion
- Drop the glyph-align optimization flag
- ngl: Avoid reusing frames while they are in use
- Fix flickering thumbnails in nautilus
- Speed up buffer handling in both ngl and Vulkan
* Demos:
- Skip demos using gl shaders when we're not using the gl renderer
* Build:
- Fix some ubsan warnings
- Avoid zink in ci since it spams stderr
* Translation updates:
Czech
German
Korean
Russian
Overview of Changes in 4.14.0, 12-03-2024
=========================================
Note: The new renderers and dmabuf support are using graphics drivers
in different ways than the old gl renderer, and trigger new driver bugs,
(see for example https://gitlab.gnome.org/GNOME/gtk/-/issues/6418 and
https://gitlab.gnome.org/GNOME/gtk/-/issues/6388). Therefore, it is
recommended to use the latest mesa release (24.0) with the new renderers.
recommended to use the latest mesa release (24.x) with the new renderers.
* GtkTextView:
- Don't snapshot children twice
- Don't blink the cursor when hidden
* GtkEmojiChooser:
- Fix presentation selector handling
* GtkSnapshot:
- Fix wrong nodes with transformed shadows
* GtkIMContext:
- Make gtk_im_context_activate_osk public
* Accessibility:
- Implement get_contents_at for all our text widgets
- Add GtkAccessibleText.get_default_attributes
* GSK:
- Don't fall back to cairo for software rendering. gl+llvmpipe is better
- Round vertical glyph position to a device pixel position if the font is hinted
- Fix problems with clip handling
- Make vulkan and ngl match their font handling
- Fix some corner-cases with offloading and clips
- Fix problem with rendering of missing glyphs in hinted fonts
* MacOs:
- Implement cursor-from-texture
* Translation updates:
Basque
British English
French
Indonesian
Kazakh
Latvian
Lithuanian
Norwegian Bokmål
Slovenian
Spanish
Turkish
Overview of Changes in 4.13.9, 02-03-2024
=========================================
* GtkEditable:
- Fix preconditions to be not too strict
* GtkEmojiChooser:
- Support search in the locale as well as in English
* GtkIconTheme:
- Make gtk_icon_paintable_new_for_file support symbolics
* GtkVideo:
- Fix a problem with cursor handling that could lead to crashes
* Accessibility:
- Fix GetCharacterAtOffset implementation
- Add a Terminal role
- Make TextCaretMoved match gtk3
- Support multiple levels of GtkEditable delegates
* GSK:
- Make the node parser more flexible for text nodes
- Change the way font scaling is handled to avoid clipping
- Fix handling of missing glyphs in the new renderers
* X11:
- Don't claim to support shadows without a compositor
* Wayland:
- Fix handling of output scales
* Tools:
- Add a compare command to gtk4-rendernode-tool
* Build:
- Fix some ubsan complaints
* Translation updates:
Basque
British English
Catalan
Finnish
Galician
Georgian
Hebrew
Indonesian
Kazakh
Latvian
Lithuanian
Persian
Polish
Russian
Slovenian
Spanish
Turkish
Ukrainian
Overview of Changes in 4.13.8, 20-02-2024

View File

@@ -185,7 +185,6 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],

View File

@@ -114,7 +114,6 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],

View File

@@ -114,7 +114,6 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -131,7 +130,6 @@
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}

View File

@@ -114,7 +114,6 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -131,7 +130,6 @@
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -184,6 +184,12 @@ create_cogs (void)
return picture;
}
static gboolean
check_cogs (GtkFishbowl *fb)
{
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
}
static void
mapped (GtkWidget *w)
{
@@ -218,36 +224,41 @@ create_graph (void)
static const struct {
const char *name;
GtkWidget * (*create_func) (void);
GtkWidget * (* create_func) (void);
gboolean (* check) (GtkFishbowl *fb);
} widget_types[] = {
{ "Icon", create_icon },
{ "Button", create_button },
{ "Blurbutton", create_blurred_button },
{ "Fontbutton", create_font_button },
{ "Levelbar", create_level_bar },
{ "Label", create_label },
{ "Spinner", create_spinner },
{ "Spinbutton", create_spinbutton },
{ "Video", create_video },
{ "Gears", create_gears },
{ "Switch", create_switch },
{ "Menubutton", create_menu_button },
{ "Shader", create_cogs },
{ "Tiger", create_tiger },
{ "Graph", create_graph },
{ "Icon", create_icon, NULL },
{ "Button", create_button, NULL },
{ "Blurbutton", create_blurred_button, NULL },
{ "Fontbutton", create_font_button, NULL },
{ "Levelbar", create_level_bar, NULL },
{ "Label", create_label, NULL },
{ "Spinner", create_spinner, NULL },
{ "Spinbutton", create_spinbutton, NULL },
{ "Video", create_video, NULL },
{ "Gears", create_gears, NULL },
{ "Switch", create_switch, NULL },
{ "Menubutton", create_menu_button, NULL },
{ "Shader", create_cogs, check_cogs },
{ "Tiger", create_tiger, NULL },
{ "Graph", create_graph, NULL },
};
static int selected_widget_type = -1;
static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
static void
static gboolean
set_widget_type (GtkFishbowl *fishbowl,
int widget_type_index)
{
GtkWidget *window;
if (widget_type_index == selected_widget_type)
return;
return TRUE;
if (widget_types[widget_type_index].check != NULL &&
!widget_types[widget_type_index].check (fishbowl))
return FALSE;
selected_widget_type = widget_type_index;
@@ -257,6 +268,8 @@ set_widget_type (GtkFishbowl *fishbowl,
window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
gtk_window_set_title (GTK_WINDOW (window),
widget_types[selected_widget_type].name);
return TRUE;
}
G_MODULE_EXPORT void
@@ -264,14 +277,17 @@ fishbowl_next_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = selected_widget_type + 1;
do
{
if (new_index + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = new_index + 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void
@@ -279,14 +295,18 @@ fishbowl_prev_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = selected_widget_type - 1;
do
{
if (new_index - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = new_index - 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void

View File

@@ -600,8 +600,8 @@ update_display (void)
if (s->len > 0)
{
pango_font_description_set_variations (desc, s->str);
g_string_free (s, TRUE);
}
g_string_free (s, TRUE);
font_desc = pango_font_description_to_string (desc);

View File

@@ -116,7 +116,9 @@ static gboolean gtk_shadertoy_tick (GtkWidget *widget,
GtkWidget *
gtk_shadertoy_new (void)
{
return g_object_new (gtk_shadertoy_get_type (), NULL);
return g_object_new (gtk_shadertoy_get_type (),
"allowed-apis", GDK_GL_API_GL,
NULL);
}
static void

View File

@@ -354,6 +354,7 @@ do_images (GtkWidget *do_widget)
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
image = gtk_image_new_from_gicon (gicon);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
g_object_unref (gicon);
gtk_frame_set_child (GTK_FRAME (frame), image);

View File

@@ -827,13 +827,25 @@ demo_search_changed_cb (GtkSearchEntry *entry,
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static gboolean
demo_can_run (GtkWidget *window,
const char *name)
{
if (name != NULL && strcmp (name, "gltransition") == 0)
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
return TRUE;
}
static GListModel *
create_demo_model (void)
create_demo_model (GtkWidget *window)
{
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
DemoData *demo = gtk_demos;
GtkDemo *d;
gtk_widget_realize (window);
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
d->name = "main";
d->title = "GTK Demo";
@@ -845,16 +857,20 @@ create_demo_model (void)
while (demo->title)
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
DemoData *children = demo->children;
DemoData *children = demo->children;
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
if (demo_can_run (window, demo->name))
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
g_list_store_append (store, d);
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
g_list_store_append (store, d);
}
if (children)
{
@@ -862,15 +878,19 @@ create_demo_model (void)
while (children->title)
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
if (demo_can_run (window, children->name))
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
g_list_store_append (G_LIST_STORE (d->children_model), child);
}
g_list_store_append (G_LIST_STORE (d->children_model), child);
children++;
}
}
@@ -936,7 +956,7 @@ activate (GApplication *app)
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
listmodel = create_demo_model ();
listmodel = create_demo_model (window);
treemodel = gtk_tree_list_model_new (G_LIST_MODEL (listmodel),
FALSE,
TRUE,

View File

@@ -2,7 +2,7 @@
<interface>
<menu id="menubar">
<submenu>
<attribute name="label" translatable="yes">_Application</attribute>
<attribute name="label" translatable="yes">_File</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_New</attribute>
@@ -33,7 +33,7 @@
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">_File</attribute>
<attribute name="label" translatable="yes">_Preferences</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_Prefer Dark Theme</attribute>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -338,7 +338,7 @@ do_path_maze (GtkWidget *do_widget)
GskPath *path;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_title (GTK_WINDOW (window), "Follow the maze with the mouse");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -322,12 +322,14 @@ stroke bounds of the path.
### text
| property | syntax | default | printed |
| -------- | ------------------- | ------------------- | ----------- |
| color | `<color>` | black | non-default |
| font | `<string>` `<url>`? | "Cantarell 11" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
| property | syntax | default | printed |
| ------------ | ------------------- | ------------------- | ----------- |
| color | `<color>` | black | non-default |
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
| hint-style | `<hint style>` | slight | non-default |
| antialias | `<antialias>` | gray | non-default |
Creates a node like `gsk_text_node_new()` with the given properties.
@@ -336,12 +338,15 @@ font that is specified in the string. It can be either a data url containing
a base64-encoded font file, or a regular url that points to a font file.
Glyphs can be specified as an ASCII string, or as a comma-separated list of
their glyph ID and advance width. Optionally, x and y offsets and flags can
their glyph IDs. Optionally, the advance width, x and y offsets and flags can
be specified as well, like this: 40 10 0 0 color.
If the given font does not exist or the given glyphs are invalid for the given
font, an error node will be returned.
Possible values for hint-style are none, slight or full.
Possible value for antialias are none or gray.
### texture
| property | syntax | default | printed |

View File

@@ -69,9 +69,9 @@ Image:
4 CARD32 IMAGE_DATA_OFFSET
ICON_FLAGS
HAS_SUFFIX_PNG 1
HAS_SUFFIX_XPM 2
HAS_SUFFIX_SVG 4
HAS_SUFFIX_XPM 1
HAS_SUFFIX_SVG 2
HAS_SUFFIX_PNG 4
HAS_ICON_FILE 8
ImageData:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -38,13 +38,13 @@ can run the build, using Ninja:
```
cd builddir
ninja
ninja install
meson compile
meson install
```
If you don't have permission to write to the directory you are
installing in, you may have to change to root temporarily before
running `ninja install`.
running `meson install`.
Several environment variables are useful to pass to set before
running *meson*. `CPPFLAGS` contains options to pass to the C
@@ -112,10 +112,10 @@ responsible for controlling the debugging features of GTK with
## Dependencies
Before you can compile the GTK widget toolkit, you need to have
various other tools and libraries installed on your
system. Dependencies of GTK have their own build systems, so
you will need to refer to their own installation instructions.
Before you can compile GTK, you need to have various other tools and
libraries installed on your system. Dependencies of GTK have their own
build systems, so you will need to refer to their own installation
instructions.
A particular important tool used by GTK to find its dependencies
is `pkg-config`.
@@ -156,8 +156,8 @@ Other libraries are maintained separately.
the development environment for these libraries that your
operating system vendor provides.
- The [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
library provides Pango with a standard way of locating
fonts and matching them against font names.
library provides Pango with a standard way of locating fonts and matching
them against font names.
- [Cairo](https://www.cairographics.org) is a graphics library that
supports vector graphics and image compositing. Both Pango and GTK
use Cairo for drawing. Note that we also need the auxiliary cairo-gobject
@@ -220,13 +220,12 @@ meson configure builddir
### `x11-backend`, `win32-backend`, `broadway-backend`, `wayland-backend` and `macos-backend`
Enable specific backends for GDK. If none of these options
are given, the Wayland backend will be enabled by default,
if the platform is Linux; the X11 backend will also be enabled
by default, unless the platform is Windows, in which case the
default is win32, or the platform is macOS, in which case the
default is macOS. If any backend is explicitly enabled or disabled,
no other platform will be enabled automatically.
Enable specific backends for GDK. If none of these options are given, the
Wayland backend will be enabled by default, if the platform is Linux; the
X11 backend will also be enabled by default, unless the platform is Windows,
in which case the default is win32, or the platform is macOS, in which case
the default is macOS. If any backend is explicitly enabled or disabled, no
other platform will be enabled automatically.
### `vulkan`

View File

@@ -1,7 +1,7 @@
Title: CSS in GTK
Slug: css
This chapter describes how GTK uses CSS for styling and layout.
This chapter describes how GTK uses CSS for styling and layout.
It is not meant to be an explanation of CSS from first principles,
but focuses on listing supported CSS features and differences
between Web CSS and GTK.

View File

@@ -28,6 +28,9 @@ GTK depends on the following libraries:
- **OpenGL**: OpenGL is the premier environment for developing portable,
interactive 2D and 3D graphics applications. More information available
on the [Khronos website][opengl].
- **Vulkan**: Vulkan is the a newer graphics API, that can be considered
the successor of OpenGL. More information available on the
[Khronos website][vulkan].
- **Pango**: Pango is a library for internationalized text handling. It
centers around the `PangoLayout` object, representing a paragraph of
text. Pango provides the engine for `GtkTextView`, `GtkLabel`,
@@ -60,6 +63,7 @@ GTK is divided into three parts:
[gio]: https://developer.gnome.org/gio/stable/
[cairo]: https://www.cairographics.org/manual/
[opengl]: https://www.opengl.org/about/
[vulkan]: https://www.vulkan.org/
[pango]: https://pango.gnome.org/
[gdkpixbuf]: https://developer.gnome.org/gdk-pixbuf/stable/
[graphene]: https://ebassi.github.io/graphene/

View File

@@ -278,14 +278,11 @@ are only available when GTK has been configured with `-Ddebug=true`.
: OpenGL renderer information
`vulkan`
: Vulkan renderer information
: Check Vulkan errors
`shaders`
: Information about shaders
`surface`
: Information about surfaces
`fallback`
: Information about fallback usage in renderers
@@ -303,9 +300,6 @@ A number of options affect behavior instead of logging:
`full-redraw`
: Force full redraws
`sync`
: Sync after each frame
`staging`
: Use a staging image for texture upload (Vulkan only)
@@ -347,6 +341,28 @@ a `*`, which means: try all remaining backends. The special value
backends. For more information about selecting backends,
see the [func@Gdk.DisplayManager.get] function.
### `GDK_GL_DISABLE`
This variable can be set to a list of values, which cause GDK to
disable extension features of the OpenGL support.
Note that these features may already be disabled if the GL driver
does not support them.
`debug`
: GL_KHR_debug
`unpack-subimage`
:GL_EXT_unpack_subimage
`half-float`
:GL_OES_vertex_half_float
`sync`
:GL_ARB_sync
`base-instance`
:GL_EXT_base_instance
### `GDK_VULKAN_DEVICE`
This variable can be set to the index of a Vulkan device to override
@@ -354,7 +370,7 @@ the default selection of the device that is used for Vulkan rendering.
The special value `list` can be used to obtain a list of all Vulkan
devices.
### `GDK_VULKAN_SKIP`
### `GDK_VULKAN_DISABLE`
This variable can be set to a list of values, which cause GDK to
disable features of the Vulkan support.
@@ -434,7 +450,7 @@ using and the GDK backend supports them:
installation.
### `GSK_GPU_SKIP`
### `GSK_GPU_DISABLE`
This variable can be set to a list of values, which cause GSK to
disable certain optimizations of the "ngl" and "vulkan" renderer.
@@ -454,9 +470,6 @@ disable certain optimizations of the "ngl" and "vulkan" renderer.
`mipmap`
: Avoid creating mipmaps
`gl-baseinstance`
: Assume no ARB/EXT_base_instance support
The special value `all` can be used to turn on all values. The special
value `help` can be used to obtain a list of all supported values.
@@ -469,10 +482,10 @@ n seconds. The default timeout is 15 seconds.
### `GSK_MAX_TEXTURE_SIZE`
Limit texture size to the minimum of this value and the OpenGL limit
for texture sizes. This can be used to debug issues with texture slicing
on systems where the OpenGL texture size limit would otherwise make
texture slicing difficult to test.
Limit texture size to the minimum of this value and the OpenGL limit for
texture sizes in the "gl" renderer. This can be used to debug issues with
texture slicing on systems where the OpenGL texture size limit would
otherwise make texture slicing difficult to test.
### `GTK_CSD`

View File

@@ -1538,6 +1538,7 @@ describe_egl_config (EGLDisplay egl_display,
EGLConfig egl_config)
{
EGLint red, green, blue, alpha, type;
EGLint depth, stencil;
if (egl_config == NULL)
return g_strdup ("-");
@@ -1556,7 +1557,15 @@ describe_egl_config (EGLDisplay egl_display,
else
type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
if (!eglGetConfigAttrib (egl_display, egl_config, EGL_DEPTH_SIZE, &depth))
depth = 0;
if (!eglGetConfigAttrib (egl_display, egl_config, EGL_STENCIL_SIZE, &stencil))
stencil = 0;
return g_strdup_printf ("R%dG%dB%dA%d%s%s%s", red, green, blue, alpha,
type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float",
depth > 0 ? ", depth buffer" : "",
stencil > 0 ? ", stencil buffer" : "");
}
gpointer
@@ -2037,9 +2046,12 @@ gdk_display_get_dmabuf_formats (GdkDisplay *display)
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{
if (display == NULL)
return _gdk_debug_flags;
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
return display ? priv->debug_flags : _gdk_debug_flags;
return priv->debug_flags;
}
void

View File

@@ -50,18 +50,6 @@
#include "gdkenumtypes.h"
#include "gdkeventsprivate.h"
static struct {
GdkDragAction action;
const char *name;
GdkCursor *cursor;
} drag_cursors[] = {
{ GDK_ACTION_ASK, "dnd-ask", NULL },
{ GDK_ACTION_COPY, "copy", NULL },
{ GDK_ACTION_MOVE, "move", NULL },
{ GDK_ACTION_LINK, "alias", NULL },
{ 0, "no-drop", NULL },
};
enum {
PROP_0,
PROP_CONTENT,
@@ -786,6 +774,20 @@ gdk_drag_handle_source_event (GdkEvent *event)
return FALSE;
}
static struct {
GdkDragAction action;
const char *name;
GdkCursor *cursor;
} drag_cursors[] = {
{ 0, "default", NULL },
{ GDK_ACTION_ASK, "dnd-ask", NULL },
{ GDK_ACTION_COPY, "copy", NULL },
{ GDK_ACTION_MOVE, "dnd-move", NULL }, /* Not using move here, since move is stuck using
* a mismatched visual metaphor in Adwaita
*/
{ GDK_ACTION_LINK, "alias", NULL },
};
GdkCursor *
gdk_drag_get_cursor (GdkDrag *drag,
GdkDragAction action)

View File

@@ -79,14 +79,23 @@ static guint signals[LAST_SIGNAL];
static guint fps_counter;
#define FRAME_HISTORY_MAX_LENGTH 128
/* 60Hz plus some extra for monotonic time inaccuracy */
#define FRAME_HISTORY_DEFAULT_LENGTH 64
#define frame_timings_unref(x) gdk_frame_timings_unref((GdkFrameTimings *) (x))
#define GDK_ARRAY_NAME timings
#define GDK_ARRAY_TYPE_NAME Timings
#define GDK_ARRAY_ELEMENT_TYPE GdkFrameTimings *
#define GDK_ARRAY_PREALLOC FRAME_HISTORY_DEFAULT_LENGTH
#define GDK_ARRAY_FREE_FUNC frame_timings_unref
#include "gdk/gdkarrayimpl.c"
struct _GdkFrameClockPrivate
{
gint64 frame_counter;
int n_timings;
int current;
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
Timings timings;
int n_freeze_inhibitors;
};
@@ -99,11 +108,8 @@ static void
gdk_frame_clock_finalize (GObject *object)
{
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
int i;
for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
if (priv->timings[i] != 0)
gdk_frame_timings_unref (priv->timings[i]);
timings_clear (&priv->timings);
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
}
@@ -257,7 +263,8 @@ gdk_frame_clock_init (GdkFrameClock *clock)
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
priv->frame_counter = -1;
priv->current = FRAME_HISTORY_MAX_LENGTH - 1;
priv->current = 0;
timings_init (&priv->timings);
if (fps_counter == 0)
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
@@ -416,7 +423,7 @@ gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock)
static inline gint64
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
{
return frame_clock->priv->frame_counter + 1 - frame_clock->priv->n_timings;
return frame_clock->priv->frame_counter + 1 - timings_get_size (&frame_clock->priv->timings);
}
/**
@@ -445,31 +452,44 @@ gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
}
void
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock,
gint64 monotonic_time)
{
GdkFrameClockPrivate *priv;
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
priv = frame_clock->priv;
priv->frame_counter++;
priv->current = (priv->current + 1) % FRAME_HISTORY_MAX_LENGTH;
/* Try to steal the previous frame timing instead of discarding
* and allocating a new one.
*/
if G_LIKELY (priv->n_timings == FRAME_HISTORY_MAX_LENGTH &&
_gdk_frame_timings_steal (priv->timings[priv->current],
priv->frame_counter))
return;
if (priv->n_timings < FRAME_HISTORY_MAX_LENGTH)
priv->n_timings++;
if (G_UNLIKELY (timings_get_size (&priv->timings) == 0))
timings_append (&priv->timings, _gdk_frame_timings_new (priv->frame_counter));
else
gdk_frame_timings_unref (priv->timings[priv->current]);
{
GdkFrameTimings *timings;
priv->timings[priv->current] = _gdk_frame_timings_new (priv->frame_counter);
priv->current = (priv->current + 1) % timings_get_size (&priv->timings);
timings = timings_get (&priv->timings, priv->current);
if (timings->frame_time + G_USEC_PER_SEC > monotonic_time)
{
/* Keep the timings, not a second old yet */
timings = _gdk_frame_timings_new (priv->frame_counter);
timings_splice (&priv->timings, priv->current, 0, FALSE, &timings, 1);
}
else if (_gdk_frame_timings_steal (timings, priv->frame_counter))
{
/* Stole the previous frame timing instead of discarding
* and allocating a new one, so nothing to do
*/
}
else
{
timings = _gdk_frame_timings_new (priv->frame_counter);
timings_splice (&priv->timings, priv->current, 1, FALSE, &timings, 1);
}
}
}
static inline GdkFrameTimings *
@@ -477,17 +497,21 @@ _gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,
gint64 frame_counter)
{
GdkFrameClockPrivate *priv = frame_clock->priv;
int pos;
gsize size, pos;
if (frame_counter > priv->frame_counter)
return NULL;
if (frame_counter <= priv->frame_counter - priv->n_timings)
size = timings_get_size (&priv->timings);
if (G_UNLIKELY (size == 0))
return NULL;
pos = (priv->current - (priv->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
if (priv->frame_counter - frame_counter >= size)
return NULL;
return priv->timings[pos];
pos = (priv->current - (priv->frame_counter - frame_counter) + size) % size;
return timings_get (&priv->timings, pos);
}
/**
@@ -779,7 +803,10 @@ gdk_frame_clock_get_fps (GdkFrameClock *frame_clock)
start_counter = _gdk_frame_clock_get_history_start (frame_clock);
end_counter = _gdk_frame_clock_get_frame_counter (frame_clock);
start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
for (start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
end_counter > start_counter && start != NULL && !gdk_frame_timings_get_complete (start);
start = _gdk_frame_clock_get_timings (frame_clock, start_counter))
start_counter++;
for (end = _gdk_frame_clock_get_timings (frame_clock, end_counter);
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
end = _gdk_frame_clock_get_timings (frame_clock, end_counter))

View File

@@ -192,6 +192,13 @@ compute_smooth_frame_time (GdkFrameClock *clock,
* and new_frame_time >= old_frame_time. */
frames_passed = (new_frame_time - smoothed_frame_time_base + frame_interval / 2) / frame_interval;
if (frames_passed > 1)
gdk_profiler_add_markf ((smoothed_frame_time_base - (frame_interval * (frames_passed-1))) * 1000L,
frame_interval * (frames_passed-1) * 1000L,
"Dropped Frames",
"%u frames may have been dropped",
frames_passed-1);
/* We use an approximately whole number of frames in the future from
* last smoothed frame time. This way we avoid minor jitter in the
* frame times making the animation speed uneven, but still animate
@@ -548,7 +555,7 @@ gdk_frame_clock_paint_idle (void *data)
priv->smoothed_frame_time_period = frame_interval;
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
_gdk_frame_clock_begin_frame (clock);
_gdk_frame_clock_begin_frame (clock, priv->frame_time);
/* Note "current" is different now so timings != prev_timings */
timings = gdk_frame_clock_get_current_timings (clock);

View File

@@ -106,7 +106,8 @@ struct _GdkFrameTimings
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock,
gint64 monotonic_time);
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
GdkFrameTimings *timings);
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,

View File

@@ -125,7 +125,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
* the GL_UNPACK_ROW_LENGTH support
*/
if (gdk_gl_context_get_use_es (paint_context) &&
!(version >= 300 || gdk_gl_context_has_unpack_subimage (paint_context)))
!(version >= 300 || gdk_gl_context_has_feature (paint_context, GDK_GL_FEATURE_UNPACK_SUBIMAGE)))
return;
/* TODO: avoid reading back non-required data due to dest clip */

View File

@@ -103,6 +103,15 @@
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
static const GdkDebugKey gdk_gl_feature_keys[] = {
{ "debug", GDK_GL_FEATURE_DEBUG, "GL_KHR_debug" },
{ "unpack-subimage", GDK_GL_FEATURE_UNPACK_SUBIMAGE, "GL_EXT_unpack_subimage" },
{ "half-float", GDK_GL_FEATURE_VERTEX_HALF_FLOAT, "GL_OES_vertex_half_float" },
{ "sync", GDK_GL_FEATURE_SYNC, "GL_ARB_sync" },
{ "base-instance", GDK_GL_FEATURE_BASE_INSTANCE, "GL_ARB_base_instance" },
{ "buffer-storage", GDK_GL_FEATURE_BUFFER_STORAGE, "GL_EXT_buffer_storage" },
};
typedef struct _GdkGLContextPrivate GdkGLContextPrivate;
struct _GdkGLContextPrivate
@@ -112,13 +121,9 @@ struct _GdkGLContextPrivate
GdkGLMemoryFlags memory_flags[GDK_MEMORY_N_FORMATS];
guint has_khr_debug : 1;
GdkGLFeatures features;
guint use_khr_debug : 1;
guint has_half_float : 1;
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;
@@ -290,7 +295,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
GdkDisplay *display = gdk_gl_context_get_display (context);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
GdkGLContext *share = gdk_display_get_gl_context (display);
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
GdkGLContextPrivate *share_priv = share ? gdk_gl_context_get_instance_private (share) : NULL;
EGLConfig egl_config;
EGLContext ctx;
EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;
@@ -658,6 +663,7 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_surface_get_display (surface);
EGLSurface egl_surface;
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
if (priv->egl_context == NULL)
return;
@@ -666,8 +672,6 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
egl_surface = gdk_surface_get_egl_surface (surface);
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL swap buffers", NULL);
if (priv->eglSwapBuffersWithDamage)
{
EGLint stack_rects[4 * 4]; /* 4 rects */
@@ -698,6 +702,8 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
else
eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
#endif
gdk_profiler_add_mark (begin_time, GDK_PROFILER_CURRENT_TIME - begin_time, "EGL swap buffers", NULL);
}
static void
@@ -897,11 +903,12 @@ gdk_gl_context_label_object_printf (GdkGLContext *context,
gboolean
gdk_gl_context_has_unpack_subimage (GdkGLContext *context)
gdk_gl_context_has_feature (GdkGLContext *self,
GdkGLFeatures feature)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_unpack_subimage;
return (priv->features & feature) == feature;
}
static gboolean
@@ -1663,10 +1670,53 @@ gdk_gl_version_init_epoxy (GdkGLVersion *version)
*version = GDK_GL_VERSION_INIT (epoxy_version / 10, epoxy_version % 10);
}
static GdkGLFeatures
gdk_gl_context_check_features (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLFeatures features = 0;
if (gdk_gl_context_get_use_es (context))
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage"))
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
else
{
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
if (epoxy_has_gl_extension ("GL_KHR_debug"))
features |= GDK_GL_FEATURE_DEBUG;
if (gdk_gl_context_check_version (context, "3.0", "3.0") ||
epoxy_has_gl_extension ("GL_OES_vertex_half_float"))
features |= GDK_GL_FEATURE_VERTEX_HALF_FLOAT;
if (gdk_gl_context_check_version (context, "3.2", "3.0") ||
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync"))
features |= GDK_GL_FEATURE_SYNC;
if (gdk_gl_context_check_version (context, "4.2", "9.9") ||
epoxy_has_gl_extension ("GL_EXT_base_instance") ||
epoxy_has_gl_extension ("GL_ARB_base_instance"))
features |= GDK_GL_FEATURE_BASE_INSTANCE;
if (gdk_gl_context_check_version (context, "4.4", "9.9") ||
epoxy_has_gl_extension ("GL_EXT_buffer_storage") ||
epoxy_has_gl_extension ("GL_ARB_buffer_storage"))
features |= GDK_GL_FEATURE_BUFFER_STORAGE;
return features;
}
static void
gdk_gl_context_check_extensions (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLFeatures supported_features, disabled_features;
gboolean gl_debug = FALSE;
GdkDisplay *display;
@@ -1684,69 +1734,54 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
if (priv->has_debug_output && gl_debug)
{
gdk_gl_context_make_current (context);
glEnable (GL_DEBUG_OUTPUT);
glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback (gl_debug_message_callback, NULL);
}
if (gdk_gl_context_get_use_es (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;
/* If we asked for a core profile, but didn't get one, we're in legacy mode */
if (!gdk_gl_context_get_use_es (context) &&
!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
priv->is_legacy = 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)))
priv->is_legacy = TRUE;
}
supported_features = gdk_gl_context_check_features (context);
disabled_features = gdk_parse_debug_var ("GDK_GL_DISABLE",
gdk_gl_feature_keys,
G_N_ELEMENTS (gdk_gl_feature_keys));
if (priv->has_khr_debug && gl_debug)
priv->features = supported_features & ~disabled_features;
gdk_gl_context_init_memory_flags (context);
if ((priv->features & GDK_GL_FEATURE_DEBUG) && gl_debug)
{
priv->use_khr_debug = TRUE;
glGetIntegerv (GL_MAX_LABEL_LENGTH, &priv->max_debug_label_length);
}
priv->has_half_float = gdk_gl_context_check_version (context, "3.0", "3.0") ||
epoxy_has_gl_extension ("GL_OES_vertex_half_float");
priv->has_sync = gdk_gl_context_check_version (context, "3.2", "3.0") ||
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync");
gdk_gl_context_init_memory_flags (context);
{
int max_texture_size;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
GDK_DISPLAY_DEBUG (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), OPENGL,
"%s version: %d.%d (%s)\n"
"* GLSL version: %s\n"
"* Max texture size: %d\n"
"* Extensions checked:\n"
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s\n"
" - half float: %s\n"
" - sync: %s\n"
" - bgra: %s",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
gdk_gl_version_get_major (&priv->gl_version), gdk_gl_version_get_minor (&priv->gl_version),
priv->is_legacy ? "legacy" : "core",
glGetString (GL_SHADING_LANGUAGE_VERSION),
max_texture_size,
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");
}
if (GDK_DISPLAY_DEBUG_CHECK (display, OPENGL))
{
int i, max_texture_size;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
gdk_debug_message ("%s version: %d.%d (%s)\n"
"* GLSL version: %s\n"
"* Max texture size: %d\n",
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",
glGetString (GL_SHADING_LANGUAGE_VERSION),
max_texture_size);
gdk_debug_message ("Enabled features (use GDK_GL_DISABLE env var to disable):");
for (i = 0; i < G_N_ELEMENTS (gdk_gl_feature_keys); i++)
{
gdk_debug_message (" %s: %s",
gdk_gl_feature_keys[i].key,
(priv->features & gdk_gl_feature_keys[i].value) ? "YES" :
((disabled_features & gdk_gl_feature_keys[i].value) ? "disabled via env var" :
(((supported_features & gdk_gl_feature_keys[i].value) == 0) ? "not supported" :
"Hum, what? This should not happen.")));
}
}
priv->extensions_checked = TRUE;
}
@@ -2015,30 +2050,6 @@ gdk_gl_context_get_format_flags (GdkGLContext *self,
return priv->memory_flags[format];
}
gboolean
gdk_gl_context_has_debug (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->debug_enabled || priv->use_khr_debug;
}
gboolean
gdk_gl_context_has_vertex_half_float (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_half_float;
}
gboolean
gdk_gl_context_has_sync (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_sync;
}
/* Return if glGenVertexArrays, glBindVertexArray and glDeleteVertexArrays
* can be used
*/

View File

@@ -27,6 +27,15 @@
G_BEGIN_DECLS
typedef enum {
GDK_GL_FEATURE_DEBUG = 1 << 0,
GDK_GL_FEATURE_UNPACK_SUBIMAGE = 1 << 1,
GDK_GL_FEATURE_VERTEX_HALF_FLOAT = 1 << 2,
GDK_GL_FEATURE_SYNC = 1 << 3,
GDK_GL_FEATURE_BASE_INSTANCE = 1 << 4,
GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 5,
} GdkGLFeatures;
typedef enum {
GDK_GL_NONE = 0,
GDK_GL_EGL,
@@ -142,7 +151,6 @@ void gdk_gl_context_get_matching_version (GdkGLContext
gboolean legacy,
GdkGLVersion *out_version);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_push_debug_group (GdkGLContext *context,
const char *message);
void gdk_gl_context_push_debug_group_printf (GdkGLContext *context,
@@ -163,14 +171,11 @@ const char * gdk_gl_context_get_glsl_version_string (GdkGLContext
GdkGLMemoryFlags gdk_gl_context_get_format_flags (GdkGLContext *self,
GdkMemoryFormat format) G_GNUC_PURE;
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_feature (GdkGLContext *self,
GdkGLFeatures feature) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
gboolean gdk_gl_context_has_vertex_half_float (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_sync (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);

View File

@@ -494,7 +494,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
self->id = gdk_gl_texture_builder_get_id (builder);
GDK_TEXTURE (self)->format = gdk_gl_texture_builder_get_format (builder);
self->has_mipmap = gdk_gl_texture_builder_get_has_mipmap (builder);
if (gdk_gl_context_has_sync (self->context))
if (gdk_gl_context_has_feature (self->context, GDK_GL_FEATURE_SYNC))
self->sync = gdk_gl_texture_builder_get_sync (builder);
self->destroy = destroy;
self->data = data;

View File

@@ -260,6 +260,11 @@ gdk_vulkan_strerror (VkResult result)
case VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
return "The provided binary shader code is not compatible with this device. (VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)";
#endif
#if VK_HEADER_VERSION >= 274
case VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
return "The specified Video Std parameters do not adhere to the syntactic or semantic requirements of the used video compression standard or implementation";
#endif
case VK_RESULT_MAX_ENUM:
default:
return "Unknown Vulkan error.";
@@ -547,9 +552,8 @@ physical_device_supports_extension (VkPhysicalDevice device,
return FALSE;
}
static gboolean
physical_device_check_features (VkPhysicalDevice device,
GdkVulkanFeatures *out_features)
static GdkVulkanFeatures
physical_device_check_features (VkPhysicalDevice device)
{
VkPhysicalDeviceVulkan12Features v12_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
@@ -558,15 +562,16 @@ physical_device_check_features (VkPhysicalDevice device,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
.pNext = &v12_features
};
VkPhysicalDeviceFeatures2 features = {
VkPhysicalDeviceFeatures2 v10_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &ycbcr_features
};
VkExternalSemaphoreProperties semaphore_props = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
};
GdkVulkanFeatures features;
vkGetPhysicalDeviceFeatures2 (device, &features);
vkGetPhysicalDeviceFeatures2 (device, &v10_features);
vkGetPhysicalDeviceExternalSemaphoreProperties (device,
&(VkPhysicalDeviceExternalSemaphoreInfo) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
@@ -574,46 +579,46 @@ physical_device_check_features (VkPhysicalDevice device,
},
&semaphore_props);
*out_features = 0;
features = 0;
if (features.features.shaderUniformBufferArrayDynamicIndexing &&
features.features.shaderSampledImageArrayDynamicIndexing)
*out_features |= GDK_VULKAN_FEATURE_DYNAMIC_INDEXING;
if (v10_features.features.shaderUniformBufferArrayDynamicIndexing &&
v10_features.features.shaderSampledImageArrayDynamicIndexing)
features |= GDK_VULKAN_FEATURE_DYNAMIC_INDEXING;
if (v12_features.descriptorIndexing &&
v12_features.descriptorBindingPartiallyBound &&
v12_features.descriptorBindingVariableDescriptorCount &&
v12_features.descriptorBindingSampledImageUpdateAfterBind &&
v12_features.descriptorBindingStorageBufferUpdateAfterBind)
*out_features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
else if (physical_device_supports_extension (device, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
*out_features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
if (v12_features.shaderSampledImageArrayNonUniformIndexing &&
v12_features.shaderStorageBufferArrayNonUniformIndexing)
*out_features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
if (ycbcr_features.samplerYcbcrConversion ||
physical_device_supports_extension (device, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME))
*out_features |= GDK_VULKAN_FEATURE_YCBCR;
features |= GDK_VULKAN_FEATURE_YCBCR;
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) &&
physical_device_supports_extension (device, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME))
*out_features |= GDK_VULKAN_FEATURE_DMABUF;
features |= GDK_VULKAN_FEATURE_DMABUF;
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME))
{
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT)
*out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT;
features |= GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT;
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)
*out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT;
features |= GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT;
}
if (physical_device_supports_extension (device, VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME))
*out_features |= GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT;
features |= GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT;
return TRUE;
return features;
}
static void
@@ -1361,7 +1366,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
first = 0;
last = n_devices;
skip_features = gdk_parse_debug_var ("GDK_VULKAN_SKIP",
skip_features = gdk_parse_debug_var ("GDK_VULKAN_DISABLE",
gsk_vulkan_feature_keys,
G_N_ELEMENTS (gsk_vulkan_feature_keys));
@@ -1449,8 +1454,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
GdkVulkanFeatures features, device_features;
uint32_t n_queue_props;
if (!physical_device_check_features (devices[i], &device_features))
continue;
device_features = physical_device_check_features (devices[i]);
features = device_features & ~skip_features;
@@ -1535,7 +1539,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
display->vk_queue_family_index = j;
display->vulkan_features = features;
GDK_DISPLAY_DEBUG (display, VULKAN, "Enabled features (use GDK_VULKAN_SKIP env var to disable):");
GDK_DISPLAY_DEBUG (display, VULKAN, "Enabled features (use GDK_VULKAN_DISABLE env var to disable):");
for (i = 0; i < G_N_ELEMENTS (gsk_vulkan_feature_keys); i++)
{
GDK_DISPLAY_DEBUG (display, VULKAN, " %s: %s",

View File

@@ -30,6 +30,7 @@
#include <jpeglib.h>
#include <jerror.h>
#include <setjmp.h>
#include <malloc.h>
/* {{{ Error handling */
@@ -237,8 +238,10 @@ gdk_load_jpeg (GBytes *input_bytes,
g_bytes_unref (bytes);
malloc_trim (0);
gdk_profiler_end_mark (before, "Load jpeg", NULL);
return texture;
}

View File

@@ -27,6 +27,7 @@
#include "gsk/gl/fp16private.h"
#include <png.h>
#include <stdio.h>
#include <malloc.h>
/* The main difference between the png load/save code here and
* gdk-pixbuf is that we can support loading 16-bit data in the
@@ -300,6 +301,8 @@ gdk_load_png (GBytes *bytes,
g_free (row_pointers);
png_destroy_read_struct (&png, &info, NULL);
malloc_trim (0);
if (GDK_PROFILER_IS_RUNNING)
{
gint64 end = GDK_PROFILER_CURRENT_TIME;

View File

@@ -26,6 +26,7 @@
#include "gdktexturedownloaderprivate.h"
#include <tiffio.h>
#include <malloc.h>
/* Our main interest in tiff as an image format is that it is
* flexible enough to save all our texture formats without
@@ -500,6 +501,8 @@ gdk_load_tiff (GBytes *input_bytes,
TIFFClose (tif);
malloc_trim (0);
if (GDK_PROFILER_IS_RUNNING)
{
gint64 end = GDK_PROFILER_CURRENT_TIME;

View File

@@ -214,22 +214,6 @@ typedef NSString *CALayerContentsGravity;
}
}
-(void)setFrame:(NSRect)frame display:(BOOL)display
{
NSRect contentRect = [self contentRectForFrameRect:frame];
GdkSurface *surface = GDK_SURFACE (gdk_surface);
gboolean maximized = (surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, frame))
{
gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
_gdk_surface_update_size (surface);
}
[super setFrame:frame display:display];
[[self contentView] setFrame:NSMakeRect (0, 0, contentRect.size.width, contentRect.size.height)];
}
-(id)initWithContentRect:(NSRect)contentRect
styleMask:(NSWindowStyleMask)styleMask
backing:(NSBackingStoreType)backingType
@@ -312,10 +296,6 @@ typedef NSString *CALayerContentsGravity;
GdkMonitor *monitor;
GdkRectangle geometry;
GdkRectangle workarea;
int shadow_top = 0;
int shadow_left = 0;
int shadow_right = 0;
int shadow_bottom = 0;
GdkRectangle window_gdk;
GdkPoint pointer_position;
GdkPoint new_origin;
@@ -323,13 +303,6 @@ typedef NSString *CALayerContentsGravity;
if (!inManualMove)
return NO;
/* Get our shadow so we can adjust the window position sans-shadow */
_gdk_macos_surface_get_shadow (gdk_surface,
&shadow_top,
&shadow_right,
&shadow_bottom,
&shadow_left);
windowFrame = [self frame];
currentLocation = [NSEvent mouseLocation];
@@ -355,21 +328,9 @@ typedef NSString *CALayerContentsGravity;
window_gdk.width = windowFrame.size.width;
window_gdk.height = windowFrame.size.height;
/* Subtract our shadowin from the window */
window_gdk.x += shadow_left;
window_gdk.y += shadow_top;
window_gdk.width = window_gdk.width - shadow_left - shadow_right;
window_gdk.height = window_gdk.height - shadow_top - shadow_bottom;
/* Now place things on the monitor */
_edge_snapping_motion (&self->snapping, &pointer_position, &window_gdk);
/* And add our shadow back to the frame */
window_gdk.x -= shadow_left;
window_gdk.y -= shadow_top;
window_gdk.width += shadow_left + shadow_right;
window_gdk.height += shadow_top + shadow_bottom;
/* Convert to quartz coordinates */
_gdk_macos_display_to_display_coords ([self gdkDisplay],
window_gdk.x,
@@ -387,12 +348,17 @@ typedef NSString *CALayerContentsGravity;
-(void)windowDidMove:(NSNotification *)notification
{
if ([self isZoomed])
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
else
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
_gdk_macos_surface_configure ([self gdkSurface]);
}
-(void)windowDidResize:(NSNotification *)notification
{
_gdk_macos_surface_configure (gdk_surface);
[self windowDidMove: notification];
/* If we're using server-side decorations, this notification is coming
* in from a display-side change. We need to request a layout in
@@ -413,7 +379,6 @@ typedef NSString *CALayerContentsGravity;
-(void)beginManualMove
{
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
NSPoint initialMoveLocation;
GdkPoint point;
GdkMonitor *monitor;
@@ -432,13 +397,6 @@ typedef NSString *CALayerContentsGravity;
initialMoveLocation = [NSEvent mouseLocation];
if (maximized)
[self setFrame:NSMakeRect (initialMoveLocation.x - (int)lastUnmaximizedFrame.size.width/2,
initialMoveLocation.y,
lastUnmaximizedFrame.size.width,
lastUnmaximizedFrame.size.height)
display:YES];
_gdk_macos_display_from_display_coords ([self gdkDisplay],
initialMoveLocation.x,
initialMoveLocation.y,
@@ -734,26 +692,16 @@ typedef NSString *CALayerContentsGravity;
-(void)setStyleMask:(NSWindowStyleMask)styleMask
{
gboolean was_fullscreen;
gboolean is_fullscreen;
gboolean was_opaque;
gboolean is_opaque;
was_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
was_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
[super setStyleMask:styleMask];
is_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
if (was_fullscreen != is_fullscreen)
{
if (was_fullscreen)
[self setFrame:lastUnfullscreenFrame display:NO];
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
}
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
if (was_opaque != is_opaque)
{
@@ -766,58 +714,20 @@ typedef NSString *CALayerContentsGravity;
-(NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{
GdkMacosSurface *surface = gdk_surface;
NSRect rect;
int shadow_top;
/* Allow the window to move up "shadow_top" more than normally allowed
* by the default impl. This makes it possible to move windows with
* client side shadow right up to the screen's menu bar. */
_gdk_macos_surface_get_shadow (surface, &shadow_top, NULL, NULL, NULL);
rect = [super constrainFrameRect:frameRect toScreen:screen];
if (frameRect.origin.y > rect.origin.y)
rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + shadow_top);
rect.origin.y = MIN (frameRect.origin.y, rect.origin.y);
return rect;
}
/* Implementing this method avoids new windows move around the screen. */
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
defaultFrame:(NSRect)newFrame
{
NSRect screenFrame = [[self screen] visibleFrame];
GdkMacosSurface *surface = gdk_surface;
gboolean maximized = GDK_SURFACE (surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
if (!maximized)
return screenFrame;
else
return lastUnmaximizedFrame;
}
-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
toFrame:(NSRect)newFrame
{
GdkMacosSurface *surface = gdk_surface;
GdkToplevelState state = GDK_SURFACE (surface)->state;
if (state & GDK_TOPLEVEL_STATE_MAXIMIZED)
{
lastMaximizedFrame = newFrame;
}
else
{
lastUnmaximizedFrame = [nsWindow frame];
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
}
inMaximizeTransition = YES;
return YES;
}
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
{
inMaximizeTransition = NO;
return newFrame;
}
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
@@ -828,7 +738,6 @@ typedef NSString *CALayerContentsGravity;
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = YES;
lastUnfullscreenFrame = [self frame];
}
-(void)windowDidEnterFullScreen:(NSNotification *)aNotification

View File

@@ -49,10 +49,6 @@
EdgeSnapping snapping;
NSRect lastUnmaximizedFrame;
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
BOOL inMaximizeTransition;
BOOL inFullscreenTransition;
}

View File

@@ -151,6 +151,57 @@ create_blank_cursor (void)
return nscursor;
}
static NSCursor *
create_cursor_from_texture (GdkTexture *texture,
int x,
int y)
{
guint32 width;
guint32 height;
guchar *pixels;
gsize stride;
GdkTextureDownloader *downloader;
NSCursor *nscursor;
NSBitmapImageRep *nsbitmap;
NSImage *nsimage;
if (texture == NULL)
return create_blank_cursor ();
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
nsbitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:0
bitsPerPixel:0];
pixels = [nsbitmap bitmapData];
stride = [nsbitmap bytesPerRow];
downloader = gdk_texture_downloader_new (texture);
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
gdk_texture_downloader_download_into (downloader,
pixels,
stride);
gdk_texture_downloader_free (downloader);
nsimage = [[NSImage alloc] init];
[nsimage addRepresentation:nsbitmap];
[nsimage setSize:NSMakeSize(width, height)];
[nsbitmap release];
nscursor = [[NSCursor alloc] initWithImage:nsimage
hotSpot:NSMakePoint(x, y)];
[nsimage release];
return nscursor;
}
NSCursor *
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
{
@@ -161,7 +212,17 @@ _gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
if (cursor != NULL)
name = gdk_cursor_get_name (cursor);
{
name = gdk_cursor_get_name (cursor);
if (name == NULL)
{
nscursor = create_cursor_from_texture (gdk_cursor_get_texture (cursor),
gdk_cursor_get_hotspot_x (cursor),
gdk_cursor_get_hotspot_y (cursor));
return nscursor;
}
}
if (name == NULL)
goto load_cursor;

View File

@@ -47,20 +47,20 @@ _gdk_macos_display_position_toplevel_with_parent (GdkMacosDisplay *self,
/* Try to center on top of the parent but also try to make the whole thing
* visible in case that lands us under the topbar/panel/etc.
*/
parent_rect.x = parent->root_x + parent->shadow_left;
parent_rect.y = parent->root_y + parent->shadow_top;
parent_rect.width = GDK_SURFACE (parent)->width - parent->shadow_left - parent->shadow_right;
parent_rect.height = GDK_SURFACE (parent)->height - parent->shadow_top - parent->shadow_bottom;
parent_rect.x = parent->root_x;
parent_rect.y = parent->root_y;
parent_rect.width = GDK_SURFACE (parent)->width;
parent_rect.height = GDK_SURFACE (parent)->height;
surface_rect.width = GDK_SURFACE (surface)->width - surface->shadow_left - surface->shadow_right;
surface_rect.height = GDK_SURFACE (surface)->height - surface->shadow_top - surface->shadow_bottom;
surface_rect.width = GDK_SURFACE (surface)->width;
surface_rect.height = GDK_SURFACE (surface)->height;
surface_rect.x = parent_rect.x + ((parent_rect.width - surface_rect.width) / 2);
surface_rect.y = parent_rect.y + ((parent_rect.height - surface_rect.height) / 2);
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;
*x = surface_rect.x;
*y = surface_rect.y;
}
static inline gboolean
@@ -99,15 +99,15 @@ _gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
gdk_macos_monitor_get_workarea (monitor, &workarea);
/* First place at top-left of current monitor */
surface_rect.width = GDK_SURFACE (surface)->width - surface->shadow_left - surface->shadow_right;
surface_rect.height = GDK_SURFACE (surface)->height - surface->shadow_top - surface->shadow_bottom;
surface_rect.width = GDK_SURFACE (surface)->width;
surface_rect.height = GDK_SURFACE (surface)->height;
surface_rect.x = workarea.x + ((workarea.width - surface_rect.width) / 2);
surface_rect.y = workarea.y + ((workarea.height - surface_rect.height) / 2);
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (surface->best_monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;
*x = surface_rect.x;
*y = surface_rect.y;
/* Try to see if there are any other surfaces at this origin and if so,
* adjust until we get something better.
@@ -119,11 +119,11 @@ _gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
*y += WARP_OFFSET_Y;
/* If we reached the bottom right, just bail and try the workspace origin */
if (*x + surface->shadow_left + WARP_OFFSET_X > workarea.x + workarea.width ||
*y + surface->shadow_top + WARP_OFFSET_Y > workarea.y + workarea.height)
if (*x + WARP_OFFSET_X > workarea.x + workarea.width ||
*y + WARP_OFFSET_Y > workarea.y + workarea.height)
{
*x = workarea.x - surface->shadow_left;
*y = workarea.y - surface->shadow_top;
*x = workarea.x;
*y = workarea.y;
return;
}
}

View File

@@ -998,7 +998,9 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
{
const GdkToNSEventMap *map = iter->data;
if (map->gdk_event == event)
if (map->gdk_event->event_type == event->event_type &&
map->gdk_event->device == event->device &&
map->gdk_event->time == event->time)
return map->nsevent;
}

View File

@@ -68,19 +68,10 @@ gdk_macos_popup_surface_layout (GdkMacosPopupSurface *self,
monitor = _gdk_macos_surface_get_best_monitor (GDK_MACOS_SURFACE (self));
gdk_macos_monitor_get_workarea (monitor, &bounds);
gdk_popup_layout_get_shadow_width (layout,
&self->parent_instance.shadow_left,
&self->parent_instance.shadow_right,
&self->parent_instance.shadow_top,
&self->parent_instance.shadow_bottom);
gdk_surface_layout_popup_helper (GDK_SURFACE (self),
width,
height,
self->parent_instance.shadow_left,
self->parent_instance.shadow_right,
self->parent_instance.shadow_top,
self->parent_instance.shadow_bottom,
0, 0, 0, 0, /* shadow-left/right/top/bottom */
monitor,
&bounds,
self->layout,

View File

@@ -61,11 +61,6 @@ struct _GdkMacosSurface
int height;
} next_layout;
int shadow_top;
int shadow_right;
int shadow_bottom;
int shadow_left;
cairo_rectangle_int_t next_frame;
gint64 pending_frame_counter;
@@ -91,16 +86,6 @@ CGDirectDisplayID _gdk_macos_surface_get_screen_id (GdkMacosSurface
const char *_gdk_macos_surface_get_title (GdkMacosSurface *self);
void _gdk_macos_surface_set_title (GdkMacosSurface *self,
const char *title);
void _gdk_macos_surface_get_shadow (GdkMacosSurface *self,
int *top,
int *right,
int *bottom,
int *left);
void _gdk_macos_surface_set_shadow (GdkMacosSurface *self,
int top,
int right,
int bottom,
int left);
gboolean _gdk_macos_surface_is_opaque (GdkMacosSurface *self);
NSView *_gdk_macos_surface_get_view (GdkMacosSurface *self);
gboolean _gdk_macos_surface_get_modal_hint (GdkMacosSurface *self);

View File

@@ -56,14 +56,6 @@ enum {
static GParamSpec *properties [LAST_PROP];
static gboolean
window_is_fullscreen (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
return ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
}
void
_gdk_macos_surface_request_frame (GdkMacosSurface *self)
{
@@ -244,32 +236,6 @@ gdk_macos_surface_get_scale (GdkSurface *surface)
return [self->window backingScaleFactor];
}
void
_gdk_macos_surface_set_shadow (GdkMacosSurface *surface,
int top,
int right,
int bottom,
int left)
{
GdkMacosSurface *self = (GdkMacosSurface *)surface;
g_assert (GDK_IS_MACOS_SURFACE (self));
if (self->shadow_top == top &&
self->shadow_right == right &&
self->shadow_bottom == bottom &&
self->shadow_left == left)
return;
self->shadow_top = top;
self->shadow_right = right;
self->shadow_bottom = bottom;
self->shadow_left = left;
if (top || right || bottom || left)
[self->window setHasShadow:NO];
}
static void
gdk_macos_surface_begin_frame (GdkMacosSurface *self)
{
@@ -587,29 +553,6 @@ gdk_macos_surface_init (GdkMacosSurface *self)
self->monitors = g_ptr_array_new_with_free_func (g_object_unref);
}
void
_gdk_macos_surface_get_shadow (GdkMacosSurface *self,
int *top,
int *right,
int *bottom,
int *left)
{
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if (top)
*top = self->shadow_top;
if (left)
*left = self->shadow_left;
if (bottom)
*bottom = self->shadow_bottom;
if (right)
*right = self->shadow_right;
}
gboolean
_gdk_macos_surface_is_opaque (GdkMacosSurface *self)
{
@@ -758,7 +701,7 @@ _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
state = GDK_SURFACE (self)->state;
is_fullscreen = window_is_fullscreen (self);
is_fullscreen = ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
was_fullscreen = (state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
if (is_fullscreen != was_fullscreen)
@@ -1105,16 +1048,12 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_set_object (&child->best_monitor, best);
area.x = self->root_x + GDK_SURFACE (child)->x + child->shadow_left;
area.y = self->root_y + GDK_SURFACE (child)->y + child->shadow_top;
area.width = GDK_SURFACE (child)->width - child->shadow_left - child->shadow_right;
area.height = GDK_SURFACE (child)->height - child->shadow_top - child->shadow_bottom;
area.x = self->root_x + GDK_SURFACE (child)->x;
area.y = self->root_y + GDK_SURFACE (child)->y;
area.width = GDK_SURFACE (child)->width;
area.height = GDK_SURFACE (child)->height;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (best), &area);
area.x -= child->shadow_left;
area.y -= child->shadow_top;
_gdk_macos_surface_move (child, area.x, area.y);
gdk_surface_invalidate_rect (GDK_SURFACE (child), NULL);
}

View File

@@ -96,37 +96,26 @@ _gdk_macos_toplevel_surface_unminimize (GdkMacosToplevelSurface *self)
[window deminiaturize:window];
}
static void
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
static gboolean
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
GdkToplevelSize size;
GdkDisplay *display;
GdkMonitor *monitor;
int bounds_width, bounds_height;
int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
NSWindowStyleMask style_mask;
gboolean maximize;
gboolean fullscreen;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
if (layout != self->layout)
{
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
self->layout = gdk_toplevel_layout_copy (layout);
}
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
return FALSE;
_gdk_macos_toplevel_surface_attach_to_parent (self);
style_mask = [nswindow styleMask];
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
display = gdk_surface_get_display (surface);
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
@@ -144,59 +133,121 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (toplevel, &size);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
g_warn_if_fail (size.width > 0);
g_warn_if_fail (size.height > 0);
width = size.width;
height = size.height;
if (gdk_toplevel_layout_get_resizable (layout))
if (self->layout != NULL &&
gdk_toplevel_layout_get_resizable (self->layout))
{
geometry.min_width = size.min_width;
geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
/* Only set 'Resizable' mask to get native resize zones if the window is
* titled, otherwise we do this internally for CSD and do not need
* NSWindow to do it for us. Additionally, it can mess things up when
* doing a window resize since it can cause mouseDown to get passed
* through to the next window.
*/
if ((style_mask & NSWindowStyleMaskTitled) != 0)
style_mask |= NSWindowStyleMaskResizable;
else
style_mask &= ~NSWindowStyleMaskResizable;
}
else
{
geometry.max_width = geometry.min_width = width;
geometry.max_height = geometry.min_height = height;
geometry.max_width = geometry.min_width = size.width;
geometry.max_height = geometry.min_height = size.height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
style_mask &= ~NSWindowStyleMaskResizable;
}
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
GDK_TOPLEVEL_STATE_MAXIMIZED |
GDK_TOPLEVEL_STATE_TILED |
GDK_TOPLEVEL_STATE_TOP_TILED |
GDK_TOPLEVEL_STATE_RIGHT_TILED |
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
GDK_TOPLEVEL_STATE_LEFT_TILED |
GDK_TOPLEVEL_STATE_MINIMIZED) ||
[macos_surface->window inLiveResize])
return FALSE;
/* If we delayed a user resize until the beginning of the frame,
* apply it now so we can start processing updates for it.
*/
if (macos_surface->next_layout.width > 0 &&
macos_surface->next_layout.height > 0)
{
int root_x = macos_surface->next_layout.root_x;
int root_y = macos_surface->next_layout.root_y;
int width = macos_surface->next_layout.width;
int height = macos_surface->next_layout.height;
gdk_surface_constrain_size (&geometry, mask,
width, height,
&width, &height);
macos_surface->next_layout.width = 0;
macos_surface->next_layout.height = 0;
_gdk_macos_surface_move_resize (macos_surface,
root_x, root_y,
width, height);
return FALSE;
}
gdk_surface_constrain_size (&geometry, mask,
size.width, size.height,
&size.width, &size.height);
if ((size.width != self->last_computed_width ||
size.height != self->last_computed_height) &&
(size.width != surface->width ||
size.height != surface->height))
{
self->last_computed_width = size.width;
self->last_computed_height = size.height;
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
}
return FALSE;
}
static void
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
GdkDisplay *display = gdk_surface_get_display (surface);
NSWindowStyleMask style_mask;
gboolean maximize;
gboolean fullscreen;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
if (layout != self->layout)
{
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
self->layout = gdk_toplevel_layout_copy (layout);
}
_gdk_macos_toplevel_surface_attach_to_parent (self);
_gdk_macos_toplevel_surface_compute_size (surface);
/* Only set 'Resizable' mask to get native resize zones if the window is
* titled, otherwise we do this internally for CSD and do not need
* NSWindow to do it for us. Additionally, it can mess things up when
* doing a window resize since it can cause mouseDown to get passed
* through to the next window.
*/
style_mask = [nswindow styleMask];
if (gdk_toplevel_layout_get_resizable (layout) &&
(style_mask & NSWindowStyleMaskTitled) != 0)
style_mask |= NSWindowStyleMaskResizable;
else
style_mask &= ~NSWindowStyleMaskResizable;
if (style_mask != [nswindow styleMask])
[nswindow setStyleMask:style_mask];
if (size.shadow.is_valid)
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (surface),
size.shadow.top,
size.shadow.right,
size.shadow.bottom,
size.shadow.left);
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
GDK_DEBUG (MISC, "Resizing \"%s\" to %dx%d",
GDK_MACOS_SURFACE (self)->title ?
GDK_MACOS_SURFACE (self)->title :
"untitled",
width, height);
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
/* Maximized state */
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
{
@@ -378,125 +429,6 @@ _gdk_macos_toplevel_surface_hide (GdkSurface *surface)
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
}
static gboolean
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
GdkToplevelSize size;
GdkDisplay *display;
GdkMonitor *monitor;
int bounds_width, bounds_height;
GdkGeometry geometry;
GdkSurfaceHints mask;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
return FALSE;
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
display = gdk_surface_get_display (surface);
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
{
GdkRectangle workarea;
gdk_macos_monitor_get_workarea (monitor, &workarea);
bounds_width = workarea.width;
bounds_height = workarea.height;
}
else
{
bounds_width = G_MAXINT;
bounds_height = G_MAXINT;
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
g_warn_if_fail (size.width > 0);
g_warn_if_fail (size.height > 0);
if (self->layout != NULL &&
gdk_toplevel_layout_get_resizable (self->layout))
{
geometry.min_width = size.min_width;
geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
{
geometry.max_width = geometry.min_width = size.width;
geometry.max_height = geometry.min_height = size.height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
}
if (size.shadow.is_valid)
_gdk_macos_surface_set_shadow (macos_surface,
size.shadow.top,
size.shadow.right,
size.shadow.bottom,
size.shadow.left);
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
GDK_TOPLEVEL_STATE_MAXIMIZED |
GDK_TOPLEVEL_STATE_TILED |
GDK_TOPLEVEL_STATE_TOP_TILED |
GDK_TOPLEVEL_STATE_RIGHT_TILED |
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
GDK_TOPLEVEL_STATE_LEFT_TILED |
GDK_TOPLEVEL_STATE_MINIMIZED) ||
[macos_surface->window inLiveResize])
return FALSE;
/* If we delayed a user resize until the beginning of the frame,
* apply it now so we can start processing updates for it.
*/
if (macos_surface->next_layout.width > 0 &&
macos_surface->next_layout.height > 0)
{
int root_x = macos_surface->next_layout.root_x;
int root_y = macos_surface->next_layout.root_y;
int width = macos_surface->next_layout.width;
int height = macos_surface->next_layout.height;
gdk_surface_constrain_size (&geometry, mask,
width, height,
&width, &height);
macos_surface->next_layout.width = 0;
macos_surface->next_layout.height = 0;
_gdk_macos_surface_move_resize (macos_surface,
root_x, root_y,
width, height);
return FALSE;
}
gdk_surface_constrain_size (&geometry, mask,
size.width, size.height,
&size.width, &size.height);
if ((size.width != self->last_computed_width ||
size.height != self->last_computed_height) &&
(size.width != surface->width ||
size.height != surface->height))
{
self->last_computed_width = size.width;
self->last_computed_height = size.height;
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
}
return FALSE;
}
static void
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
{

View File

@@ -79,6 +79,7 @@ static const struct {
{ "move", "dnd-move" },
{ "no-drop", "dnd-none" },
{ "dnd-ask", "dnd-copy" }, /* not CSS, but we want to guarantee it anyway */
{ "dnd-move", "default" },
{ "not-allowed", "crossed_circle" },
{ "grab", "hand2" },
{ "grabbing", "hand2" },

View File

@@ -310,7 +310,8 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
if (buffer)
{
wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
if (wl_surface_get_version (pointer->pointer_surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
wl_surface_damage (pointer->pointer_surface, 0, 0, w, h);
wl_surface_commit (pointer->pointer_surface);
}

View File

@@ -58,6 +58,7 @@
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include <wayland/server-decoration-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#include "wm-button-layout-translation.h"
@@ -95,7 +96,6 @@
#define GTK_SHELL1_VERSION 5
#define OUTPUT_VERSION_WITH_DONE 2
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
#define XDG_ACTIVATION_VERSION 1
#define OUTPUT_VERSION 3
#ifdef HAVE_TOPLEVEL_STATE_SUSPENDED
@@ -585,21 +585,25 @@ gdk_registry_handle_global (void *data,
{
display_wayland->xdg_activation =
wl_registry_bind (display_wayland->wl_registry, id,
&xdg_activation_v1_interface,
MIN (version, XDG_ACTIVATION_VERSION));
&xdg_activation_v1_interface, 1);
}
else if (strcmp (interface, "wp_fractional_scale_manager_v1") == 0)
{
display_wayland->fractional_scale =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_fractional_scale_manager_v1_interface,
MIN (version, 1));
&wp_fractional_scale_manager_v1_interface, 1);
}
else if (strcmp (interface, "wp_viewporter") == 0)
{
display_wayland->viewporter =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_viewporter_interface,
&wp_viewporter_interface, 1);
}
else if (strcmp (interface, "wp_presentation") == 0)
{
display_wayland->presentation =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_presentation_interface,
MIN (version, 1));
}
@@ -700,7 +704,8 @@ _gdk_wayland_display_open (const char *display_name)
process_on_globals_closures (display_wayland);
/* Wait for initializing to complete. This means waiting for all
* asynchronous roundtrips that were triggered during initial roundtrip. */
* asynchronous roundtrips that were triggered during initial roundtrip.
*/
while (display_wayland->async_roundtrips != NULL)
{
if (wl_display_dispatch (display_wayland->wl_display) < 0)
@@ -710,6 +715,18 @@ _gdk_wayland_display_open (const char *display_name)
}
}
/* Check that we got all the required globals */
if (display_wayland->compositor == NULL ||
display_wayland->shm == NULL ||
display_wayland->data_device_manager == NULL)
{
g_warning ("The Wayland compositor does not provide one or more of the required interfaces, "
"not using Wayland display");
g_object_unref (display);
return NULL;
}
if (display_wayland->xdg_wm_base_id)
{
display_wayland->shell_variant = GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL;
@@ -799,6 +816,7 @@ gdk_wayland_display_dispose (GObject *object)
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
g_clear_pointer (&display_wayland->presentation, wp_presentation_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf_feedback, zwp_linux_dmabuf_feedback_v1_destroy);
if (display_wayland->linux_dmabuf_formats)

View File

@@ -39,6 +39,7 @@
#include <gdk/wayland/xdg-activation-v1-client-protocol.h>
#include <gdk/wayland/fractional-scale-v1-client-protocol.h>
#include <gdk/wayland/viewporter-client-protocol.h>
#include <gdk/wayland/presentation-time-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@@ -125,6 +126,7 @@ struct _GdkWaylandDisplay
struct xdg_activation_v1 *xdg_activation;
struct wp_fractional_scale_manager_v1 *fractional_scale;
struct wp_viewporter *viewporter;
struct wp_presentation *presentation;
GList *async_roundtrips;

View File

@@ -34,6 +34,7 @@
#include <gdk/wayland/gdkwayland.h>
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/gdkseat-wayland.h>
#include <gdk/wayland/gdkwaylandpresentationtime-private.h>
#include <xkbcommon/xkbcommon.h>

View File

@@ -466,9 +466,9 @@ gdk_wayland_surface_create_subsurface (GdkSurface *surface)
GdkWaylandSubsurface *sub;
struct wl_region *region;
if (disp->viewporter == NULL)
if (disp->subcompositor == NULL || disp->viewporter == NULL)
{
GDK_DISPLAY_DEBUG (display, OFFLOAD, "Can't use subsurfaces without viewporter");
GDK_DISPLAY_DEBUG (display, OFFLOAD, "Can't use subsurfaces without subcompositor and viewporter");
return NULL;
}

View File

@@ -44,6 +44,8 @@ struct _GdkWaylandSurface
struct wl_event_queue *event_queue;
struct wl_callback *frame_callback;
GdkWaylandPresentationTime *presentation_time;
unsigned int initial_configure_received : 1;
unsigned int has_uncommitted_ack_configure : 1;
unsigned int has_pending_subsurface_commits : 1;

View File

@@ -52,6 +52,7 @@
#include "gdktoplevel-wayland-private.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
/**
@@ -201,17 +202,23 @@ get_egl_window_size (GdkSurface *surface,
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_NO_FRACTIONAL))
{
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window", gdk_fractional_scale_to_int (&impl->scale));
*width = surface->width * gdk_fractional_scale_to_int (&impl->scale);
*height = surface->height * gdk_fractional_scale_to_int (&impl->scale);
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window (%d %d => %d %d)",
gdk_fractional_scale_to_int (&impl->scale),
surface->width, surface->height,
*width, *height);
}
else
{
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window", gdk_fractional_scale_to_double (&impl->scale));
*width = gdk_fractional_scale_scale (&impl->scale, surface->width),
*height = gdk_fractional_scale_scale (&impl->scale, surface->height);
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window (%d %d => %d %d)",
gdk_fractional_scale_to_double (&impl->scale),
surface->width, surface->height,
*width, *height);
}
}
@@ -397,6 +404,17 @@ gdk_wayland_surface_request_frame (GdkSurface *surface)
wl_proxy_set_queue ((struct wl_proxy *) self->frame_callback, NULL);
wl_callback_add_listener (self->frame_callback, &frame_listener, surface);
if (self->presentation_time == NULL)
{
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
self->presentation_time = gdk_wayland_presentation_time_new (wayland_display);
}
gdk_wayland_presentation_time_track (self->presentation_time,
clock,
self->display_server.wl_surface,
gdk_frame_clock_get_frame_counter (clock));
for (gsize i = 0; i < gdk_surface_get_n_subsurfaces (surface); i++)
{
GdkSubsurface *subsurface = gdk_surface_get_subsurface (surface, i);
@@ -1042,6 +1060,7 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
unmap_popups_for_surface (surface);
g_clear_pointer (&impl->presentation_time, gdk_wayland_presentation_time_free);
g_clear_pointer (&impl->frame_callback, wl_callback_destroy);
if (impl->awaiting_frame_frozen)
{

View File

@@ -34,6 +34,7 @@
#include "gdktoplevelprivate.h"
#include "gdkdevice-wayland-private.h"
#include <wayland/presentation-time-client-protocol.h>
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
@@ -122,6 +123,8 @@ struct _GdkWaylandToplevel
struct wl_output *initial_fullscreen_output;
struct wp_presentation_feedback *feedback;
struct {
GdkToplevelState unset_flags;
GdkToplevelState set_flags;
@@ -458,6 +461,49 @@ gdk_wayland_toplevel_compute_size (GdkSurface *surface)
return FALSE;
}
static gboolean
has_per_edge_tiling_info (GdkToplevelState state)
{
return state & (GDK_TOPLEVEL_STATE_TOP_TILED |
GDK_TOPLEVEL_STATE_RIGHT_TILED |
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
GDK_TOPLEVEL_STATE_LEFT_TILED);
}
static GdkToplevelState
infer_edge_constraints (GdkToplevelState state)
{
if (state & (GDK_TOPLEVEL_STATE_MAXIMIZED | GDK_TOPLEVEL_STATE_FULLSCREEN))
return state;
if (!(state & GDK_TOPLEVEL_STATE_TILED) || !has_per_edge_tiling_info (state))
return state |
GDK_TOPLEVEL_STATE_TOP_RESIZABLE |
GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE |
GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE |
GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
if (!(state & GDK_TOPLEVEL_STATE_TOP_TILED))
state |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
if (!(state & GDK_TOPLEVEL_STATE_RIGHT_TILED))
state |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
if (!(state & GDK_TOPLEVEL_STATE_BOTTOM_TILED))
state |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
if (!(state & GDK_TOPLEVEL_STATE_LEFT_TILED))
state |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
return state;
}
static gboolean
supports_native_edge_constraints (GdkWaylandToplevel*toplevel)
{
struct gtk_surface1 *gtk_surface = toplevel->display_server.gtk_surface;
if (!gtk_surface)
return FALSE;
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
}
static void
gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
{
@@ -475,6 +521,9 @@ gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
new_state = wayland_toplevel->pending.state;
wayland_toplevel->pending.state = 0;
if (!supports_native_edge_constraints (wayland_toplevel))
new_state = infer_edge_constraints (new_state);
is_resizing = wayland_toplevel->pending.is_resizing;
wayland_toplevel->pending.is_resizing = FALSE;
@@ -1990,13 +2039,7 @@ gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
static gboolean
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
{
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
struct gtk_surface1 *gtk_surface = wayland_toplevel->display_server.gtk_surface;
if (!gtk_surface)
return FALSE;
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
return TRUE;
}
static void
@@ -2667,7 +2710,7 @@ gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
if (!display_wayland->xdg_importer)
if (!display_wayland->xdg_importer && !display_wayland->xdg_importer_v2)
{
g_warning ("Server is missing xdg_foreign support");
return FALSE;

View File

@@ -0,0 +1,19 @@
#pragma once
#include <gdk/gdkframeclock.h>
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/gdksurface-wayland.h>
#include <gdk/wayland/gdkwaylanddisplay.h>
G_BEGIN_DECLS
typedef struct _GdkWaylandPresentationTime GdkWaylandPresentationTime;
GdkWaylandPresentationTime *gdk_wayland_presentation_time_new (GdkWaylandDisplay *display);
void gdk_wayland_presentation_time_track (GdkWaylandPresentationTime *self,
GdkFrameClock *frame_clock,
struct wl_surface *surface,
gint64 frame_number);
void gdk_wayland_presentation_time_free (GdkWaylandPresentationTime *self);
G_END_DECLS

View File

@@ -0,0 +1,152 @@
#include "config.h"
#include <gdk/gdkframeclockprivate.h>
#include "gdkwaylandpresentationtime-private.h"
typedef struct _GdkWaylandPresentationFrame
{
GdkWaylandPresentationTime *self;
struct wp_presentation_feedback *feedback;
GdkFrameClock *frame_clock;
gint64 frame_number;
} GdkWaylandPresentationFrame;
static void
gdk_wayland_presentation_frame_free (GdkWaylandPresentationFrame *frame)
{
g_clear_pointer (&frame->feedback, wp_presentation_feedback_destroy);
g_clear_object (&frame->frame_clock);
frame->self = NULL;
g_free (frame);
}
struct _GdkWaylandPresentationTime
{
GdkWaylandDisplay *display;
GPtrArray *frames;
};
GdkWaylandPresentationTime *
gdk_wayland_presentation_time_new (GdkWaylandDisplay *display)
{
GdkWaylandPresentationTime *self;
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL);
self = g_new0 (GdkWaylandPresentationTime, 1);
self->display = g_object_ref (display);
self->frames = g_ptr_array_new_with_free_func ((GDestroyNotify)gdk_wayland_presentation_frame_free);
return self;
}
void
gdk_wayland_presentation_time_free (GdkWaylandPresentationTime *self)
{
g_clear_pointer (&self->frames, g_ptr_array_unref);
g_clear_object (&self->display);
g_free (self);
}
static gint64
time_from_wayland (uint32_t tv_sec_hi,
uint32_t tv_sec_lo,
uint32_t tv_nsec)
{
guint64 t = tv_sec_hi;
t <<= 32;
t |= tv_sec_lo;
t *= G_USEC_PER_SEC;
t += tv_nsec / 1000L;
return (gint64)t;
}
static void
gdk_wayland_presentation_feedback_sync_output (void *data,
struct wp_presentation_feedback *feedback,
struct wl_output *output)
{
}
static void
gdk_wayland_presentation_feedback_presented (void *data,
struct wp_presentation_feedback *feedback,
uint32_t tv_sec_hi,
uint32_t tv_sec_lo,
uint32_t tv_nsec,
uint32_t refresh,
uint32_t seq_hi,
uint32_t seq_lo,
uint32_t flags)
{
GdkWaylandPresentationFrame *frame = data;
GdkWaylandPresentationTime *self;
GdkFrameTimings *timings;
guint pos;
g_assert (frame != NULL);
g_assert (frame->self != NULL);
self = frame->self;
if ((timings = gdk_frame_clock_get_timings (frame->frame_clock, frame->frame_number)))
{
timings->presentation_time = time_from_wayland (tv_sec_hi, tv_sec_lo, tv_nsec);
timings->complete = TRUE;
}
if (g_ptr_array_find (self->frames, frame, &pos))
g_ptr_array_remove_index_fast (self->frames, pos);
}
static void
gdk_wayland_presentation_feedback_discarded (void *data,
struct wp_presentation_feedback *feedback)
{
GdkWaylandPresentationFrame *frame = data;
guint pos;
g_assert (frame != NULL);
g_assert (frame->self != NULL);
if (g_ptr_array_find (frame->self->frames, frame, &pos))
g_ptr_array_remove_index_fast (frame->self->frames, pos);
}
static const struct wp_presentation_feedback_listener gdk_wayland_presentation_feedback_listener = {
gdk_wayland_presentation_feedback_sync_output,
gdk_wayland_presentation_feedback_presented,
gdk_wayland_presentation_feedback_discarded,
};
void
gdk_wayland_presentation_time_track (GdkWaylandPresentationTime *self,
GdkFrameClock *frame_clock,
struct wl_surface *surface,
gint64 frame_number)
{
struct wp_presentation_feedback *feedback;
GdkWaylandPresentationFrame *frame;
g_return_if_fail (self != NULL);
g_return_if_fail (surface != NULL);
if (self->display->presentation == NULL)
return;
if (!(feedback = wp_presentation_feedback (self->display->presentation, surface)))
return;
frame = g_new0 (GdkWaylandPresentationFrame, 1);
frame->self = self;
frame->frame_clock = g_object_ref (frame_clock);
frame->frame_number = frame_number;
frame->feedback = g_steal_pointer (&feedback);
g_ptr_array_add (self->frames, frame);
wp_presentation_feedback_add_listener (frame->feedback,
&gdk_wayland_presentation_feedback_listener,
frame);
}

View File

@@ -22,6 +22,7 @@ gdk_wayland_sources = files([
'gdktoplevel-wayland.c',
'gdkpopup-wayland.c',
'gdkvulkancontext-wayland.c',
'gdkwaylandpresentationtime.c',
'wm-button-layout-translation.c',
])
@@ -69,6 +70,7 @@ proto_sources = [
['xdg-activation', 'staging', 'v1', ],
['fractional-scale', 'staging', 'v1', ],
['linux-dmabuf', 'unstable', 'v1', ],
['presentation-time', 'stable', 'v1', ],
]
gdk_wayland_gen_headers = []

View File

@@ -1627,7 +1627,7 @@ _gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
has_any_decorations = FALSE;
if (style & (WS_BORDER | WS_THICKFRAME | WS_CAPTION |
WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX))
WS_SYSMENU | WS_MAXIMIZEBOX))
has_any_decorations = TRUE;
else
GDK_NOTE (MISC, g_print ("Window %p (handle %p): has no decorations (style %lx)\n",
@@ -1696,7 +1696,6 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
}

View File

@@ -3015,6 +3015,8 @@ gdk_x11_display_init_gl_backend (GdkX11Display *self,
self->egl_version = epoxy_egl_version (egl_display);
XFree (visinfo);
return TRUE;
}

View File

@@ -488,12 +488,14 @@ gsk_gl_command_queue_new (GdkGLContext *context,
int max_texture_size = atoi (g_getenv ("GSK_MAX_TEXTURE_SIZE"));
if (max_texture_size == 0)
{
g_warning ("Failed to parse GSK_MAX_TEXTURE_SIZE");
g_warning ("Failed to parse %s", "GSK_MAX_TEXTURE_SIZE");
}
else
{
max_texture_size = MAX (max_texture_size, 512);
GSK_DEBUG(OPENGL, "Limiting max texture size to %d", max_texture_size);
GSK_DEBUG (RENDERER,
"Limiting texture size in the GL renderer to %d (via %s)",
max_texture_size, "GSK_MAX_TEXTURE_SIZE");
self->max_texture_size = MIN (self->max_texture_size, max_texture_size);
}
}
@@ -1622,7 +1624,7 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
{
glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, width, height, gl_format, gl_type, data);
}
else if (stride % bpp == 0 && gdk_gl_context_has_unpack_subimage (self->context))
else if (stride % bpp == 0 && gdk_gl_context_has_feature (self->context, GDK_GL_FEATURE_UNPACK_SUBIMAGE))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);

View File

@@ -1835,7 +1835,7 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
state = g_new0 (GskGLTextureState, 1);
state->texture_id = texture_id;
state->context = g_object_ref (self->command_queue->context);
if (gdk_gl_context_has_sync (self->command_queue->context))
if (gdk_gl_context_has_feature (self->command_queue->context, GDK_GL_FEATURE_SYNC))
state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
g_hash_table_steal (self->textures, GUINT_TO_POINTER (texture_id));

View File

@@ -194,7 +194,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
{
gdk_gl_context_make_current (context);
if (!gdk_gl_context_has_vertex_half_float (context))
if (!gdk_gl_context_has_feature (context, GDK_GL_FEATURE_VERTEX_HALF_FLOAT))
{
int major, minor;

View File

@@ -52,8 +52,6 @@
#include "ninesliceprivate.h"
#include "fp16private.h"
#define ALLOW_OFFLOAD_FOR_ANY_TEXTURE 1
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
#define MAX_GRADIENT_STOPS 6
@@ -176,6 +174,8 @@ struct _GskGLRenderJob
* looking at the format of the framebuffer we are rendering on.
*/
int target_format;
guint offscreen_count; /* if > 0, we're rendering to an offscreen */
};
typedef struct _GskGLRenderOffscreen
@@ -1235,7 +1235,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
texture = gdk_texture_new_for_surface (surface);
texture_id = gsk_gl_driver_load_texture (job->driver, texture, FALSE);
if (gdk_gl_context_has_debug (job->command_queue->context))
if (gdk_gl_context_has_feature (job->command_queue->context, GDK_GL_FEATURE_DEBUG))
gdk_gl_context_label_object_printf (job->command_queue->context, GL_TEXTURE, texture_id,
"Fallback %s %d",
g_type_name_from_instance ((GTypeInstance *) node),
@@ -2532,7 +2532,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
get_target_format (job, node),
&render_target);
if (gdk_gl_context_has_debug (context))
if (gdk_gl_context_has_feature (context, GDK_GL_FEATURE_DEBUG))
{
gdk_gl_context_label_object_printf (context,
GL_TEXTURE,
@@ -4002,9 +4002,15 @@ gsk_gl_render_job_visit_subsurface_node (GskGLRenderJob *job,
{
if (!gdk_subsurface_is_above_parent (subsurface))
{
/* Clear the area so we can see through */
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)))
if (job->offscreen_count > 0)
{
GDK_DISPLAY_DEBUG (gdk_gl_context_get_display (job->command_queue->context), OFFLOAD, "Hiding subsurface %p in offscreen context", subsurface);
gdk_subsurface_detach (subsurface);
gsk_gl_render_job_visit_node (job, gsk_subsurface_node_get_child (node));
}
else if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)))
{
/* Clear the area so we can see through */
GskGLCommandBatch *batch;
guint16 color[4];
rgba_to_half (&(GdkRGBA){0,0,0,0}, color);
@@ -4382,7 +4388,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
&render_target))
g_assert_not_reached ();
if (gdk_gl_context_has_debug (job->command_queue->context))
if (gdk_gl_context_has_feature (job->command_queue->context, GDK_GL_FEATURE_DEBUG))
{
gdk_gl_context_label_object_printf (job->command_queue->context,
GL_TEXTURE,
@@ -4422,8 +4428,12 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
reset_clip = TRUE;
}
job->offscreen_count++;
gsk_gl_render_job_visit_node (job, node);
job->offscreen_count--;
if (reset_clip)
gsk_gl_render_job_pop_clip (job);

View File

@@ -2,13 +2,14 @@
#include "gskglbufferprivate.h"
/* {{{ GskGLBuffer */
struct _GskGLBuffer
{
GskGpuBuffer parent_instance;
GLenum target;
GLuint buffer_id;
GLenum access;
guchar *data;
};
@@ -19,7 +20,6 @@ gsk_gl_buffer_finalize (GObject *object)
{
GskGLBuffer *self = GSK_GL_BUFFER (object);
g_free (self->data);
glDeleteBuffers (1, &self->buffer_id);
G_OBJECT_CLASS (gsk_gl_buffer_parent_class)->finalize (object);
@@ -34,13 +34,9 @@ gsk_gl_buffer_map (GskGpuBuffer *buffer)
}
static void
gsk_gl_buffer_unmap (GskGpuBuffer *buffer)
gsk_gl_buffer_unmap (GskGpuBuffer *buffer,
gsize used)
{
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
gsk_gl_buffer_bind (self);
glBufferSubData (self->target, 0, gsk_gpu_buffer_get_size (buffer), self->data);
}
static void
@@ -60,28 +56,6 @@ gsk_gl_buffer_init (GskGLBuffer *self)
{
}
GskGpuBuffer *
gsk_gl_buffer_new (GLenum target,
gsize size,
GLenum access)
{
GskGLBuffer *self;
self = g_object_new (GSK_TYPE_GL_BUFFER, NULL);
gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size);
self->target = target;
self->access = access;
glGenBuffers (1, &self->buffer_id);
glBindBuffer (target, self->buffer_id);
glBufferData (target, size, NULL, GL_STATIC_DRAW);
self->data = malloc (size);
return GSK_GPU_BUFFER (self);
}
void
gsk_gl_buffer_bind (GskGLBuffer *self)
{
@@ -95,3 +69,140 @@ gsk_gl_buffer_bind_base (GskGLBuffer *self,
glBindBufferBase (self->target, index, self->buffer_id);
}
static void
gsk_gl_buffer_setup (GskGLBuffer *self,
GLenum target,
gsize size)
{
gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size);
self->target = target;
glGenBuffers (1, &self->buffer_id);
}
/* }}} */
/* {{{ GskGLMappedBuffer */
struct _GskGLMappedBuffer
{
GskGLBuffer parent_instance;
};
G_DEFINE_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK_TYPE_GL_BUFFER)
static void
gsk_gl_mapped_buffer_finalize (GObject *object)
{
GskGLBuffer *self = GSK_GL_BUFFER (object);
gsk_gl_buffer_bind (self);
glUnmapBuffer (self->target);
G_OBJECT_CLASS (gsk_gl_mapped_buffer_parent_class)->finalize (object);
}
static void
gsk_gl_mapped_buffer_class_init (GskGLMappedBufferClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gsk_gl_mapped_buffer_finalize;
}
static void
gsk_gl_mapped_buffer_init (GskGLMappedBuffer *self)
{
}
GskGpuBuffer *
gsk_gl_mapped_buffer_new (GLenum target,
gsize size)
{
GskGLBuffer *self;
self = g_object_new (GSK_TYPE_GL_MAPPED_BUFFER, NULL);
gsk_gl_buffer_setup (self, target, size);
gsk_gl_buffer_bind (self);
glBufferStorage (target,
size,
NULL,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
self->data = glMapBufferRange (target,
0,
size,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
return GSK_GPU_BUFFER (self);
}
/* }}} */
/* {{{ GskGLCopiedBuffer */
struct _GskGLCopiedBuffer
{
GskGLBuffer parent_instance;
};
G_DEFINE_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK_TYPE_GL_BUFFER)
static void
gsk_gl_copied_buffer_finalize (GObject *object)
{
GskGLBuffer *self = GSK_GL_BUFFER (object);
g_free (self->data);
G_OBJECT_CLASS (gsk_gl_copied_buffer_parent_class)->finalize (object);
}
static void
gsk_gl_copied_buffer_unmap (GskGpuBuffer *buffer,
gsize used)
{
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
if (used == 0)
return;
gsk_gl_buffer_bind (self);
glBufferSubData (self->target, 0, used, self->data);
}
static void
gsk_gl_copied_buffer_class_init (GskGLCopiedBufferClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GskGpuBufferClass *buffer_class = GSK_GPU_BUFFER_CLASS (klass);
gobject_class->finalize = gsk_gl_copied_buffer_finalize;
buffer_class->unmap = gsk_gl_copied_buffer_unmap;
}
static void
gsk_gl_copied_buffer_init (GskGLCopiedBuffer *self)
{
}
GskGpuBuffer *
gsk_gl_copied_buffer_new (GLenum target,
gsize size)
{
GskGLBuffer *self;
self = g_object_new (GSK_TYPE_GL_COPIED_BUFFER, NULL);
gsk_gl_buffer_setup (self, target, size);
gsk_gl_buffer_bind (self);
glBufferData (target, size, NULL, GL_STATIC_DRAW);
self->data = malloc (size);
return GSK_GPU_BUFFER (self);
}
/* }}} */

View File

@@ -7,12 +7,17 @@
G_BEGIN_DECLS
#define GSK_TYPE_GL_BUFFER (gsk_gl_buffer_get_type ())
#define GSK_TYPE_GL_MAPPED_BUFFER (gsk_gl_mapped_buffer_get_type ())
#define GSK_TYPE_GL_COPIED_BUFFER (gsk_gl_copied_buffer_get_type ())
G_DECLARE_FINAL_TYPE (GskGLBuffer, gsk_gl_buffer, GSK, GL_BUFFER, GskGpuBuffer)
G_DECLARE_FINAL_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK, GL_MAPPED_BUFFER, GskGLBuffer)
G_DECLARE_FINAL_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK, GL_COPIED_BUFFER, GskGLBuffer)
GskGpuBuffer * gsk_gl_buffer_new (GLenum target,
gsize size,
GLenum access);
GskGpuBuffer * gsk_gl_mapped_buffer_new (GLenum target,
gsize size);
GskGpuBuffer * gsk_gl_copied_buffer_new (GLenum target,
gsize size);
void gsk_gl_buffer_bind (GskGLBuffer *self);
void gsk_gl_buffer_bind_base (GskGLBuffer *self,

View File

@@ -9,6 +9,7 @@
#include "gdk/gdkdisplayprivate.h"
#include "gdk/gdkglcontextprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include <glib/gi18n-lib.h>
@@ -473,6 +474,7 @@ gsk_gl_device_load_program (GskGLDevice *self,
guint n_external_textures,
GError **error)
{
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
GLuint vertex_shader_id, fragment_shader_id, program_id;
GLint link_status;
@@ -527,6 +529,11 @@ gsk_gl_device_load_program (GskGLDevice *self,
return 0;
}
gdk_profiler_end_markf (begin_time,
"Compile Program",
"name=%s id=%u frag=%u vert=%u",
op_class->shader_name, program_id, fragment_shader_id, vertex_shader_id);
return program_id;
}

View File

@@ -20,6 +20,7 @@ struct _GskGLFrame
GLuint globals_buffer_id;
guint next_texture_slot;
GLsync sync;
GHashTable *vaos;
};
@@ -34,7 +35,23 @@ G_DEFINE_TYPE (GskGLFrame, gsk_gl_frame, GSK_TYPE_GPU_FRAME)
static gboolean
gsk_gl_frame_is_busy (GskGpuFrame *frame)
{
return FALSE;
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return FALSE;
return glClientWaitSync (self->sync, 0, 0) == GL_TIMEOUT_EXPIRED;
}
static void
gsk_gl_frame_wait (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return;
glClientWaitSync (self->sync, 0, G_MAXINT64);
}
static void
@@ -50,6 +67,12 @@ gsk_gl_frame_cleanup (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (self->sync)
{
glClientWaitSync (self->sync, 0, -1);
g_clear_pointer (&self->sync, glDeleteSync);
}
self->next_texture_slot = 0;
GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->cleanup (frame);
@@ -124,14 +147,22 @@ gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame,
*/
g_hash_table_remove_all (self->vaos);
return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BUFFER_STORAGE))
return gsk_gl_mapped_buffer_new (GL_ARRAY_BUFFER, size);
else
return gsk_gl_copied_buffer_new (GL_ARRAY_BUFFER, size);
}
static GskGpuBuffer *
gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
{
return gsk_gl_buffer_new (GL_UNIFORM_BUFFER, size, GL_WRITE_ONLY);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BUFFER_STORAGE))
return gsk_gl_mapped_buffer_new (GL_UNIFORM_BUFFER, size);
else
return gsk_gl_copied_buffer_new (GL_UNIFORM_BUFFER, size);
}
static void
@@ -160,6 +191,10 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
{
op = gsk_gpu_op_gl_command (op, frame, &state);
}
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_SYNC))
self->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
static void
@@ -180,6 +215,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
gpu_frame_class->wait = gsk_gl_frame_wait;
gpu_frame_class->setup = gsk_gl_frame_setup;
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;

View File

@@ -17,23 +17,16 @@ struct _GskGpuBlendModeOp
};
static void
gsk_gpu_blend_mode_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_blend_mode_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBlendmodeInstance *instance;
GskGpuBlendmodeInstance *instance = (GskGpuBlendmodeInstance *) instance_;
instance = (GskGpuBlendmodeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "blend-mode");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->bottom_id);
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->top_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
@@ -41,7 +34,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBlendModeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_blend_mode_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -52,6 +45,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_blendmode_info,
#endif
gsk_gpu_blend_mode_op_print_instance,
gsk_gpu_blendmode_setup_attrib_locations,
gsk_gpu_blendmode_setup_vao
};

View File

@@ -20,22 +20,15 @@ struct _GskGpuBlurOp
};
static void
gsk_gpu_blur_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_blur_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBlurInstance *instance;
GskGpuBlurInstance *instance = (GskGpuBlurInstance *) instance_;
instance = (GskGpuBlurInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "blur");
gsk_gpu_print_shader_info (string, shader->clip);
g_string_append_printf (string, "%g,%g ", instance->blur_direction[0], instance->blur_direction[1]);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
@@ -43,7 +36,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBlurOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_blur_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +47,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_blur_info,
#endif
gsk_gpu_blur_op_print_instance,
gsk_gpu_blur_setup_attrib_locations,
gsk_gpu_blur_setup_vao
};

View File

@@ -25,18 +25,12 @@ color_equal (const float *color1,
}
static void
gsk_gpu_border_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_border_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBorderInstance *instance;
GskGpuBorderInstance *instance = (GskGpuBorderInstance *) instance_;
instance = (GskGpuBorderInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "border");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, (const float *) &instance->border_colors[0]);
@@ -58,8 +52,6 @@ gsk_gpu_border_op_print (GskGpuOp *op,
instance->border_widths[2],
instance->border_widths[3]);
}
gsk_gpu_print_newline (string);
}
#ifdef GDK_RENDERING_VULKAN
@@ -85,7 +77,7 @@ static const GskGpuShaderOpClass GSK_GPU_BORDER_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBorderOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_border_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_border_op_vk_command,
#endif
@@ -96,6 +88,7 @@ static const GskGpuShaderOpClass GSK_GPU_BORDER_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_border_info,
#endif
gsk_gpu_border_op_print_instance,
gsk_gpu_border_setup_attrib_locations,
gsk_gpu_border_setup_vao
};

View File

@@ -20,24 +20,17 @@ struct _GskGpuBoxShadowOp
};
static void
gsk_gpu_box_shadow_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_box_shadow_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBoxshadowInstance *instance;
GskGpuBoxshadowInstance *instance = (GskGpuBoxshadowInstance *) instance_;
instance = (GskGpuBoxshadowInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, shader->variation & VARIATION_INSET ? "inset-shadow" : "outset-shadow");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, instance->color);
g_string_append_printf (string, "%g %g %g %g ",
instance->shadow_offset[0], instance->shadow_offset[1],
instance->blur_radius, instance->shadow_spread);
gsk_gpu_print_newline (string);
}
#ifdef GDK_RENDERING_VULKAN
@@ -63,7 +56,7 @@ static const GskGpuShaderOpClass GSK_GPU_BOX_SHADOW_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBoxShadowOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_box_shadow_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_box_shadow_op_vk_command,
#endif
@@ -74,6 +67,7 @@ static const GskGpuShaderOpClass GSK_GPU_BOX_SHADOW_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_boxshadow_info,
#endif
gsk_gpu_box_shadow_op_print_instance,
gsk_gpu_boxshadow_setup_attrib_locations,
gsk_gpu_boxshadow_setup_vao
};

View File

@@ -2,6 +2,8 @@
#include "gskgpubufferprivate.h"
#include <gdk/gdkprofilerprivate.h>
typedef struct _GskGpuBufferPrivate GskGpuBufferPrivate;
struct _GskGpuBufferPrivate
@@ -11,9 +13,13 @@ struct _GskGpuBufferPrivate
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuBuffer, gsk_gpu_buffer, G_TYPE_OBJECT)
static guint profiler_buffer_uploads_id;
static gint64 profiler_buffer_uploads;
static void
gsk_gpu_buffer_class_init (GskGpuBufferClass *klass)
{
profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU");
}
static void
@@ -29,7 +35,7 @@ gsk_gpu_buffer_setup (GskGpuBuffer *self,
priv->size = size;
}
gsize
gsk_gpu_buffer_get_size (GskGpuBuffer *self)
{
@@ -45,8 +51,12 @@ gsk_gpu_buffer_map (GskGpuBuffer *self)
}
void
gsk_gpu_buffer_unmap (GskGpuBuffer *self)
gsk_gpu_buffer_unmap (GskGpuBuffer *self,
gsize size)
{
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self);
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size);
profiler_buffer_uploads += size;
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
}

View File

@@ -23,7 +23,8 @@ struct _GskGpuBufferClass
GObjectClass parent_class;
guchar * (* map) (GskGpuBuffer *self);
void (* unmap) (GskGpuBuffer *self);
void (* unmap) (GskGpuBuffer *self,
gsize used);
};
GType gsk_gpu_buffer_get_type (void) G_GNUC_CONST;
@@ -34,7 +35,8 @@ void gsk_gpu_buffer_setup (GskGpuB
gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self);
guchar * gsk_gpu_buffer_map (GskGpuBuffer *self);
void gsk_gpu_buffer_unmap (GskGpuBuffer *self);
void gsk_gpu_buffer_unmap (GskGpuBuffer *self,
gsize used);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuBuffer, g_object_unref)

View File

@@ -30,6 +30,14 @@ gsk_gpu_clip_init_rect (GskGpuClip *clip,
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
}
static void
gsk_gpu_clip_init_rounded_rect (GskGpuClip *self,
const GskRoundedRect *rect)
{
self->type = GSK_GPU_CLIP_ROUNDED;
gsk_rounded_rect_init_copy (&self->rect, rect);
}
void
gsk_gpu_clip_init_copy (GskGpuClip *self,
const GskGpuClip *src)
@@ -129,6 +137,13 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
break;
case GSK_GPU_CLIP_NONE:
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
if (gsk_gpu_clip_init_after_intersection (dest, res))
break;
/* XXX: This may grow the bounds quite substantially */
gsk_gpu_clip_init_rounded_rect (dest, rounded);
break;
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);

View File

@@ -16,6 +16,7 @@ typedef enum {
GSK_GPU_CLIP_ALL_CLIPPED,
/* No clipping is necessary, but the clip rect is set
* to the actual bounds of the underlying framebuffer
* or handled via the scissor.
*/
GSK_GPU_CLIP_NONE,
/* The clip exists outside the rect, so clipping must

View File

@@ -16,22 +16,15 @@ struct _GskGpuColorizeOp
};
static void
gsk_gpu_colorize_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_colorize_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColorizeInstance *instance;
GskGpuColorizeInstance *instance = (GskGpuColorizeInstance *) instance_;
instance = (GskGpuColorizeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "colorize");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorizeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_colorize_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_colorize_info,
#endif
gsk_gpu_colorize_op_print_instance,
gsk_gpu_colorize_setup_attrib_locations,
gsk_gpu_colorize_setup_vao
};

View File

@@ -16,21 +16,14 @@ struct _GskGpuColorMatrixOp
};
static void
gsk_gpu_color_matrix_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_color_matrix_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColormatrixInstance *instance;
GskGpuColormatrixInstance *instance = (GskGpuColormatrixInstance *) instance_;
instance = (GskGpuColormatrixInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "color-matrix");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
@@ -38,7 +31,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorMatrixOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_color_matrix_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -49,6 +42,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_colormatrix_info,
#endif
gsk_gpu_color_matrix_op_print_instance,
gsk_gpu_colormatrix_setup_attrib_locations,
gsk_gpu_colormatrix_setup_vao
};

View File

@@ -17,21 +17,14 @@ struct _GskGpuColorOp
};
static void
gsk_gpu_color_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_color_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColorInstance *instance;
GskGpuColorInstance *instance = (GskGpuColorInstance *) instance_;
instance = (GskGpuColorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "color");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_color_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_color_info,
#endif
gsk_gpu_color_op_print_instance,
gsk_gpu_color_setup_attrib_locations,
gsk_gpu_color_setup_vao
};

View File

@@ -18,20 +18,13 @@ struct _GskGpuConicGradientOp
};
static void
gsk_gpu_conic_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_conic_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuConicgradientInstance *instance;
GskGpuConicgradientInstance *instance = (GskGpuConicgradientInstance *) instance_;
instance = (GskGpuConicgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "conic-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuConicGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_conic_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_conicgradient_info,
#endif
gsk_gpu_conic_gradient_op_print_instance,
gsk_gpu_conicgradient_setup_attrib_locations,
gsk_gpu_conicgradient_setup_vao
};

View File

@@ -16,23 +16,16 @@ struct _GskGpuCrossFadeOp
};
static void
gsk_gpu_cross_fade_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_cross_fade_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuCrossfadeInstance *instance;
GskGpuCrossfadeInstance *instance = (GskGpuCrossfadeInstance *) instance_;
instance = (GskGpuCrossfadeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "cross-fade");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->start_id);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->end_id);
g_string_append_printf (string, "%g%%", 100 * instance->opacity_progress[1]);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
@@ -40,7 +33,7 @@ static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuCrossFadeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_cross_fade_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -51,6 +44,7 @@ static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_crossfade_info,
#endif
gsk_gpu_cross_fade_op_print_instance,
gsk_gpu_crossfade_setup_attrib_locations,
gsk_gpu_crossfade_setup_vao
};

View File

@@ -11,6 +11,7 @@
#include "gdk/gdkprofilerprivate.h"
#include "gsk/gskdebugprivate.h"
#include "gsk/gskprivate.h"
#define MAX_SLICES_PER_ATLAS 64
@@ -905,6 +906,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
GskGpuImage *image;
gsize atlas_x, atlas_y, padding;
float subpixel_x, subpixel_y;
PangoFont *scaled_font;
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
if (cache)
@@ -916,13 +918,20 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
return cache->image;
}
/* Note: we want to scale the font to the required size *and* ensure that
* metrics hinting is off. The latter is necessary since pango lets metrics
* hinting influence the rendering of hexboxes, and we get bad outcomes if
* that happens.
*/
scaled_font = gsk_reload_font (font, scale, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_STYLE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT);
subpixel_x = (flags & 3) / 4.f;
subpixel_y = ((flags >> 2) & 3) / 4.f;
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
origin.x = floor (ink_rect.x * scale / PANGO_SCALE + subpixel_x);
origin.y = floor (ink_rect.y * scale / PANGO_SCALE + subpixel_y);
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * scale / PANGO_SCALE + subpixel_x) - origin.x;
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * scale / PANGO_SCALE + subpixel_y) - origin.y;
pango_font_get_glyph_extents (scaled_font, glyph, &ink_rect, NULL);
origin.x = floor (ink_rect.x * 1.0 / PANGO_SCALE + subpixel_x);
origin.y = floor (ink_rect.y * 1.0 / PANGO_SCALE + subpixel_y);
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * 1.0 / PANGO_SCALE + subpixel_x) - origin.x;
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * 1.0 / PANGO_SCALE + subpixel_y) - origin.y;
padding = 1;
image = gsk_gpu_device_add_atlas_image (self,
@@ -956,7 +965,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
gsk_gpu_upload_glyph_op (frame,
cache->image,
font,
scaled_font,
glyph,
&(cairo_rectangle_int_t) {
.x = rect.origin.x - padding,
@@ -964,7 +973,6 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
.width = rect.size.width + 2 * padding,
.height = rect.size.height + 2 * padding,
},
scale,
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
cache->origin.y + padding));
@@ -973,6 +981,9 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
*out_bounds = cache->bounds;
*out_origin = cache->origin;
g_object_unref (scaled_font);
return cache->image;
}

View File

@@ -126,7 +126,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
bytes,
stride);
g_bytes_unref (bytes);
gsk_gpu_buffer_unmap (self->buffer);
gsk_gpu_buffer_unmap (self->buffer, 0);
}
static GskGpuOp *
@@ -272,7 +272,7 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
data->context = g_object_ref (context);
data->texture_id = gsk_gl_image_steal_texture (GSK_GL_IMAGE (self->image));
if (gdk_gl_context_has_sync (context))
if (gdk_gl_context_has_feature (context, GDK_GL_FEATURE_SYNC))
data->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
builder = gdk_gl_texture_builder_new ();

View File

@@ -40,6 +40,7 @@ struct _GskGpuFramePrivate
GskGpuOps ops;
GskGpuOp *first_op;
GskGpuOp *last_op;
GskGpuBuffer *vertex_buffer;
guchar *vertex_buffer_data;
@@ -70,6 +71,8 @@ gsk_gpu_frame_default_cleanup (GskGpuFrame *self)
gsk_gpu_op_finish (op);
}
gsk_gpu_ops_set_size (&priv->ops, 0);
priv->last_op = NULL;
}
static void
@@ -248,27 +251,35 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
SortData *sort_data)
{
SortData subpasses = { { NULL, NULL }, { NULL, NULL } };
SortData pass = { { NULL, NULL }, { NULL, NULL } };
if (op->op_class->stage == GSK_GPU_STAGE_BEGIN_PASS)
{
pass.command.first = op;
pass.command.last = op;
op = op->next;
}
while (op)
{
switch (op->op_class->stage)
{
case GSK_GPU_STAGE_UPLOAD:
if (sort_data->upload.first == NULL)
sort_data->upload.first = op;
if (pass.upload.first == NULL)
pass.upload.first = op;
else
sort_data->upload.last->next = op;
sort_data->upload.last = op;
pass.upload.last->next = op;
pass.upload.last = op;
op = op->next;
break;
case GSK_GPU_STAGE_COMMAND:
case GSK_GPU_STAGE_SHADER:
if (sort_data->command.first == NULL)
sort_data->command.first = op;
if (pass.command.first == NULL)
pass.command.first = op;
else
sort_data->command.last->next = op;
sort_data->command.last = op;
pass.command.last->next = op;
pass.command.last = op;
op = op->next;
break;
@@ -282,19 +293,13 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
break;
case GSK_GPU_STAGE_BEGIN_PASS:
if (subpasses.command.first == NULL)
subpasses.command.first = op;
else
subpasses.command.last->next = op;
subpasses.command.last = op;
/* append subpass to existing subpasses */
op = gsk_gpu_frame_sort_render_pass (self, op->next, &subpasses);
op = gsk_gpu_frame_sort_render_pass (self, op, &subpasses);
break;
case GSK_GPU_STAGE_END_PASS:
sort_data->command.last->next = op;
sort_data->command.last = op;
pass.command.last->next = op;
pass.command.last = op;
op = op->next;
goto out;
@@ -305,22 +310,38 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
}
out:
/* prepend subpasses to the current pass */
/* append to the sort data, first the subpasses, then the current pass */
if (subpasses.upload.first)
{
if (sort_data->upload.first != NULL)
subpasses.upload.last->next = sort_data->upload.first;
sort_data->upload.last->next = subpasses.upload.first;
else
sort_data->upload.last = subpasses.upload.last;
sort_data->upload.first = subpasses.upload.first;
sort_data->upload.first = subpasses.upload.first;
sort_data->upload.last = subpasses.upload.last;
}
if (pass.upload.first)
{
if (sort_data->upload.first != NULL)
sort_data->upload.last->next = pass.upload.first;
else
sort_data->upload.first = pass.upload.first;
sort_data->upload.last = pass.upload.last;
}
if (subpasses.command.first)
{
if (sort_data->command.first != NULL)
subpasses.command.last->next = sort_data->command.first;
sort_data->command.last->next = subpasses.command.first;
else
sort_data->command.last = subpasses.command.last;
sort_data->command.first = subpasses.command.first;
sort_data->command.first = subpasses.command.first;
sort_data->command.last = subpasses.command.last;
}
if (pass.command.first)
{
if (sort_data->command.first != NULL)
sort_data->command.last->next = pass.command.first;
else
sort_data->command.first = pass.command.first;
sort_data->command.last = pass.command.last;
}
return op;
@@ -331,8 +352,13 @@ gsk_gpu_frame_sort_ops (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
SortData sort_data = { { NULL, }, };
gsk_gpu_frame_sort_render_pass (self, priv->first_op, &sort_data);
GskGpuOp *op;
op = priv->first_op;
while (op)
{
op = gsk_gpu_frame_sort_render_pass (self, op, &sort_data);
}
if (sort_data.upload.first)
{
@@ -343,6 +369,8 @@ gsk_gpu_frame_sort_ops (GskGpuFrame *self)
priv->first_op = sort_data.command.first;
if (sort_data.command.last)
sort_data.command.last->next = NULL;
priv->last_op = NULL;
}
gpointer
@@ -360,7 +388,17 @@ gsk_gpu_frame_alloc_op (GskGpuFrame *self,
NULL,
size);
return gsk_gpu_ops_index (&priv->ops, pos);
priv->last_op = (GskGpuOp *) gsk_gpu_ops_index (&priv->ops, pos);
return priv->last_op;
}
GskGpuOp *
gsk_gpu_frame_get_last_op (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
return priv->last_op;
}
GskGpuImage *
@@ -426,7 +464,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
if (priv->vertex_buffer_data)
{
memcpy (new_data, priv->vertex_buffer_data, old_size);
gsk_gpu_buffer_unmap (priv->vertex_buffer);
gsk_gpu_buffer_unmap (priv->vertex_buffer, old_size);
}
g_object_unref (priv->vertex_buffer);
priv->vertex_buffer = new_buffer;
@@ -434,7 +472,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
}
priv->vertex_buffer_used = size_needed;
return size_needed - size;
}
@@ -480,7 +518,7 @@ gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
{
g_assert (offset > 0);
gsk_gpu_buffer_unmap (priv->storage_buffer);
gsk_gpu_buffer_unmap (priv->storage_buffer, 0);
g_clear_object (&priv->storage_buffer);
priv->storage_buffer_data = 0;
priv->storage_buffer_used = 0;
@@ -505,6 +543,12 @@ gsk_gpu_frame_is_busy (GskGpuFrame *self)
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
}
void
gsk_gpu_frame_wait (GskGpuFrame *self)
{
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
}
static void
copy_texture (gpointer user_data,
GdkTexture *texture)
@@ -591,14 +635,14 @@ gsk_gpu_frame_submit (GskGpuFrame *self)
if (priv->vertex_buffer)
{
gsk_gpu_buffer_unmap (priv->vertex_buffer);
gsk_gpu_buffer_unmap (priv->vertex_buffer, priv->vertex_buffer_used);
priv->vertex_buffer_data = NULL;
priv->vertex_buffer_used = 0;
}
if (priv->storage_buffer_data)
{
gsk_gpu_buffer_unmap (priv->storage_buffer);
gsk_gpu_buffer_unmap (priv->storage_buffer, priv->storage_buffer_used);
priv->storage_buffer_data = NULL;
priv->storage_buffer_used = 0;
}

View File

@@ -24,6 +24,7 @@ struct _GskGpuFrameClass
GObjectClass parent_class;
gboolean (* is_busy) (GskGpuFrame *self);
void (* wait) (GskGpuFrame *self);
void (* setup) (GskGpuFrame *self);
void (* cleanup) (GskGpuFrame *self);
GskGpuImage * (* upload_texture) (GskGpuFrame *self,
@@ -69,6 +70,7 @@ GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuF
gsize *out_offset);
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);
void gsk_gpu_frame_wait (GskGpuFrame *self);
void gsk_gpu_frame_render (GskGpuFrame *self,
gint64 timestamp,
@@ -83,6 +85,7 @@ void gsk_gpu_frame_download_texture (GskGpuF
GdkMemoryFormat format,
guchar *data,
gsize stride);
GskGpuOp *gsk_gpu_frame_get_last_op (GskGpuFrame *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuFrame, g_object_unref)

View File

@@ -19,23 +19,15 @@ struct _GskGpuLinearGradientOp
};
static void
gsk_gpu_linear_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_linear_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuLineargradientInstance *instance;
instance = (GskGpuLineargradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
GskGpuLineargradientInstance *instance = (GskGpuLineargradientInstance *) instance_;
if (shader->variation & VARIATION_REPEATING)
gsk_gpu_print_op (string, indent, "repeating-linear-gradient");
else
gsk_gpu_print_op (string, indent, "linear-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_string (string, "repeating");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
@@ -43,7 +35,7 @@ static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuLinearGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_linear_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +46,7 @@ static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_lineargradient_info,
#endif
gsk_gpu_linear_gradient_op_print_instance,
gsk_gpu_lineargradient_setup_attrib_locations,
gsk_gpu_lineargradient_setup_vao
};

View File

@@ -16,22 +16,15 @@ struct _GskGpuMaskOp
};
static void
gsk_gpu_mask_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_mask_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuMaskInstance *instance;
GskGpuMaskInstance *instance = (GskGpuMaskInstance *) instance_;
instance = (GskGpuMaskInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "mask");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->source_id);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->mask_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuMaskOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_mask_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_mask_info,
#endif
gsk_gpu_mask_op_print_instance,
gsk_gpu_mask_setup_attrib_locations,
gsk_gpu_mask_setup_vao
};

View File

@@ -40,6 +40,7 @@
#include "gskroundedrectprivate.h"
#include "gskstrokeprivate.h"
#include "gsktransformprivate.h"
#include "gskprivate.h"
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdksubsurfaceprivate.h"
@@ -183,13 +184,13 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
{
float scale_x = viewport->size.width / width;
float scale_y = viewport->size.height / height;
gsk_gpu_clip_init_rect (&self->clip,
&GRAPHENE_RECT_INIT (
scale_x * clip->x,
scale_y * clip->y,
scale_x * clip->width,
scale_y * clip->height
));
gsk_gpu_clip_init_empty (&self->clip,
&GRAPHENE_RECT_INIT (
scale_x * clip->x,
scale_y * clip->y,
scale_x * clip->width,
scale_y * clip->height
));
}
self->modelview = NULL;
@@ -1327,7 +1328,7 @@ gsk_gpu_node_processor_add_node_clipped (GskGpuNodeProcessor *self,
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
return;
}
else if (self->clip.type == GSK_GPU_CLIP_RECT &&
else if ((self->clip.type == GSK_GPU_CLIP_RECT || self->clip.type == GSK_GPU_CLIP_CONTAINED) &&
gsk_rect_contains_rect (&self->clip.rect.bounds, &clip))
{
self->clip.type = GSK_GPU_CLIP_NONE;
@@ -1610,7 +1611,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
gsk_transform_unref (inverse);
gsk_gpu_clip_init_contained (&self->clip, &new_bounds);
gsk_gpu_clip_init_empty (&self->clip, &new_bounds);
}
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
{
@@ -1648,10 +1649,13 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
old_pixels = graphene_vec2_get_x (&old_scale) * graphene_vec2_get_y (&old_scale) *
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
new_pixels = scale_x * scale_y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
if (new_pixels > 2 * old_pixels)
old_pixels = MAX (graphene_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
graphene_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
new_pixels = MAX (scale_x * self->clip.rect.bounds.size.width,
scale_y * self->clip.rect.bounds.size.height);
/* Check that our offscreen doesn't get too big. 1.5 ~ sqrt(2) */
if (new_pixels > 1.5 * old_pixels)
{
float forced_downscale = 2 * old_pixels / new_pixels;
scale_x *= forced_downscale;
@@ -2055,7 +2059,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
guint32 descriptor;
gboolean need_mipmap, need_offscreen;
need_offscreen = self->modelview != NULL ||
need_offscreen = self->modelview != NULL ||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
if (need_offscreen)
{
@@ -2996,7 +3000,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
guint i, num_glyphs;
float scale, inv_scale;
GdkRGBA color;
gboolean glyph_align;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
GskGpuImage *last_image;
guint32 descriptor;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (self->opacity < 1.0 &&
gsk_text_node_has_color_glyphs (node))
@@ -3005,9 +3014,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
return;
}
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN) &&
gsk_transform_get_category (self->modelview) >= GSK_TRANSFORM_CATEGORY_2D;
device = gsk_gpu_frame_get_device (self->frame);
color = *gsk_text_node_get_color (node);
color.alpha *= self->opacity;
num_glyphs = gsk_text_node_get_num_glyphs (node);
@@ -3020,29 +3028,38 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
descriptor = 0;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset, glyph_origin;
guint32 descriptor;
GskGpuGlyphLookupFlags flags;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
if (glyph_align)
{
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
flags = ((int) glyph_origin.x & 3) |
(((int) glyph_origin.y & 3) << 2);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
}
else
{
flags = 0;
}
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
@@ -3053,11 +3070,23 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
&glyph_bounds,
&glyph_offset);
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x * inv_scale,
-glyph_bounds.origin.y * inv_scale,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale);
glyph_bounds = GRAPHENE_RECT_INIT (0,
0,
glyph_bounds.size.width * inv_scale,
glyph_bounds.size.height * inv_scale);
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
glyph_origin.y - glyph_offset.y * inv_scale);
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
if (image != last_image)
{
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
last_image = image;
}
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
@@ -3076,7 +3105,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
&glyph_tex_rect,
&color);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
}
@@ -3093,6 +3122,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
guint32 tex_id;
GskGpuImage *last_image;
graphene_point_t offset;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (gsk_text_node_has_color_glyphs (node))
return FALSE;
@@ -3112,18 +3145,43 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds;
graphene_point_t glyph_offset;
graphene_point_t glyph_offset, glyph_origin;
GskGpuGlyphLookupFlags flags;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
font,
glyphs[i].glyph,
0,
flags,
scale,
&glyph_bounds,
&glyph_offset);
@@ -3136,8 +3194,8 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
last_image = image;
}
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
glyph_origin.y - glyph_offset.y * inv_scale);
gsk_gpu_pattern_writer_append_uint (self, tex_id);
gsk_gpu_pattern_writer_append_rect (self,
@@ -3147,7 +3205,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
glyph_bounds.size.width * inv_scale,
glyph_bounds.size.height * inv_scale
),
&glyph_offset);
&glyph_origin);
gsk_gpu_pattern_writer_append_rect (self,
&GRAPHENE_RECT_INIT (
- glyph_bounds.origin.x * inv_scale,
@@ -3155,9 +3213,9 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale
),
&glyph_offset);
&glyph_origin);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
return TRUE;

View File

@@ -19,23 +19,15 @@ struct _GskGpuRadialGradientOp
};
static void
gsk_gpu_radial_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_radial_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuRadialgradientInstance *instance;
instance = (GskGpuRadialgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
GskGpuRadialgradientInstance *instance = (GskGpuRadialgradientInstance *) instance_;
if (shader->variation & VARIATION_REPEATING)
gsk_gpu_print_op (string, indent, "repeating-radial-gradient");
else
gsk_gpu_print_op (string, indent, "radial-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_string (string, "repeating");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
@@ -43,7 +35,7 @@ static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuRadialGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_radial_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +46,7 @@ static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_radialgradient_info,
#endif
gsk_gpu_radial_gradient_op_print_instance,
gsk_gpu_radialgradient_setup_attrib_locations,
gsk_gpu_radialgradient_setup_vao
};

View File

@@ -30,9 +30,6 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
};
typedef struct _GskGpuRendererPrivate GskGpuRendererPrivate;
@@ -167,24 +164,36 @@ static GskGpuFrame *
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
{
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
GskGpuFrame *earliest_frame = NULL;
gint64 earliest_time = G_MAXINT64;
guint i;
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
gint64 timestamp;
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, GSK_GPU_MAX_FRAMES);
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
if (timestamp < earliest_time)
{
earliest_time = timestamp;
earliest_frame = priv->frames[i];
}
}
g_assert (earliest_frame);
gsk_gpu_frame_wait (earliest_frame);
return earliest_frame;
}
static gboolean
@@ -218,31 +227,17 @@ gsk_gpu_renderer_unrealize (GskRenderer *renderer)
{
GskGpuRenderer *self = GSK_GPU_RENDERER (renderer);
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
gsize i, j;
gsize i;
gsk_gpu_renderer_make_current (self);
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0, j = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
break;
if (gsk_gpu_frame_is_busy (priv->frames[i]))
{
if (i > j)
{
priv->frames[j] = priv->frames[i];
priv->frames[i] = NULL;
}
j++;
continue;
}
g_clear_object (&priv->frames[i]);
}
if (j == 0)
if (priv->frames[i] == NULL)
break;
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, j);
if (gsk_gpu_frame_is_busy (priv->frames[i]))
gsk_gpu_frame_wait (priv->frames[i]);
g_clear_object (&priv->frames[i]);
}
g_clear_object (&priv->context);
@@ -458,7 +453,7 @@ gsk_gpu_renderer_class_init (GskGpuRendererClass *klass)
gsk_ensure_resources ();
klass->optimizations = -1;
klass->optimizations &= ~gdk_parse_debug_var ("GSK_GPU_SKIP",
klass->optimizations &= ~gdk_parse_debug_var ("GSK_GPU_DISABLE",
gsk_gpu_optimization_keys,
G_N_ELEMENTS (gsk_gpu_optimization_keys));
klass->get_scale = gsk_gpu_renderer_real_get_scale;

View File

@@ -35,9 +35,6 @@ struct _GskGpuRendererClass
void (* make_current) (GskGpuRenderer *self);
GskGpuImage * (* get_backbuffer) (GskGpuRenderer *self);
void (* wait) (GskGpuRenderer *self,
GskGpuFrame **frame,
gsize n_frames);
double (* get_scale) (GskGpuRenderer *self);
GdkDmabufFormats * (* get_dmabuf_formats) (GskGpuRenderer *self);

View File

@@ -17,21 +17,14 @@ struct _GskGpuRoundedColorOp
};
static void
gsk_gpu_rounded_color_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_rounded_color_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuRoundedcolorInstance *instance;
GskGpuRoundedcolorInstance *instance = (GskGpuRoundedcolorInstance *) instance_;
instance = (GskGpuRoundedcolorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "rounded-color");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuRoundedColorOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_rounded_color_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_roundedcolor_info,
#endif
gsk_gpu_rounded_color_op_print_instance,
gsk_gpu_roundedcolor_setup_attrib_locations,
gsk_gpu_roundedcolor_setup_vao
};

View File

@@ -3,6 +3,7 @@
#include "gskgpushaderopprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskgldescriptorsprivate.h"
#include "gskgldeviceprivate.h"
#include "gskglframeprivate.h"
@@ -12,6 +13,8 @@
#include "gskvulkandeviceprivate.h"
#endif
#include "gdkglcontextprivate.h"
/* maximum number of ops to merge into one call
* If this number is too high, the command may take too long
* causing the driver to kill us.
@@ -26,6 +29,36 @@ gsk_gpu_shader_op_finish (GskGpuOp *op)
g_clear_object (&self->desc);
}
void
gsk_gpu_shader_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
const GskGpuShaderOpClass *shader_class = (const GskGpuShaderOpClass *) op->op_class;
const char *shader_name;
guchar *instance;
gsize i;
if (g_str_has_prefix (shader_class->shader_name, "gskgpu"))
shader_name = shader_class->shader_name + 6;
else
shader_name = shader_class->shader_name;
instance = gsk_gpu_frame_get_vertex_data (frame, self->vertex_offset);
for (i = 0; i < self->n_ops; i++)
{
gsk_gpu_print_op (string, indent, shader_name);
gsk_gpu_print_shader_info (string, self->clip);
shader_class->print_instance (self,
instance + i * shader_class->vertex_size,
string);
gsk_gpu_print_newline (string);
}
}
#ifdef GDK_RENDERING_VULKAN
GskGpuOp *
gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
@@ -37,15 +70,15 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
GskVulkanDescriptors *desc;
GskGpuOp *next;
gsize i, n;
gsize i, n_ops, max_ops_per_draw;
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE) &&
gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING))
n = MAX_MERGE_OPS;
max_ops_per_draw = MAX_MERGE_OPS;
else
n = 1;
i = 1;
max_ops_per_draw = 1;
desc = GSK_VULKAN_DESCRIPTORS (self->desc);
if (desc && state->desc != desc)
{
@@ -53,7 +86,8 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
state->desc = desc;
}
for (next = op->next; next && i < n; next = next->next)
n_ops = self->n_ops;
for (next = op->next; next; next = next->next)
{
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
@@ -61,10 +95,10 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
next_shader->desc != self->desc ||
next_shader->variation != self->variation ||
next_shader->clip != self->clip ||
next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size)
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
break;
i++;
n_ops += next_shader->n_ops;
}
vkCmdBindPipeline (state->vk_command_buffer,
@@ -78,10 +112,13 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
state->vk_format,
state->vk_render_pass));
vkCmdDraw (state->vk_command_buffer,
6 * instance_scale, i,
0, self->vertex_offset / shader_op_class->vertex_size);
for (i = 0; i < n_ops; i += max_ops_per_draw)
{
vkCmdDraw (state->vk_command_buffer,
6 * instance_scale, MIN (max_ops_per_draw, n_ops - i),
0, self->vertex_offset / shader_op_class->vertex_size + i);
}
return next;
}
@@ -104,7 +141,7 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
GskGLDescriptors *desc;
GskGpuOp *next;
gsize i, n, n_external;
gsize i, n_ops, n_external, max_ops_per_draw;
desc = GSK_GL_DESCRIPTORS (self->desc);
if (desc)
@@ -135,11 +172,12 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
}
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE))
n = MAX_MERGE_OPS;
max_ops_per_draw = MAX_MERGE_OPS;
else
n = 1;
i = 1;
for (next = op->next; next && i < n; next = next->next)
max_ops_per_draw = 1;
n_ops = self->n_ops;
for (next = op->next; next; next = next->next)
{
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
@@ -147,28 +185,32 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
next_shader->desc != self->desc ||
next_shader->variation != self->variation ||
next_shader->clip != self->clip ||
next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size)
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
break;
i++;
n_ops += next_shader->n_ops;
}
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE))
for (i = 0; i < n_ops; i += max_ops_per_draw)
{
glDrawArraysInstancedBaseInstance (GL_TRIANGLES,
0,
6 * instance_scale,
i,
self->vertex_offset / shader_op_class->vertex_size);
}
else
{
shader_op_class->setup_vao (self->vertex_offset);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BASE_INSTANCE))
{
glDrawArraysInstancedBaseInstance (GL_TRIANGLES,
0,
6 * instance_scale,
MIN (max_ops_per_draw, n_ops - i),
self->vertex_offset / shader_op_class->vertex_size + i);
}
else
{
shader_op_class->setup_vao (self->vertex_offset + i * shader_op_class->vertex_size);
glDrawArraysInstanced (GL_TRIANGLES,
0,
6 * instance_scale,
i);
glDrawArraysInstanced (GL_TRIANGLES,
0,
6 * instance_scale,
MIN (max_ops_per_draw, n_ops - i));
}
}
return next;
@@ -182,7 +224,7 @@ gsk_gpu_shader_op_gl_command (GskGpuOp *op,
return gsk_gpu_shader_op_gl_command_n (op, frame, state, 1);
}
GskGpuShaderOp *
void
gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
const GskGpuShaderOpClass *op_class,
guint32 variation,
@@ -190,20 +232,39 @@ gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
GskGpuDescriptors *desc,
gpointer out_vertex_data)
{
GskGpuShaderOp *self;
GskGpuOp *last;
GskGpuShaderOp *last_shader;
gsize vertex_offset;
self = (GskGpuShaderOp *) gsk_gpu_op_alloc (frame, &op_class->parent_class);
vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
self->variation = variation;
self->clip = clip;
if (desc)
self->desc = g_object_ref (desc);
last = gsk_gpu_frame_get_last_op (frame);
/* careful: We're casting without checking, but the if() does the check */
last_shader = (GskGpuShaderOp *) last;
if (last &&
last->op_class == (const GskGpuOpClass *) op_class &&
last_shader->desc == desc &&
last_shader->variation == variation &&
last_shader->clip == clip &&
last_shader->vertex_offset + last_shader->n_ops * op_class->vertex_size == vertex_offset)
{
last_shader->n_ops++;
}
else
self->desc = NULL;
self->vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
{
GskGpuShaderOp *self;
self = (GskGpuShaderOp *) gsk_gpu_op_alloc (frame, &op_class->parent_class);
*((gpointer *) out_vertex_data) = gsk_gpu_frame_get_vertex_data (frame, self->vertex_offset);
self->variation = variation;
self->clip = clip;
self->vertex_offset = vertex_offset;
if (desc)
self->desc = g_object_ref (desc);
else
self->desc = NULL;
self->n_ops = 1;
}
return self;
*((gpointer *) out_vertex_data) = gsk_gpu_frame_get_vertex_data (frame, vertex_offset);
}

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