Commit Graph

45 Commits

Author SHA1 Message Date
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
Elias Naur 3ca4c98596 gpu/headless: tweak test to pass on MacBook Pro M1
Apparently, there is a rounding error somewhere in the pipeline
from clearing a FBO to downloading its contents on at least one Apple
M1 machine. Tweak the test colors a bit to make it pass.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-06-23 19:14:53 +02:00
Elias Naur 48a8540a68 all: [API] change clip.RRect and UniformRRect to take integer coordinates
Like the change to op.Offset before this, clip.RRect and UniformRRect
is usually used with integer coordinates. Change to integer coordinates
to eliminate many useless conversions to float32.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-05-31 10:24:09 +02:00
Elias Naur 6e66203881 gpu/headless: return error if NewTexture fails
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-13 12:58:33 +02: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
Pierre Curto af63c089f6 gpu/headless: make Screenshot take an input image to tranfer into
When extracting headless.Window's content via screenshots,
it can be useful to keep reusing the same image for output,
as well as specify which area of the Window is to be
extracted.
The updated Screenshot method does this by using the supplied
image.

API change: users must pass an existing image to Window.Screenshot.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-12-15 16:05:19 +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
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 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 bdafb3564f gpu,app: [Metal] don't store CFTypeRef values in pointer types
CFTypeRefs may not always contain valid pointers, so they must not be
stored in pointer types lest the Go runtime treats them as such.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-23 15:32:58 +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 3a98f004f9 gpu/internal/opengl: reduce number of glsl shader variants
With the use of uniform buffers gone, we don't need the glsl 3.00 es
variant any longer.

We only support desktop OpenGL on macOS which is guaranteed to be
at least version 3.2, so we don't need the glsl 1.30 variant either.

Remove a test that depended on gl_VertexID which is not support in glsl
1.00 es.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:47:11 +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 78b6268f9b gpu/headless: plug resource leaks in tests
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 13:26:43 +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 3b2992c37e gpu,app/internal/wm: add Metal port
The OpenGL (ES) implementations on Apple platforms are deprecated and
don't support GPU compute programs. This change adds support for the
replacement, the Metal GPU API.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 58cc817e5f gpu,gpu/internal: move vertex buffer stride to pipeline state
Metal needs the vertex stride at pipeline creation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 1af910959b gpu: fold buffer clearing into framebuffer bind
In Metal, clearing a framebuffer is most efficiently done during bind.
Modify our driver accordingly.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur d38c78d7ac gpu,gpu/internal: move InputDesc back from gioui.org/shader module
It was moved to gioui.org/shader by mistake.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur afaa31eca8 gpu: introduce pipeline abstraction
Modern API such as Metal and Vulkan want clients to compile expensive
state changes into pipeline objects. Change our GPU driver abstraction
to match, thereby paving the way for future drivers.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 6b537f0d4e gpu/headless: remove useless framebuffer bind
GPU.Frame now takes an explicit RenderTarget and it is no longer
necessary to bind the target.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-16 15:47:23 +02:00
Elias Naur 6c3711d95a gpu/headless: remove useless headless_gl.go abstraction
There is no longer any shared code between OpenGL backends (unlike
EGL backends).

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-16 15:47:23 +02:00
Elias Naur 6aee543234 all: switch to external shaders in the gioui.org/shaders module
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-08 13:47:41 +01:00
Elias Naur 18b4442393 all: remove Z buffer support
It is no longer needed by any rendering backend.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-08 13:47:37 +01:00
Elias Naur 2059862416 all: merge .m files with their .go counterparts
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>
2021-08-08 13:46:16 +01:00
Elias Naur 7d84e419c9 gpu,gpu/headless,app/internal/wm: add explicit RenderTarget API
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>
2021-08-08 13:45:23 +01:00
Elias Naur b3a8c24334 gpu/internal/driver: rename TextureFormatSRGB to TextureFormatSRGBA
The format implies an alpha channel; name it accordingly.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-29 08:37:18 +02:00
Elias Naur 060ae1cdf9 all: add //go:build lines
They're automatically added by Go 1.17 source formatters. This change
adds them all now.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-26 15:17:51 +02:00
Elias Naur 200957f924 gpu/headless: remove macOS context preparation no longer necessary
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-11 09:48:25 +02:00
Elias Naur 39775f555a gp/internal/opengl: support sRGB emulation for embedded content
Programs such as gio-example/glfw rely on Gio drawing blending with
the framebuffer background. This change makes it so when sRGB emulation
is active.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-16 18:17:00 +02:00
Elias Naur 21c319ace5 gpu/internal/opengl,internal: move sRGB emulation to OpenGL driver
There is only one driver but several backends (EGL, WebGL).

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-16 10:44:45 +02:00
Elias Naur 2c07b2dc0e headless: clear background to transparent, not white
The clear background is the most useful, and the old behaviour can
be achieved by filling the entire viewport with a white paint.ColorOp.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-03 11:31:45 +02:00
Elias Naur 23e0c898ef gpu/internal/driver: use strings for generated DXIL assembly
Literal strings are a more compact than literal byte slices. A future
change will switch to go:embed to save even more space.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00
Elias Naur fbee13a07d gpu/internal/convertshaders,gpu: represent converted shaders with raw literals
Raw strings with linebreaks are easier to read and produce smaller
diffs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:43:46 +02:00
Elias Naur 2328ddfeca internal/byteslice: rename package unsafe
All functions left in the old package unsafe were provided byte slice
views of other types. Rename the package accordingly and avoid a name
clash with the standard library package unsafe.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-11 11:27:02 +01:00
Elias Naur 57750fc8a0 gpu/headless,gpu/internal: rename "backend" files and names to "driver"
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-08 18:20:11 +01:00
Elias Naur 69cff4b96b gpu/internal/driver,gpu/headless: don't y-axis flip OpenGL ReadPixels images
The CPU fallback of the compute renderer needs ReadPixels data in OpenGL
format (origin at bottom left). Unfortunately, the OpenGL driver
automatically mirrors images in the Y-axis to match the top left origin
image.RGBA.

Remove the mirroring from the driver and introduce a DownloadImage to
restore the old behaviour.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-08 18:12:33 +01:00
Elias Naur 26d9e7fe5f gpu/headless: rename "backend" to "dev"
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:27:44 +01:00
Elias Naur 7bc0603d7e internal/gl: rename internal/glimpl
Now that the OpenGL driver package is named "opengl", we can finally get
rid of the ugly "glimpl" name.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:27:44 +01:00
Elias Naur c799452c57 gpu/internal/driver: rename gpu/backend
There are no longer any importers of package backend outside of
gioui.org/gpu. Move it internally, and rename it to the slightly more
specific "driver" while we're at it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:27:34 +01:00
Elias Naur 2c7aba9e7c gpu/internal/convertshaders: move internal/cmd/convertshaders
The convert program is only used by the shaders from package gpu, and
we're about to make the backend package imported by the program internal
to package gpu. Move the converter below package gpu.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:26:47 +01:00
Elias Naur 2a66bfb2b4 gpu/headless: move package app/headless
Package headless is more about rendering that windows. Move it
accordingly.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:26:47 +01:00