From f5fa968038cc43f42c8359896144df2d1a2d7f5b Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 4 May 2019 14:29:37 +0200 Subject: [PATCH] ui/app/internal/gpu: implement OpenGL ES 2 float fbo fallbacks Also applicable to WebGL. Signed-off-by: Elias Naur --- ui/app/internal/gl/gl.go | 1 + ui/app/internal/gpu/context.go | 46 +++++++++++++++++++++++++++++----- ui/app/internal/gpu/path.go | 9 ++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/ui/app/internal/gl/gl.go b/ui/app/internal/gl/gl.go index 72b37af2..25d3213a 100644 --- a/ui/app/internal/gl/gl.go +++ b/ui/app/internal/gl/gl.go @@ -35,6 +35,7 @@ const ( FRAMEBUFFER_BINDING = 0x8ca6 FRAMEBUFFER_COMPLETE = 0x8cd5 HALF_FLOAT = 0x140b + HALF_FLOAT_OES = 0x8d61 GREATER = 0x204 LINEAR = 0x2601 LINK_STATUS = 0x8b82 diff --git a/ui/app/internal/gpu/context.go b/ui/app/internal/gpu/context.go index 91cad11f..e3cf0cb9 100644 --- a/ui/app/internal/gpu/context.go +++ b/ui/app/internal/gpu/context.go @@ -1,6 +1,7 @@ package gpu import ( + "errors" "strings" "gioui.org/ui/app/internal/gl" @@ -14,6 +15,17 @@ type context struct { type caps struct { EXT_disjoint_timer_query bool 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 @@ -33,20 +45,42 @@ func newContext(glctx gl.Context) (*context, error) { if err != nil { 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{ EXT_disjoint_timer_query: strings.Contains(exts, "GL_EXT_disjoint_timer_query"), - srgbMode: srgbModeFor(ver, exts), + srgbMode: srgbMode, + floatTriple: floatTriple, } return ctx, nil } -func srgbModeFor(ver [2]int, exts string) srgbMode { +func floatTripleFor(ver [2]int, exts string) (textureTriple, error) { switch { case ver[0] >= 3: - return srgbES3 - case strings.Contains(exts, "EXT_sRGB"): - return srgbEXT + return textureTriple{gl.R16F, gl.Enum(gl.RED), gl.Enum(gl.HALF_FLOAT)}, nil + case strings.Contains(exts, "GL_OES_texture_half_float"): + 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: - 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") } } diff --git a/ui/app/internal/gpu/path.go b/ui/app/internal/gpu/path.go index f3030855..3450cece 100644 --- a/ui/app/internal/gpu/path.go +++ b/ui/app/internal/gpu/path.go @@ -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. for i := len(s.fbos); i < len(sizes); i++ { tex := ctx.CreateTexture() @@ -177,7 +177,8 @@ func (s *fboSet) resize(ctx *context, sizes []image.Point, internalFormat int, f if resize { f.size = sz 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.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 // floating point formats. Replace with GL_RGB+GL_UNSIGNED_BYTE if // 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.UseProgram(s.iprog) } @@ -278,7 +279,7 @@ func (s *stenciler) begin(sizes []image.Point) { s.ctx.BindTexture(gl.TEXTURE_2D, gl.Texture{}) s.ctx.ActiveTexture(gl.TEXTURE0) 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.BindTexture(gl.TEXTURE_2D, s.areaLUT) s.ctx.UseProgram(s.prog)