Commit Graph

229 Commits

Author SHA1 Message Date
Elias Naur ae43d18ced internal/ops: remove unused TypePushTransform
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-09-07 14:48:11 -05:00
Dominik Honnef b4d93379c4 op: don't allocate for each string reference
When storing a string in an interface value that escapes, Go has to heap
allocate space for the string header, as interface values can only store
pointers. In text-heavy applications, this can lead to hundreds of
allocations per frame due to semantic.LabelOp, the primary user of
string-typed references in ops.

Instead of allocating each string header individually, provide a slice
of strings to store string-typed references in, and store pointers into
this slice as the actual references. This only allocates when resizing
the slice's backing array, and averages out to no allocations, as the
backing array gets reused between calls to Ops.Reset.

We introduce two new functions, Write1String and Write2String, which
make use of this new slice for their last argument. We could've
automated this in the existing Write1 and Write2 methods, but that would
require type assertions on each call, and the vast majority of ops do
not make use of strings.

Signed-off-by: Dominik Honnef <dominik@honnef.co>
2023-09-02 09:02:39 -06:00
Elias Naur cf5ae4aad9 internal/egl: call eglTerminate after context release
Without eglTerminate, using EGL will crash or report spurious errors after
creating and destroying enough contexts. The test program in #528
takes 5-10 window cycles before errors show up for me.

Fixes: https://todo.sr.ht/~eliasnaur/gio/528
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-08-23 13:31:31 -06:00
Chris Waldon babe7a292b app,internal/debug: define GIODEBUG env var
This commit defines an environment-variable-based debug mechanism allowing
users to toggle various debug features of their applications at runtime. The
only currently supported features are debug logging in the text stack and
suppressing the usage message that would otherwise be printed if you supplied
a malformed GIODEBUG value. The syntax is a comma-delimited list of features
right now. To see the usage, set the variable to the empty string (or any other
unsupported value):

$ GIODEBUG="" go run .

To suppress the usage message, use GIODEBUG=silent. This may be helpful for scripts
trying to activate debug features and inspect their output across versions of Gio
with different debug options available.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2023-07-19 09:54:27 +02:00
Egon Elbre e5fe3a0732 internal/stroke: optimize SplitCubic
│   sec/op    │   sec/op     vs base               │
SplitCubic/4-10    37.36n ± 0%   36.16n ± 0%  -3.21% (p=0.000 n=10)
SplitCubic/8-10    74.53n ± 0%   72.21n ± 0%  -3.12% (p=0.000 n=10)
SplitCubic/16-10   149.3n ± 1%   144.5n ± 0%  -3.22% (p=0.000 n=10)
SplitCubic/33-10   340.1n ± 0%   334.4n ± 0%  -1.65% (p=0.000 n=10)

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2023-06-27 12:36:14 +02:00
Egon Elbre 55404aec91 internal/stroke: add BenchmarkSplitCubic
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2023-06-27 12:34:40 +02:00
Egon Elbre 0edc00a721 internal/stroke: tiny optimization to approxCubeTo
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2023-06-27 12:34:32 +02: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
Egon Elbre bce4153640 internal/stroke: fix line overlap
When the line overlaps itself backtracking exactly, e.g.

   path.MoveTo(0, 100)
   path.LineTo(100, 0)
   path.LineTo(0, 100)

then acos calculation is relatively unstable. By using atan2 it avoids
some of such problems in the calculation. Additionally, it simpliflies
the round join calculation.

Fixes: https://todo.sr.ht/~eliasnaur/gio/474
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2023-02-06 12:01:52 -06: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
Elias Naur 80196f3c3e op: tolerate incomplete macros
Before this change, a macro not Stop'ed would result in an endless
loop during op decoding.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-10-04 17:11:35 -06:00
Inkeliz 83cb383523 app,internal/gl: [wasm] fix context lost
Before that change, Gio could crash when the WebGL context was lost
unexpectedly. Now, Gio will properly handle such situation and
recreate the buffers/resources when context is restored and will
wait until context is recovered.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2022-09-15 06:58:27 -06:00
Elias Naur 61b2e37691 all: format comments with go fmt ./... using Go 1.19
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-08-06 12:26:03 +02:00
Elias Naur 5326ca5fbe all: add support for macOS to flake.nix
The Nix version of the macOS toolchain has difficulties compiling
Objective-C modules; disable modules instead of figuring out why.
It also doesn't include any frameworks automatically; add them explicitly.

While here, move suppression of OpenGL deprecation to a GL-specific
file.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-08-01 01:33:21 +02:00
psydvl e711cbc004 internal/vk: fix wayland-client linking
Signed-off-by: psydvl <psydvl@fea.st>
2022-07-18 10:44:47 +02:00
Egon Elbre f8f68a4e9f internal/ops: optimize Decode
Using clean struct creation creates a lot of temporary variables in
assembly. Inline the assignments, which generates less code.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 20:12:41 +02:00
Egon Elbre 17f604fb50 internal/ops: use single table for OpType
Size and NumRefs are always used together, so consolidate info to
a single table to avoid two separate lookups.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 20:12:35 +02:00
Egon Elbre e7dd180447 internal/ops: avoid some bounds checks in decode
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 20:11:16 +02:00
Egon Elbre f8efc9c2a6 internal/ops: use lookup table for NumRefs
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 20:11:16 +02:00
Egon Elbre d3d2c51717 internal/ops: avoid bounds check in OpType.Size()
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 20:06:44 +02:00
Egon Elbre 3670f70c01 internal/f32color: optimize LinearFromSRGB
Previously each call was ~100ns, the new implementation is ~1ns.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-07-02 06:57:54 +02:00
Elias Naur dab796808a internal/gl: avoid excessive Cgo pointer checks
As suggested by Egon Elbre, passing a large struct of function pointers
forces Cgo checks on all of the pointer on every Cgo call. This
change instead passes only the relevant function pointer.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-06-27 11:08:19 +02:00
Elias Naur 3f38e67ce0 io/system: add ActionInputOp to register window move gesture areas
The app.Window.Perform(ActionMove) is the wrong abstraction for
initiating a move gesture: Windows needs to know the move gesture
area at pointer move, and macOS needs to know the pointer button
down event that triggers the move gesture. This change replaces
Perform(ActionMove) with a new system.ActionInputOp that marks an
area movable.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-06-25 19:40:46 +02:00
Elias Naur 916efb4612 all: apply suggestions from staticcheck.io
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-06-07 12:28:28 +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 3d37491342 all: [API] replace unit.Value with separate unit.Dp, unit.Sp types
The unit.Value is a struct and thus more inconvenient to use than its
underlying float32 type. In addition, most uses don't need a general
value, but rather a specific unit given by the context. This change
replaces unit.Value with two float32 units, Dp and Sp. It also changes
variables and parameters of unit.Value to a specific unit type matching
the context. That is, unit.Dp everywhere except for text sizes which are
in Sp.

Switching to typed float32s has multiple advantages

- They can be constants:

const touchSlop = unit.Dp(16)

- Casting untyped constants is no longer necessary:

insets := layout.UniformInset(16)

- Calculation with values is natural:

func (s ScrollbarStyle) Width() unit.Dp {
	return s.Indicator.MinorWidth + s.Track.MinorPadding + s.Track.MinorPadding
}

The main API change is that calls to gtx.Px must be replaced with either
gtx.Dp or gtx.Sp depending on the unit.

Idea by Christophe Meessen.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-05-31 10:24:09 +02:00
Elias Naur 380f96b3fc io/key: [API] implement key event propagation
Before this change, every Event would be passed to the focused InputOp
tag, making it impossible to implement, say, program-wide shortcuts.
This change implements key.Event routing similar to how pointer.Events
are routed: every InputOp describes the set of keys it can handle, and
the router use that information to deliver an Event to the matching
handler.

This is an API change, because every InputOp must now include a filter
matching the keys it wants to handle.

Fixes: https://todo.sr.ht/~eliasnaur/gio/395
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-14 19:09:00 +02:00
Egon Elbre 3fd231367f internal/stroke: optimize arc drawing
Arc with a small angle doesn't need many segments.

Updates: https://todo.sr.ht/~eliasnaur/gio/313
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-03-14 11:42:59 +01:00
Elias Naur 7785310e9d gpu/internal/vulkan,internal/vk: allocate descriptor sets in batches
We know exactly the configuration and number of sets in each pool, so
we may as well allocate them al up front.

References: https://todo.sr.ht/~eliasnaur/gio/375
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-11 20:34:49 +01:00
Elias Naur e8aa881d40 gpu/internal/vulkan: [Vulkan] replace Device/QueueWaitIdle with fences
vkDeviceWaitIdle and vkQueueWaitIdle are expensive; a vkFence is cheaper
and the usual way to ensure a previous frame has completed before starting
another.

References: https://todo.sr.ht/~eliasnaur/gio/375
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
Egon Elbre 4172566aad io/pointer: [API] make cursor name into a byte
Add most of the common cursors defined by different systems.

Normalize cursor names to match CSS.

This is API change: some cursor names have changed, and the
underlying type is no longer a string.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-03-01 14:04:21 +01:00
Elias Naur 50e35c9c3f widget/material: add focus and hover indicators to Clickable
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-28 17:28:13 +01:00
Elias Naur 2bea9a3736 internal/f32color: add support for light widgets to Hovered
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-28 13:20:33 +01:00
Elias Naur b74c9f9603 internal/f32color: extract color mixing into separate function
Refactor to enable Hovered for light widgets.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-28 13:13:14 +01:00
Inkeliz 182e701081 internal/gl: [js] replace Call to Bind/Invoke
Before that patch, the Call function was used to call each
JS function related to WebGL. The Call function contains
strings, which is slow on most browsers. Now, it uses
Bind on the initialization and re-use the same function,
avoiding the usage of strings.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2022-02-14 22:23:04 +00:00
Elias Naur 31f55232bf app,widget,io: implement IME positioning
This change implements reporting of the caret position from Editor, as well
as Windows, macOS, Android support. As a result, the IME composition window
on Windows and macOS is now positioned correctly.

References: https://todo.sr.ht/~eliasnaur/gio/246
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-13 20:09:06 +01:00
Andy Balholm 44c9fb7448 internal/stroke: don't draw round join if angle is NaN
References: https://todo.sr.ht/~eliasnaur/gio/331
Signed-off-by: Andy Balholm <andy@balholm.com>
2022-02-06 11:07:16 +01:00
Elias Naur 58cdb3e1da app,widget: implement Editor IME support, add Android implementation
Fixes: https://todo.sr.ht/~eliasnaur/gio/116
References: https://todo.sr.ht/~eliasnaur/gio/246
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-06 10:31:53 +01:00
Elias Naur 65199a2274 op,internal/ops: support CallOps without macros
A recorded macro is prefixed with an internal macro op that stores
the end of the macro. The end is used to efficiently skip the macro
when not calling it. The call a macro, the CallOp stores the start
position of the macro.

To support seamless wrapping of Ops lists, this change removes the
dependency on the macro op prefix from CallOp. Internal code can
now call an Ops like this:

    var ops op.Ops
    var wrapper op.Ops

    ops.AddCall(&wrapper.Internal, &ops.Internal, ops.PC{}, ops.PCFor(&ops.Internal))

References: https://todo.sr.ht/~eliasnaur/gio/318
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-01-20 09:56:30 +01:00
Pierre Curto 9a2fee1c0e op, internal/ops: cleanups
Remove unnecessary fill when starting a recording in op.Record.
Have the exact number of possible stack kinds in ops.Ops.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2022-01-18 15:49:43 +01:00
Pierre Curto 2ce9ad36af clip: check Path ops are not mixed with others
Multiple operations Op, such as clip.Path, cannot
be interleaved with other ops. This patch adds a
mechanism to ensure that is the case by starting
multi ops with ops.BeginMulti and ending them with
ops.EndMulti while operations are written to op.Ops
with ops.WriteMulti.
This mechanism is applied to clip.Path.

Fixes: https://todo.sr.ht/~eliasnaur/gio/336
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2022-01-15 19:16:07 +01:00
Elias Naur aadb6609ec internal/vk: [Android] add workaround for Vulkan on the emulator
According to the Vulkan specification the pApplicationInfo member of
the VkInstanceCreateInfo structure may be NULL. However, the Android
emulator crashes on vkEnumeratePhysicalDevices if set to NULL.
This change adds a minimal info to please the emulator.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-01-08 17:20:35 +01:00
Elias Naur 8d8aeef66b app,gpu,internal/egl: lock OS thread when making OpenGL context current
OpenGL stores the current context in thread-local memory, but commit
4f5baa9a51 removed a runtime.LockOSThread from app.Window that ensured
the goroutine that drives the context stays on the operating thread that
has the context current. This change restores the thread lock.

As a bonus, this change makes the OpenGL contexts responsible for locking
the thread at MakeCurrent, thereby removing LockOSThread calls from GPU
backend-agnostic code.

Fixes: https://todo.sr.ht/~eliasnaur/gio/334
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-01-05 11:49:29 +01:00
Andy Balholm 6d9db2b13c internal/stroke: properly calculate maxDist
The calculated value for maxDist (the maximum allowable error when
converting cubic Beziers to quadratics) was way too small when the
first control point was very close to the starting point of the segment.

(f32.Rectangle.Add does not expand the rectangle to include the new point;
it moves the rectangle by the point's X and Y coordinates.)

Splitting the curve into such small pieces was resulting in very ugly
output.

Fixes: https://todo.sr.ht/~eliasnaur/gio/331
Signed-off-by: Andy Balholm <andy@balholm.com>
2022-01-04 17:28:37 +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
Pierre Curto 03016f0c69 widget: add drag and drop support
This patch adds internal Drag and Drop support to app.Windows.

The new package io/transfer adds the ability to
define draggable and droppable targets, which
are leveraged by the new widget.Draggable type.

The API is generic and could handle future use
cases, such as external Drag and Drop.

Updates gio#153

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-12-07 12:45:53 +01:00
Elias Naur 8a90074d04 io/semantic: add package for adding semantic descriptions to UI components
Software such as screen readers require semantic descriptions of user
interfaces to effectively present and interact with them. Package
semantic, combined with the existing package clip provide the operations
for Gio programs to describe themselves.

This change implements the semantic package and the routing changes for
accessing semantic trees; follow-ups add semantic information to widgets
and implement mapping semantic tree to platform representations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-12-01 17:23:54 +01:00
Pierre Curto 74490b4dfc internal/stroke: separate more the circle special case in ArcTransform
Avoid calculations not relevant for a circle.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-26 22:31:23 +01:00