Backend.queryState sets GL_ACTIVE_TEXTURE to access texture bindings; this change
makes sure GL_ACTIVE_TEXTURE is restored.
Also, make sure GL state changes made in Backend.restoreState is reflected
in Backend.glstate. Backend.glstate is not used after restoreState, so this
is just for clarity.
This is an alternative to https://github.com/gioui/gio/pull/77.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
For some reason, the Android emulator OpenGL implementation needs the output
framebuffer current when eglSwapBuffers is called; otherwise sRGB emulation
breaks. We used to restore the default FBO explicitly, 9b5e9ae607
restored it implicitly through automatic state restoring, but 30ecf75a0f
broke that by only saving and restoring shared context state. This change
restores the explicit behaviour for non-shared contexts.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
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>
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>
The novulkan tag didn't completely disable the Vulkan backend, and
the backend wouldn't register on FreeBSD. This change fixes both
issues.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
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>
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>
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>
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>
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>
We're about to split state into a clip stack and a transform stack. The
intersect fields belongs to clip state.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
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>
Most Gio programs have exlusive access to their OpenGL contexts, where
saving and restoring of the GL state is not required.
This change applies to all OpenGL platforms, but matters most for WASM
where syscalls are slow.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Before this change, the sRGB emulation target would always be the
current framebuffer. Now it's the render target passed to BeginFrame.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
glGetUniformLocation can return -1 (not found) for uniforms that have
been optimized out during linking of a GPU program. This happens because
the default renderer compile multiple program from the same generic
template.
Updates gio#280
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
There are too many driver issues with ES 3.1 compute shaders. Most
devices support Vulkan but some, such as the Samsung J2, will fall back
to the CPU renderer.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
To use glCopyTexSubImage2D on the Samsung J2 it's not enough to
set GL_READ_FRAMEBUFFER. This change binds GL_FRAMEBUFFER, setting both
READ_FRAMEBUFFER and DRAW_FRAMEBUFFER, fixing the issue.
Setting only GL_READ_FRAMEBUFFER was also a genuine bug, because OpenGL
ES 2.0 doesn't support it.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
MemoryBarrier is meant to stand in for OpenGL ES 3.1's glMemoryBarrier.
However, it badly fits with the other backends: Metal and D3D11 have
automatic memory barriers, and Vulkan needs barriers for graphics as
well.
This change removes MemoryBarrier, and puts the burden on the backends.
The OpenGL backend simply adds a barrier between every compute dispatch.
This change only adds a single memory barrier compared to the manual
barriers before this change, which is unlikely to affect performance
much.. We can revisit the automatic barriers if they ever become a
performance problem.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
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>
Vulkan doesn't support it, so move vertex buffer updates outside render
passes. Splitting render passes is another approach, but not as
efficient.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
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>
Currently, we run kernel4.comp with whatever texture was
bound (or none) when there are no materials in the set of layers.
However, Vulkan require every image binding to a compute shader to be
non-null and valid. This change works around that limitation by binding
a small dummy texture when no materials are needed.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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>
GPU contexts can hold on to a significant amount of resources. Clean
them up immediately instead of at test cleanup.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Don't copy the padding when stride is larger than the width. Applies to
Texture.Upload and Framebuffer.ReadPixels.
Signed-off-by: Elias Naur <mail@eliasnaur.com>