diff --git a/app/headless/headless.go b/app/headless/headless.go index 10755226..8ad772dd 100644 --- a/app/headless/headless.go +++ b/app/headless/headless.go @@ -9,6 +9,8 @@ import ( "image" "runtime" + "gioui.org/app/internal/glimpl" + "gioui.org/app/internal/srgb" "gioui.org/gpu" "gioui.org/gpu/gl" "gioui.org/op" @@ -18,12 +20,12 @@ import ( type Window struct { size image.Point ctx context - fbo *gl.SRGBFBO + fbo *srgb.SRGBFBO gpu *gpu.GPU } type context interface { - Functions() gl.Functions + Functions() *glimpl.Functions MakeCurrent() error ReleaseCurrent() Release() @@ -41,7 +43,7 @@ func NewWindow(width, height int) (*Window, error) { } err = contextDo(ctx, func() error { f := ctx.Functions() - fbo, err := gl.NewSRGBFBO(f) + fbo, err := srgb.NewSRGBFBO(f) if err != nil { ctx.Release() return err diff --git a/app/headless/headless_darwin.go b/app/headless/headless_darwin.go index 26d442ea..998173ac 100644 --- a/app/headless/headless_darwin.go +++ b/app/headless/headless_darwin.go @@ -4,7 +4,6 @@ package headless import ( "gioui.org/app/internal/glimpl" - "gioui.org/gpu/gl" ) /* @@ -16,7 +15,7 @@ import ( import "C" type nsContext struct { - c gl.Functions + c *glimpl.Functions ctx C.CFTypeRef prepared bool } @@ -39,7 +38,7 @@ func (c *nsContext) ReleaseCurrent() { C.gio_headless_clearCurrentContext(c.ctx) } -func (c *nsContext) Functions() gl.Functions { +func (c *nsContext) Functions() *glimpl.Functions { return c.c } diff --git a/app/headless/headless_js.go b/app/headless/headless_js.go index f2e53bc3..90ca85eb 100644 --- a/app/headless/headless_js.go +++ b/app/headless/headless_js.go @@ -7,12 +7,11 @@ import ( "syscall/js" "gioui.org/app/internal/glimpl" - "gioui.org/gpu/gl" ) type jsContext struct { ctx js.Value - f gl.Functions + f *glimpl.Functions } func newContext() (*jsContext, error) { @@ -38,7 +37,7 @@ func newContext() (*jsContext, error) { return c, nil } -func (c *jsContext) Functions() gl.Functions { +func (c *jsContext) Functions() *glimpl.Functions { return c.f } diff --git a/app/internal/egl/egl.go b/app/internal/egl/egl.go index 98593470..c6b6a628 100644 --- a/app/internal/egl/egl.go +++ b/app/internal/egl/egl.go @@ -11,18 +11,18 @@ import ( "strings" "gioui.org/app/internal/glimpl" - "gioui.org/gpu/gl" + "gioui.org/app/internal/srgb" ) type Context struct { - c gl.Functions + c *glimpl.Functions disp _EGLDisplay eglCtx *eglContext eglSurf _EGLSurface width, height int refreshFBO bool // For sRGB emulation. - srgbFBO *gl.SRGBFBO + srgbFBO *srgb.SRGBFBO } type eglContext struct { @@ -115,7 +115,7 @@ func NewContext(disp NativeDisplayType) (*Context, error) { return c, nil } -func (c *Context) Functions() gl.Functions { +func (c *Context) Functions() *glimpl.Functions { return c.c } @@ -161,7 +161,7 @@ func (c *Context) MakeCurrent() error { } if c.srgbFBO == nil { var err error - c.srgbFBO, err = gl.NewSRGBFBO(c.c) + c.srgbFBO, err = srgb.NewSRGBFBO(c.c) if err != nil { return err } diff --git a/gpu/gl/srgb.go b/app/internal/srgb/srgb.go similarity index 52% rename from gpu/gl/srgb.go rename to app/internal/srgb/srgb.go index 253fa157..9071beef 100644 --- a/gpu/gl/srgb.go +++ b/app/internal/srgb/srgb.go @@ -1,12 +1,14 @@ // SPDX-License-Identifier: Unlicense OR MIT -package gl +package srgb import ( "fmt" "runtime" "strings" + "gioui.org/app/internal/glimpl" + "gioui.org/gpu/gl" "gioui.org/internal/unsafe" ) @@ -14,28 +16,28 @@ import ( // for gamma-correct rendering on platforms without // sRGB enabled native framebuffers. type SRGBFBO struct { - c Functions + c *glimpl.Functions width, height int - frameBuffer Framebuffer - depthBuffer Renderbuffer - colorTex Texture + frameBuffer gl.Framebuffer + depthBuffer gl.Renderbuffer + colorTex gl.Texture blitted bool - quad Buffer - prog Program + quad gl.Buffer + prog gl.Program es3 bool } -func NewSRGBFBO(f Functions) (*SRGBFBO, error) { +func NewSRGBFBO(f *glimpl.Functions) (*SRGBFBO, error) { var es3 bool - glVer := f.GetString(VERSION) - ver, err := parseGLVersion(glVer) + glVer := f.GetString(gl.VERSION) + ver, err := gl.ParseGLVersion(glVer) if err != nil { return nil, err } if ver[0] >= 3 { es3 = true } else { - exts := f.GetString(EXTENSIONS) + exts := f.GetString(gl.EXTENSIONS) if !strings.Contains(exts, "EXT_sRGB") { return nil, fmt.Errorf("no support for OpenGL ES 3 nor EXT_sRGB") } @@ -47,57 +49,57 @@ func NewSRGBFBO(f Functions) (*SRGBFBO, error) { colorTex: f.CreateTexture(), depthBuffer: f.CreateRenderbuffer(), } - f.BindTexture(TEXTURE_2D, s.colorTex) - f.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE) - f.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE) - f.TexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST) - f.TexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, NEAREST) + f.BindTexture(gl.TEXTURE_2D, s.colorTex) + f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) return s, nil } func (s *SRGBFBO) Blit() { if !s.blitted { - prog, err := createProgram(s.c, blitVSrc, blitFSrc, []string{"pos", "uv"}) + prog, err := gl.CreateProgram(s.c, blitVSrc, blitFSrc, []string{"pos", "uv"}) if err != nil { panic(err) } s.prog = prog s.c.UseProgram(prog) - s.c.Uniform1i(getUniformLocation(s.c, prog, "tex"), 0) + s.c.Uniform1i(gl.GetUniformLocation(s.c, prog, "tex"), 0) s.quad = s.c.CreateBuffer() - s.c.BindBuffer(ARRAY_BUFFER, s.quad) - s.c.BufferData(ARRAY_BUFFER, + s.c.BindBuffer(gl.ARRAY_BUFFER, s.quad) + s.c.BufferData(gl.ARRAY_BUFFER, unsafe.BytesView([]float32{ -1, +1, 0, 1, +1, +1, 1, 1, -1, -1, 0, 0, +1, -1, 1, 0, }), - STATIC_DRAW) + gl.STATIC_DRAW) s.blitted = true } - s.c.BindFramebuffer(FRAMEBUFFER, Framebuffer{}) + s.c.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{}) s.c.UseProgram(s.prog) - s.c.BindTexture(TEXTURE_2D, s.colorTex) - s.c.BindBuffer(ARRAY_BUFFER, s.quad) - s.c.VertexAttribPointer(0 /* pos */, 2, FLOAT, false, 4*4, 0) - s.c.VertexAttribPointer(1 /* uv */, 2, FLOAT, false, 4*4, 4*2) + s.c.BindTexture(gl.TEXTURE_2D, s.colorTex) + s.c.BindBuffer(gl.ARRAY_BUFFER, s.quad) + s.c.VertexAttribPointer(0 /* pos */, 2, gl.FLOAT, false, 4*4, 0) + s.c.VertexAttribPointer(1 /* uv */, 2, gl.FLOAT, false, 4*4, 4*2) s.c.EnableVertexAttribArray(0) s.c.EnableVertexAttribArray(1) - s.c.DrawArrays(TRIANGLE_STRIP, 0, 4) - s.c.BindTexture(TEXTURE_2D, Texture{}) + s.c.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) + s.c.BindTexture(gl.TEXTURE_2D, gl.Texture{}) s.c.DisableVertexAttribArray(0) s.c.DisableVertexAttribArray(1) - s.c.BindFramebuffer(FRAMEBUFFER, s.frameBuffer) - s.c.InvalidateFramebuffer(FRAMEBUFFER, COLOR_ATTACHMENT0) - s.c.InvalidateFramebuffer(FRAMEBUFFER, DEPTH_ATTACHMENT) + s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer) + s.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0) + s.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT) // The Android emulator requires framebuffer 0 bound at eglSwapBuffer time. // Bind the sRGB framebuffer again in afterPresent. - s.c.BindFramebuffer(FRAMEBUFFER, Framebuffer{}) + s.c.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{}) } func (s *SRGBFBO) AfterPresent() { - s.c.BindFramebuffer(FRAMEBUFFER, s.frameBuffer) + s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer) } func (s *SRGBFBO) Refresh(w, h int) error { @@ -105,20 +107,20 @@ func (s *SRGBFBO) Refresh(w, h int) error { if w == 0 || h == 0 { return nil } - s.c.BindTexture(TEXTURE_2D, s.colorTex) + s.c.BindTexture(gl.TEXTURE_2D, s.colorTex) if s.es3 { - s.c.TexImage2D(TEXTURE_2D, 0, SRGB8_ALPHA8, w, h, RGBA, UNSIGNED_BYTE, nil) + s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, w, h, gl.RGBA, gl.UNSIGNED_BYTE, nil) } else /* EXT_sRGB */ { - s.c.TexImage2D(TEXTURE_2D, 0, SRGB_ALPHA_EXT, w, h, SRGB_ALPHA_EXT, UNSIGNED_BYTE, nil) + s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.SRGB_ALPHA_EXT, w, h, gl.SRGB_ALPHA_EXT, gl.UNSIGNED_BYTE, nil) } - currentRB := Renderbuffer(s.c.GetBinding(RENDERBUFFER_BINDING)) - s.c.BindRenderbuffer(RENDERBUFFER, s.depthBuffer) - s.c.RenderbufferStorage(RENDERBUFFER, DEPTH_COMPONENT16, w, h) - s.c.BindRenderbuffer(RENDERBUFFER, currentRB) - s.c.BindFramebuffer(FRAMEBUFFER, s.frameBuffer) - s.c.FramebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, s.colorTex, 0) - s.c.FramebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, s.depthBuffer) - if st := s.c.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE { + currentRB := gl.Renderbuffer(s.c.GetBinding(gl.RENDERBUFFER_BINDING)) + s.c.BindRenderbuffer(gl.RENDERBUFFER, s.depthBuffer) + s.c.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h) + s.c.BindRenderbuffer(gl.RENDERBUFFER, currentRB) + s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer) + s.c.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, s.colorTex, 0) + s.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, s.depthBuffer) + if st := s.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE { return fmt.Errorf("sRGB framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError()) } @@ -127,12 +129,12 @@ func (s *SRGBFBO) Refresh(w, h int) error { // texture result in twice gamma corrected colors. Using a plain RGBA // texture seems to work. s.c.ClearColor(.5, .5, .5, 1.0) - s.c.Clear(COLOR_BUFFER_BIT) + s.c.Clear(gl.COLOR_BUFFER_BIT) var pixel [4]byte - s.c.ReadPixels(0, 0, 1, 1, RGBA, UNSIGNED_BYTE, pixel[:]) + s.c.ReadPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel[:]) if pixel[0] == 128 { // Correct sRGB color value is ~188 - s.c.TexImage2D(TEXTURE_2D, 0, RGBA, w, h, RGBA, UNSIGNED_BYTE, nil) - if st := s.c.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE { + s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, gl.RGBA, gl.UNSIGNED_BYTE, nil) + if st := s.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE { return fmt.Errorf("fallback RGBA framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError()) } } diff --git a/app/internal/window/gl_ios.go b/app/internal/window/gl_ios.go index 8528bfbe..5e340c2f 100644 --- a/app/internal/window/gl_ios.go +++ b/app/internal/window/gl_ios.go @@ -22,7 +22,7 @@ import ( type context struct { owner *window - c gl.Functions + c *glimpl.Functions ctx C.CFTypeRef layer C.CFTypeRef init bool @@ -50,7 +50,7 @@ func newContext(w *window) (*context, error) { return c, nil } -func (c *context) Functions() gl.Functions { +func (c *context) Functions() *glimpl.Functions { return c.c } diff --git a/app/internal/window/gl_js.go b/app/internal/window/gl_js.go index 90661403..60f07e49 100644 --- a/app/internal/window/gl_js.go +++ b/app/internal/window/gl_js.go @@ -7,14 +7,14 @@ import ( "syscall/js" "gioui.org/app/internal/glimpl" - "gioui.org/gpu/gl" + "gioui.org/app/internal/srgb" ) type context struct { ctx js.Value cnv js.Value - f gl.Functions - srgbFBO *gl.SRGBFBO + f *glimpl.Functions + srgbFBO *srgb.SRGBFBO } func newContext(w *window) (*context, error) { @@ -45,7 +45,7 @@ func newContext(w *window) (*context, error) { return c, nil } -func (c *context) Functions() gl.Functions { +func (c *context) Functions() *glimpl.Functions { return c.f } @@ -76,7 +76,7 @@ func (c *context) Unlock() {} func (c *context) MakeCurrent() error { if c.srgbFBO == nil { var err error - c.srgbFBO, err = gl.NewSRGBFBO(c.f) + c.srgbFBO, err = srgb.NewSRGBFBO(c.f) if err != nil { c.Release() c.srgbFBO = nil diff --git a/app/internal/window/gl_macos.go b/app/internal/window/gl_macos.go index ffd9a58d..5c1f34d1 100644 --- a/app/internal/window/gl_macos.go +++ b/app/internal/window/gl_macos.go @@ -6,7 +6,6 @@ package window import ( "gioui.org/app/internal/glimpl" - "gioui.org/gpu/gl" ) /* @@ -19,7 +18,7 @@ import ( import "C" type context struct { - c gl.Functions + c *glimpl.Functions ctx C.CFTypeRef view C.CFTypeRef } @@ -41,7 +40,7 @@ func newContext(w *window) (*context, error) { return c, nil } -func (c *context) Functions() gl.Functions { +func (c *context) Functions() *glimpl.Functions { return c.c } diff --git a/app/internal/window/window.go b/app/internal/window/window.go index 23d8501e..10083d8d 100644 --- a/app/internal/window/window.go +++ b/app/internal/window/window.go @@ -9,7 +9,7 @@ import ( "math" "time" - "gioui.org/gpu/gl" + "gioui.org/app/internal/glimpl" "gioui.org/io/event" "gioui.org/io/system" "gioui.org/unit" @@ -32,7 +32,7 @@ type Callbacks interface { } type Context interface { - Functions() gl.Functions + Functions() *glimpl.Functions Present() error MakeCurrent() error Release() diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go index 394210c3..c0fcb6f2 100644 --- a/gpu/gl/backend.go +++ b/gpu/gl/backend.go @@ -74,7 +74,7 @@ type textureTriple struct { func NewBackend(f Functions) (*Backend, error) { exts := strings.Split(f.GetString(EXTENSIONS), " ") glVer := f.GetString(VERSION) - ver, err := parseGLVersion(glVer) + ver, err := ParseGLVersion(glVer) if err != nil { return nil, err } @@ -282,7 +282,7 @@ func (b *Backend) DepthFunc(f gpu.DepthFunc) { } func (b *Backend) NewProgram(vssrc, fssrc string, attr []string) (gpu.Program, error) { - p, err := createProgram(b.funcs, vssrc, fssrc, attr) + p, err := CreateProgram(b.funcs, vssrc, fssrc, attr) if err != nil { return nil, err } @@ -316,7 +316,7 @@ func (p *gpuProgram) Bind() { func (p *gpuProgram) UniformFor(uniform string) gpu.Uniform { f := p.backend.funcs - return getUniformLocation(f, p.obj, uniform) + return GetUniformLocation(f, p.obj, uniform) } func (b *Backend) SetupVertexArray(slot int, size int, dataType gpu.DataType, stride, offset int) { diff --git a/gpu/gl/util.go b/gpu/gl/util.go index f1c26acf..17e95980 100644 --- a/gpu/gl/util.go +++ b/gpu/gl/util.go @@ -8,7 +8,7 @@ import ( "strings" ) -func createProgram(ctx Functions, vsSrc, fsSrc string, attribs []string) (Program, error) { +func CreateProgram(ctx Functions, vsSrc, fsSrc string, attribs []string) (Program, error) { vs, err := createShader(ctx, VERTEX_SHADER, vsSrc) if err != nil { return Program{}, err @@ -37,7 +37,7 @@ func createProgram(ctx Functions, vsSrc, fsSrc string, attribs []string) (Progra return prog, nil } -func getUniformLocation(ctx Functions, prog Program, name string) Uniform { +func GetUniformLocation(ctx Functions, prog Program, name string) Uniform { loc := ctx.GetUniformLocation(prog, name) if !loc.Valid() { panic(fmt.Errorf("uniform %s not found", name)) @@ -60,7 +60,7 @@ func createShader(ctx Functions, typ Enum, src string) (Shader, error) { return sh, nil } -func parseGLVersion(glVer string) ([2]int, error) { +func ParseGLVersion(glVer string) ([2]int, error) { var ver [2]int if _, err := fmt.Sscanf(glVer, "OpenGL ES %d.%d", &ver[0], &ver[1]); err == nil { return ver, nil