ui/app/internal/gpu: implement OpenGL ES 2 float fbo fallbacks

Also applicable to WebGL.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-05-04 14:29:37 +02:00
parent d118bd5a88
commit f5fa968038
3 changed files with 46 additions and 10 deletions
+1
View File
@@ -35,6 +35,7 @@ const (
FRAMEBUFFER_BINDING = 0x8ca6 FRAMEBUFFER_BINDING = 0x8ca6
FRAMEBUFFER_COMPLETE = 0x8cd5 FRAMEBUFFER_COMPLETE = 0x8cd5
HALF_FLOAT = 0x140b HALF_FLOAT = 0x140b
HALF_FLOAT_OES = 0x8d61
GREATER = 0x204 GREATER = 0x204
LINEAR = 0x2601 LINEAR = 0x2601
LINK_STATUS = 0x8b82 LINK_STATUS = 0x8b82
+40 -6
View File
@@ -1,6 +1,7 @@
package gpu package gpu
import ( import (
"errors"
"strings" "strings"
"gioui.org/ui/app/internal/gl" "gioui.org/ui/app/internal/gl"
@@ -14,6 +15,17 @@ type context struct {
type caps struct { type caps struct {
EXT_disjoint_timer_query bool EXT_disjoint_timer_query bool
srgbMode srgbMode srgbMode srgbMode
// floatTriple holds the settings for floating point
// textures.
floatTriple textureTriple
}
// textureTriple holds the type settings for
// a TexImage2D call.
type textureTriple struct {
internalFormat int
format gl.Enum
typ gl.Enum
} }
type srgbMode uint8 type srgbMode uint8
@@ -33,20 +45,42 @@ func newContext(glctx gl.Context) (*context, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
srgbMode, err := srgbModeFor(ver, exts)
if err != nil {
return nil, err
}
floatTriple, err := floatTripleFor(ver, exts)
if err != nil {
return nil, err
}
ctx.caps = caps{ ctx.caps = caps{
EXT_disjoint_timer_query: strings.Contains(exts, "GL_EXT_disjoint_timer_query"), EXT_disjoint_timer_query: strings.Contains(exts, "GL_EXT_disjoint_timer_query"),
srgbMode: srgbModeFor(ver, exts), srgbMode: srgbMode,
floatTriple: floatTriple,
} }
return ctx, nil return ctx, nil
} }
func srgbModeFor(ver [2]int, exts string) srgbMode { func floatTripleFor(ver [2]int, exts string) (textureTriple, error) {
switch { switch {
case ver[0] >= 3: case ver[0] >= 3:
return srgbES3 return textureTriple{gl.R16F, gl.Enum(gl.RED), gl.Enum(gl.HALF_FLOAT)}, nil
case strings.Contains(exts, "EXT_sRGB"): case strings.Contains(exts, "GL_OES_texture_half_float"):
return srgbEXT return textureTriple{gl.RGBA, gl.Enum(gl.RGBA), gl.Enum(gl.HALF_FLOAT_OES)}, nil
case strings.Contains(exts, "GL_OES_texture_float"):
return textureTriple{gl.RGBA, gl.Enum(gl.RGBA), gl.Enum(gl.FLOAT)}, nil
default: default:
panic("neither OpenGL ES 3 nor EXT_sRGB is supported") return textureTriple{}, errors.New("floating point texture not supported")
}
}
func srgbModeFor(ver [2]int, exts string) (srgbMode, error) {
switch {
case ver[0] >= 3:
return srgbES3, nil
case strings.Contains(exts, "EXT_sRGB"):
return srgbEXT, nil
default:
return 0, errors.New("neither OpenGL ES 3 nor EXT_sRGB is supported")
} }
} }
+5 -4
View File
@@ -151,7 +151,7 @@ func newStenciler(ctx *context) *stenciler {
} }
} }
func (s *fboSet) resize(ctx *context, sizes []image.Point, internalFormat int, format, ty gl.Enum) { func (s *fboSet) resize(ctx *context, sizes []image.Point) {
// Add fbos. // Add fbos.
for i := len(s.fbos); i < len(sizes); i++ { for i := len(s.fbos); i < len(sizes); i++ {
tex := ctx.CreateTexture() tex := ctx.CreateTexture()
@@ -177,7 +177,8 @@ func (s *fboSet) resize(ctx *context, sizes []image.Point, internalFormat int, f
if resize { if resize {
f.size = sz f.size = sz
ctx.BindTexture(gl.TEXTURE_2D, f.tex) ctx.BindTexture(gl.TEXTURE_2D, f.tex)
ctx.TexImage2D(gl.TEXTURE_2D, 0, internalFormat, sz.X, sz.Y, format, ty, nil) tt := ctx.caps.floatTriple
ctx.TexImage2D(gl.TEXTURE_2D, 0, tt.internalFormat, sz.X, sz.Y, tt.format, tt.typ, nil)
ctx.BindFramebuffer(gl.FRAMEBUFFER, f.fbo) ctx.BindFramebuffer(gl.FRAMEBUFFER, f.fbo)
ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, f.tex, 0) ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, f.tex, 0)
} }
@@ -254,7 +255,7 @@ func (s *stenciler) beginIntersect(sizes []image.Point) {
// 8 bit coverage is enough, but OpenGL ES only supports single channel // 8 bit coverage is enough, but OpenGL ES only supports single channel
// floating point formats. Replace with GL_RGB+GL_UNSIGNED_BYTE if // floating point formats. Replace with GL_RGB+GL_UNSIGNED_BYTE if
// no floating point support is available. // no floating point support is available.
s.intersections.resize(s.ctx, sizes, gl.R16F, gl.RED, gl.HALF_FLOAT) s.intersections.resize(s.ctx, sizes)
s.ctx.ClearColor(1.0, 0.0, 0.0, 0.0) s.ctx.ClearColor(1.0, 0.0, 0.0, 0.0)
s.ctx.UseProgram(s.iprog) s.ctx.UseProgram(s.iprog)
} }
@@ -278,7 +279,7 @@ func (s *stenciler) begin(sizes []image.Point) {
s.ctx.BindTexture(gl.TEXTURE_2D, gl.Texture{}) s.ctx.BindTexture(gl.TEXTURE_2D, gl.Texture{})
s.ctx.ActiveTexture(gl.TEXTURE0) s.ctx.ActiveTexture(gl.TEXTURE0)
s.ctx.BlendFunc(gl.ONE, gl.ONE) s.ctx.BlendFunc(gl.ONE, gl.ONE)
s.fbos.resize(s.ctx, sizes, gl.R16F, gl.RED, gl.HALF_FLOAT) s.fbos.resize(s.ctx, sizes)
s.ctx.ClearColor(0.0, 0.0, 0.0, 0.0) s.ctx.ClearColor(0.0, 0.0, 0.0, 0.0)
s.ctx.BindTexture(gl.TEXTURE_2D, s.areaLUT) s.ctx.BindTexture(gl.TEXTURE_2D, s.areaLUT)
s.ctx.UseProgram(s.prog) s.ctx.UseProgram(s.prog)