The only reason for separate files is Objective-C callbacks into Go,
or when the Go side is common, yet the Objective-C side differs from
macOS to iOS.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Both the OpenGL and the Direct3D API are stateful and gpu.GPU renders to
the render target current when Frame is called.
Modern GPU API such as Metal don't have a concept of a current render
target, and the target even changes each frame.
Add RenderTarget and add an explicit target argument to GPU.Frame as
well as the underlying driver.Device.BeginFrame.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This change avoids the hard dependency on GPU support for sRGB encoded
textures in the compute renderer.
With this change and the previously added CPU fallback, Gio no longer
rely on any GPU functionality outside the OpenGL ES 2.0 level.
Fixes gio#49
Fixes gio#154
Fixes gio#97
Fixes gio#36
Fixes gio#172
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The SRGBFBO emulates a framebuffer in the sRGB colorspace. However, some
low-end devices may not have EXT_sRGB support to store framebuffer content in
sRGB.
This change handles missing EXT_sRGB support by falling back to the linear RGB colorspace.
Falling back loses color precision but is better than failing.
Updates gio#49
Updates gio#154
Updates gio#97
Updates gio#36
Updates gio#172
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Icons are meant to be shared among multiple widgets, but their Color
state may end up with unexpected values after use. Replace the state
with and explicit argument to Layout.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This change adds a CPU fallback for devices that don't support the old
renderer nor have GPU support for compute programs.
Most of the hard work is implemented in the gioui.org/cpu module. It
uses the SwiftShader project with light modification to output
statically compiled CPU .o files for each compute program.
The CPU fallback only covers Linux and Android on arm, arm64, amd64
architectures. There is no fundamental reason support can't be extended
to other platforms:
- macOS and iOS are probably easy, but it's likely that virtually every
device has GPU support for compute shaders.
- Windows needs a Cgo-less port, or a build constraint to require a C
compiler (Gio core doesn't).
- FreeBSD and OpenBSD are probably also easy to do because they're so
similar to Linux.
- The 386 binaries didn't work properly in my tests, so fixes to
SwiftShader is probably needed. However, I expect virtually every
Intel device can run amd64 binaries.
Updates gio#49
Fixes gio#228
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The CPU fallback for the compute renderer is contained in a separate
module for space reasons, but the CPU binaries must exactly match the
compute programs. However, there is no way to express that constraint
in go.mod.
This change generates hashes of every compute program so that a
following change can verify the CPU binaries match the programs.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The hash of the clipping paths that affect drawing operations are computed
and used to quickly determine that two operations are not equal, the
most likely outcome of a comparison.
However, for paths that are constructed once and cached computing the
hash at every frame is wasteful. This is especially true for text, which
is both cached and also among the largest paths in a frame.
This change moves the hashing to op/clip.Path construction time, and
stores the hash in the ops list so it won't be re-computed at every use.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
To re-use previously cached layers, the compute renderer must know
whether two drawing operations are equal. In the case two operations are
not equal, a fast hash comparison will most likely fail. In the case two
equal operations with complicated clipping paths, the comparison of the
path data is expensive.
This change adds support for fast ops.Key comparisons, where two paths
are equal if their ops.Key are. This is an optimization that kicks in
for text rendering, where glyph clipping shapes are re-used across
frames.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
To re-use drawing operations common to two layers, every operation must
exactly match, including their transformations. However, layers that
differ only by an integer offset can be re-used because rendering does
not depend on the absolute integer offset. This is important in the very
common case of scrolling otherwise static UI content.
This change separate the integer offset from drawing operations and
relaxes the layer cache to match layers that differ only in integer
offsets.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The compute renderer is more expensive to run than the old renderer on
low-end GPUs, and even more so on CPUs. To ensure good performance
regardless of the end-user device, this change implements automatic
re-use of content rendered in the frame before the current.
The basic idea is that every drawing operation (PaintOp), along with its
transform and clipping, can be hashed and efficiently looked up. A naïve
caching approach is then to rasterize every operation to separate
sections of several large texture atlases, turning a cache hit into a
very cheap texture copy.
However, for scenes with lots of overlapping operations, the resulting
texture memory from separating the operations would be much larger than
the memory for just the window framebuffer.
So instead of caching individual operations, this change caches layers,
which are sequences of drawing operations. It starts by putting all
operations into a single layer. Then, if the subsequent frame re-uses a
sub-sequence of that larger layer, it is split.
For example, consider a UI similar to the kitchen sample:
Hello, Gio
<Editor>
<Line Editor>
<Button> <Button> <Button>
<ProgressBar>
<Checkbox> <Toggle>
In the first frame, all of the drawing operations comprising the UI will
be stored and cached in a single layer. In the second frame the
progress bar will have moved and the renderer splits the UI into three
layers: layer A for everything up to (but not including) the progress
bar, layer B with just the progress bar, and layer C for the rest. Note
that nothing has been re-used yet. In the third frame, the progress bar
moves again, and this time layer A and C can be copied from the cache
only the progress bar needs redrawing through the compute programs.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The performance difference is negligible, but is useful when the compute
pipeline can skip rendering to empty tiles.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Until now, the two renderers have shared structures and code for
decoding drawing ops and convert them to GPU-friendly structures.
However, the decoder is tailored to the old renderer and use
structures that poorly fits the new compute renderer.
This change copies the decoder and specializes the copy for the compute
renderer, avoiding a round-trip through the old renderer decoder.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The compute renderer doesn't run on Windows yet, but the d3d11 backend needs
the method to satisfy the driver interface.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Otherwise, making a context current on another thread may result in
an EGL_BAD_ACCESS error.
Fixes gio#248
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The CPU fallback renderer relies on posix_memalign, which was exposed in
Android 4.2. Support for Android 4.1 could be restored by writing
posix_memalign outselves, but this change is easier.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The transformation information in ops.Key is a layer violation.
Introduce a key type specific to package gpu and use that instead.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Releasing the renderer is fine, but releasing the underlying context
introduces flicker when restoring a Gio window on macOS.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit ensures that the dimensions returned by material.List
include the size of the scrollbar when the scrollbar is set to
the Occupy AnchorStrategy.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This change ensures that the scrollbar anchors to the proper edge of the
content even when the list was drawn with a zero minimum constraint.
Without this, the layout.Direction used to anchor the scrollbar will choose
to use the minimum size and anchor it to the opposite edge of the content.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
For some reason, commit d331f63d20 didn't
update the generated code for material.vert properly. The outdated
version is equivalent to the new, so I only discovered this discrepancy
while changing some other shader.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The scrollbar implementation prior to this change only adjusted
list.Position.Offset. This works in all circumstances except when
list.Position.BeforeEnd=false. If the position indicates that the
scroll position is at the end of the list, the offset is ignored.
This change ensures that manually dragging the scrollbar always
causes BeforeEnd to be set to true. If the drag ends with the
scrollbar at the end of the list, BeforeEnd will be set
automatically by the next list.Layout call, so this doesn't
prevent the list from optimizing for that case in general.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
To use these lists instead of layout.List, callers simply need to
change declarations of layout.List to widget.List, and to change
calls to layout.List.Layout to material.List(th,&list).Layout.
So this:
var list layout.List
list.Layout(gtx, 10, func(gtx C, index int) D {
return material.Body1(th, fmt.Sprintf("%d", index)).Layout(gtx)
})
Becomes:
var list widget.List
material.List(th, &list).Layout(gtx, 10, func(gtx C, index int) D {
return material.Body1(th, fmt.Sprintf("%d", index)).Layout(gtx)
})
Naturally, the material.ListStyle type supports tweaking the scrollbar's
appearance and behavior.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit adds a Length field to the
layout.Position. This field contains an approximation
of the overall length of the list's contents.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This is a breaking change as Icon.Layout no longer requests a size.
Before:
sz := unit.Dp(20)
ic.Layout(gtx, sz)
After:
sz := gtx.Metric.Px(unit.Dp(20))
gtx.Constraints.Min = image.Pt(sz, 0)
ic.Layout(gtx)
Fixes gio#240
Signed-off-by: pierre <pierre.curto@gmail.com>
This creates a floating-point analog to layout.Axis.Convert
for converting from (x,y) coordinate space to (main,cross)
coordinate space.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
The platform GPU context must be Refreshed on the window event thread,
but our rendering loop must not, because it may also want access to the
window event thread.
Fixes gio#236
Signed-off-by: Elias Naur <mail@eliasnaur.com>