159 Commits

Author SHA1 Message Date
Walter Werner SCHNEIDER 36a2fa37c7 gpu: replace f32.Point/Rectangle with image.Point/Rectangle
Signed-off-by: Walter Werner SCHNEIDER <contact@schnwalter.eu>
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2025-07-28 19:49:56 +02:00
Walter Werner SCHNEIDER bbb6d05f09 gpu: respect the offset fraction when clipping
Fixes: https://todo.sr.ht/~eliasnaur/gio/534
Signed-off-by: Walter Werner SCHNEIDER <contact@schnwalter.eu>
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2025-07-28 19:49:56 +02:00
Walter Werner SCHNEIDER 4e5a344cc2 f32: replace Affine2D{} with AffineId() for identity transformations
References: https://todo.sr.ht/~eliasnaur/gio/655
Signed-off-by: Walter Werner SCHNEIDER <contact@schnwalter.eu>
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2025-07-12 15:28:03 +02:00
Walter Werner SCHNEIDER d76b4272aa f32: replace Affine2D{} with AffineId() for identity transformations
Reduces ambiguity by introducing AffineId() for representing identity transformation matrices.

References: https://todo.sr.ht/~eliasnaur/gio/655
Signed-off-by: Walter Werner SCHNEIDER <contact@schnwalter.eu>
2025-07-09 13:35:03 +02:00
Admin f73287be87 all: clean up code, upgrade to modern Go
Signed-off-by: ddkwork
2025-05-05 19:46:39 +02:00
Elias Naur 77709d1771 gpu: don't store transformed rectangle paths under the same cache key
Fixes incorrect rendering of multiple transformed instances of a
rectangle.

Fixes: https://todo.sr.ht/~eliasnaur/gio/635
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2025-02-18 15:14:35 +00:00
Elias Naur ea456f42c7 gpu: remove compute renderer
The compute renderer is a failed experiment: a better port of the
Vello vector renderer exists[0] and the upcoming Go 1.24 release
no longer builds the gioui.org/cpu module because of #60725.

Remove it.

[0] https://github.com/dominikh/jello

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-11-26 08:59:36 +00:00
Elias Naur 98d3a2eb24 gpu: fix viewport arguments for opacity layers
Fixes: https://todo.sr.ht/~eliasnaur/gio/574
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-04-12 23:34:18 +02:00
Elias Naur 109226b7e9 gpu: ensure opacity layers are rendered with correct pixel formats
FBOs and window framebuffers generally have different pixel formats, and
so require separate pipeline configurations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-04-12 18:08:20 +02:00
Elias Naur 477bd5c744 gpu: remove unused parameter
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-04-12 17:20:23 +02:00
Elias Naur 3648bdc02a io/profile: [API] delete package
It was a design mistake to make profiling data available to programs.
Rather, profiling should either be a user-configurable debug overlay,
reported through runtime/trace, or both.

This change drops the io/profile package because we're about to overhaul
event routing.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-02-05 10:59:51 +00:00
Dominik Honnef fe2a164d30 gpu: rename resourceCache to textureCache and use concrete key
The only remaining use of the cache is mapping handles to textures.
Using a concrete type for the key avoids the allocation caused by convT.

If we need more caches again in the future we can copy the type, or make
it generic.

Instead of updating the benchmark, we removed it outright. It suffered
from several flaws:

- The amount of work for each iteration of b.N wasn't constant, because
  the same cache was reused, growing ever larger in size.

- It only tested the cost of insertions. The comment "half are the same
  and half updated" wasn't true, as calling 'put' with the same key twice
  would've resulted in a panic.

- It didn't simulate any particular workload or cache size, making the
  benchmark useless for comparing different cache implementations. The
  cost of insertions isn't particularly interesting.

Signed-off-by: Dominik Honnef <dominik@honnef.co>
2024-01-04 11:57:06 -06:00
Dominik Honnef 4eca2c7d26 gpu: remove unused cache parameters
Signed-off-by: Dominik Honnef <dominik@honnef.co>
2024-01-04 11:57:02 -06:00
Egon Elbre 5fa94ff67b op/paint: add nearest neighbor scaling
This adds support for nearest neighbor filtering,
which can be useful in quite a few scenarios.

  img := paint.NewImageOp(m)
  img.Filter = paint.FilterNearest
  img.Add(gtx.Ops)

Fixes: https://todo.sr.ht/~eliasnaur/gio/414
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2023-11-15 10:38:02 -06:00
Elias Naur 526db27c75 gpu: fix opacity layer rendering on OpenGL
Fixes: https://todo.sr.ht/~eliasnaur/gio/536
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-10-02 13:07:15 -05:00
Elias Naur ae3bd2a1e1 op/paint: add opacity operation
The new paint.PushOpacity allows for adjusting the opacity of a group
of drawing operations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-09-08 11:46:17 -05:00
Dominik Honnef b183774063 internal/stroke, gpu: reuse slice when splitting cubics
When building GPU vertices from paths, we call stroke.SplitCubic once
per OpCubic. Before this change, each call to stroke.SplitCubic would
allocate a slice, which we would only use to iterate over.

This allocation can be easily avoided by reusing the slice. We can
conveniently store it in gpu.quadSplitter.

In a real application that renders hundreds of paths with tens of
rounded rectangles per path, this saved roughly 4500 allocations (or 1
MB worth) per frame.

Signed-off-by: Dominik Honnef <dominik@honnef.co>
2023-06-19 16:19:07 +02:00
Elias Naur bebc73db37 gpu: implement automatic mipmaps for images
All GPU APIs except OpenGL ES 2 can generate mipmaps for textures.
This trades 33% more GPU memory use for improved rendering quality
and speed for downscaled images.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-10-22 16:47:00 -06:00
Egon Elbre 0777afb85f gpu: avoid bounds checks in decode
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-07 09:36:26 +02:00
Egon Elbre 9de13e37e9 f32: add Affine2D.Split
splitTransform func was creating multiple copies of f32.Affine2D
due to not having access to the internal and passing around non-pointer.

This makes splitTransform from ~8ns to .Split ~2ns.

It seems that the non-pointer receiver was ~0.6ns slower in this case.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 07:04:47 +02:00
Elias Naur b5f12c5f26 f32: [API] unexport Rectangle
There are no public API that uses f32.Rectangle anymore. Move Rectangle
to an internal package for internal use.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-05-31 10:24:09 +02:00
Elias Naur fc79ec5c94 layout: [API] remove FRect
We're about to unexport f32.Rectangle, this change removes the only
public API for it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-05-31 10:24:09 +02:00
Elias Naur 1f11a5a17b f32,gpu,op/clip: add f32.Rectangle method for converting to image.Rectangle
Creating an image.Rectangle from a f32.Rectangle is used by two packages in Gio
and about to be used for a third. Add a Round method to f32.Rectangle to avoid
duplicating the implementation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-30 22:20:27 +02:00
Elias Naur f19b16fecc gpu,app: don't call time.Now when not profiling
runtime.nanotime1 shows up in profiles on Android, so avoid calling
time.Now when we can.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-11 20:34:49 +01:00
Elias Naur fea2f888bb all: replace unsafe slice operations with unsafe.Slice
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-02 16:53:02 +01:00
Pierre Curto 11bb86166a op/clip: automatically close Path in Outlines
Unclosed path segments in Path will be automatically
closed by a line.

Fixes: https://todo.sr.ht/~eliasnaur/gio/320
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-12-21 10:13:20 +01:00
Elias Naur 0c7b0b1d0b gpu,gpu/headless: plug a resource leak when taking screenshots
Ever since commit 8ff654628, the headless implementation has used two
GPU backend (not renderer) instances, one for the renderer and one for
creating the offscreen texture to render into. This arrangment leaks
resources because the backends only clear temporary storage at
BeginFrame, which is not called when reading pixel data from renders.

This change adds an internal constructor, gpu.NewWithDevice, to allow
headless.Window to share its device with the renderer, fixing the leak.
It also makes the code simpler (took me a while to debug this issue); in
fact I'm surprised it even works.

This is not a great fix: it adds an exported yet internal constructor,
and the ownership transfer of the device is surprising enough to warrant
two comments.

Fixes gio#322

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-12-14 20:53:00 +01:00
Pierre Curto 9d05f35341 op/paint: fix subimage rendering by ImageOp
This change is a follow-up to bcf3ff77ff, fixing the two renderers to
properly render images with non-zero origins.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-11 10:13:26 +01:00
Pierre Curto 86c4947ccd gpu: remove unused field
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-10 21:20:00 +01:00
Pierre Curto dce453e130 gpu: remove redundant panics when handling ops
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-10 16:44:39 +01:00
Elias Naur 5ddd572a41 gpu: don't panic for nil op.Ops argument to GPU.Frame
Updates gio#306

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-10 15:24:22 +01:00
Elias Naur 1eab4b84a6 gpu,internal/ops: move gpu.clipOp to ops.ClipOp
We're about to use clip.Ops for pointer areas; this change makes the
decoding accessible from the router package.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-26 12:13:11 +02:00
Elias Naur e14e33b87e op/clip: remove Op.Add
The Add method was a compatibility stop-gap.

API change. Use clip.Op.Push and Pop the return value to explicitly mark
the region affected by the clip operation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-26 12:13:11 +02:00
Elias Naur aac53ad0b5 gpu: don't alias stroked paths with outline paths
The default renderer caches pre-processed paths for efficient re-use,
but failed to distinguish outline paths from stroke paths.

Fixes gio#294

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-20 10:07:22 +02:00
Elias Naur bd1ef92dc4 op/clip: remove complex stroke support
In a discussion with Raph Levien, the author of our compute renderer
implementation, it became clear to me that it's not at all certain that
complex strokes will ever be efficiently supported by a GPU renderer.

At the same time, the machinery for converting a complex stroke to a
GPU-friendly outline has a significant maintenance cost. Further, it is
surprising to users that complex strokes are significantly slower and
allocate memory.

This change removes support for complex strokes, leaving only
round-capped, round-joined strokes supported by the compute renderer.
The default renderer still converts all strokes to outline, but it also
caches the result.

This is an API change. The complex stroke conversion code has been moved
to the external gioui.org/x/stroke package, with a similar API.

Updats gio#282 (Inkeliz brought up the allocation issue)

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 18:10:47 +02:00
Elias Naur 391725b9d0 op: move Ops internal methods and state to internal package ops
Merge package opconsts into ops as well; it only existed to break
import cycles.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Elias Naur 936c266b03 all: [API] split operation stack into per-state stacks
The op.Save and Load methods exist to support the need for
transformation, clip, pointer area state to behave as stacks. For
example, layout needs to apply an offset to its children but not
subsequent operations.

Before this change, op.Save and Load were used to save and restore the
state:

    ops := new(op.Ops)
    // Save state.
    state := op.Save(ops)
    // Apply offset.
    op.Offset(...).Add(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    state.Load()

A drawback with the op.Save mechanism is that there is no direct
connection between the state change and the saving and loading of state.
This causes confusion as to when a Save/Load is needed and who is
responsible for performing them, which leads to subtle bugs and over-use
of Save/Loads.

This change gets rid of the general state stack and replaces it with
per-state stacks. There is now a stack for transformation, clip, pointer
areas, and they can only be restored by the code pushing state to them.
The example above now becomes:

    ops := new(op.Ops)
    // Push offset to the transformation stack.
    stack := op.Offset(...).Push(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    stack.Pop()

For convenience, transformation also be Add'ed if the stack operation is
not required.

Simple state such as the current material no longer has a way to be
restored; it is assumed the client of a PaintOp adds their desired
material operation before it.

API change: replace op.Save/Load with explicit Push/Pop scopes for
op.TransformOps, pointer.AreaOps, clip.Ops.

To ease porting, this change retains a version of op.Save/Load that
saves and restores the transformation and clip stacks. It also retains
an Add method for clip.Op.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Elias Naur 8ebea5ad1f gpu: move drawState.clip to pathOp
The clip field tracks the intersection of the clip stack, and belongs in
the clip stack entries. This is a refactor that makes it easier to
implement scoped clip operations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 15:01:06 +02:00
Elias Naur a96c68fed1 gpu: move drawState.rect to pathOp
The rect field tracks whether the clip stack can be represented by a
pixel-aligned rectangle. It is easier to track as part of pathOp instead
of the global drawState.

Remove an obsolete comment while here.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 15:00:55 +02:00
Elias Naur 8999747ad2 app,gpu,internal/vk: add Vulkan port for Wayland, X11, Android
This change implements a Vulkan port for the two renderers, old and
compute. Run with GIORENDERER=forcecompute to test the compute renderer.

To shake out bugs faster, it is also made the default on systems that
support it. To disable Vulkan and force the use of OpenGL, use the
`novulkan` tag:

$ go run -tags novulkan gioui.org/example/kitchen

Don't forget to file an issue describing the issue that prompted the use
of the tag.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 18:40:05 +02:00
Elias Naur 0bdd24c51e gpu: fold driver.Framebuffer functionality into driver.Texture
driver.Device.NewFramebuffer doesn't provide additional information over
driver.Device.NewTexture, so Texture can hold its (optional) framebuffer
on behalf of the renderers. Metal don't even need a separate framebuffer
object.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:58 +02:00
Elias Naur b599a6d1c5 gpu: introduce driver.Device.PrepareTexture and use it in renderers
Vulkan textures (VkImage) are always in a particular layout, where each
layout is optimized for a particular use (transfer, sampling, compute
storage). Vulkan allows layout transitions everywhere except inside
render passes. This change adds driver.Device.PrepareTexture for
instructing the driver to switch a texture to a layout for sampling
in preparation for using it in a render pass.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:36 +02:00
Elias Naur 21ca9d13a8 gpu: switch from uniform buffers to combined push buffers
Vulkan doesn't support changing uniforms during a render pass. However,
push constants *can* be changed. The gio-shader repository was changed
to use push constants instead of uniforms, this change implements the
corresponding driver and renderer change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:02 +02:00
Elias Naur 3d1e9b0856 gpu: rename DrawMode to Topology and move it to pipeline descriptors
Vulkan needs the topology stated in its pipeline descriptor, not at
draw time.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur cc2edbaa51 gpu: introduce render passes
Modern GPU API such as Metal and Vulkan use explicit render passes
and command buffers for recording rendering commands. They don't have
global state; each render pass starts with a clean set of bound
textures, pipeline etc.

Change our GPU abstraction to better match newer API and modify our two
renderers to explicitly describe their render passes.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur 1d7ed55c29 gpu: support rectangular atlas packers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 07:48:26 +02:00
Elias Naur 414be0a0b3 gpu: Merge GPU.Collect and GPU.Frame
There's no meaningful reason to have them separate. The intention was to
enable rendering concurrent with other processing, but that's gaining
framerate at the expense of input latency and complicating ImageOp
semantics.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-24 08:30:52 +02:00
Elias Naur 0f81bf02c1 gpu: don't invoke GPU backend outside BeginFrame/EndFrame
The Metal backend is particularly sensitive because its staging buffers
are synchronized to BeginFrame.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-23 17:47:14 +02:00
Elias Naur d80992fc66 go.*,gpu: don't (badly) re-implement Go module versioning
Changes to the gioui.org/shader module are generally breaking changes,
which means that a particular version of gioui.org must be build with a
particular version of gioui.org/shader. Until now, the gpu package
checked the module version against an expected version and would fail at
runtime if there's a mismatch.

This change replaces all that complexity with a simple procedural
change: bump the module major version of gioui.org/shader at each such
incompatible change. It doesn't matter that we'll eventually reach
gioui.org/v1234/shader; the module is internal and won't break clients.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-22 09:18:41 +02:00
Elias Naur 44adf01768 go.*,gpu: update gioui.org/shader version
Pulls in a compatiblity fix for OpenGL ES 2.0 devices.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 10:04:56 +02:00