From 03ee75fd720717a47200393aeb4b33f5d1d27a0f Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 17 May 2021 09:50:49 +0200 Subject: [PATCH] gpu/internal/opengl: support sRGB emulation for desktop OpenGL Desktop OpenGL implements a GL_FRAMEBUFFER_SRGB setting; query that instead of the frambuffer color encoding. With this change it is no longer necessary to enable FRAMEBUFFER_SRGB in the macOS setup; remove it. Signed-off-by: Elias Naur --- app/internal/wm/gl_macos.m | 1 - gpu/internal/opengl/opengl.go | 46 +++++++++++++++++++++-------------- internal/gl/gl.go | 1 + internal/gl/gl_js.go | 3 +++ internal/gl/gl_unix.go | 10 ++++++++ internal/gl/gl_windows.go | 5 ++++ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/app/internal/wm/gl_macos.m b/app/internal/wm/gl_macos.m index 4f29208b..e722407e 100644 --- a/app/internal/wm/gl_macos.m +++ b/app/internal/wm/gl_macos.m @@ -84,5 +84,4 @@ void gio_prepareContext(void) { GLuint defVBA; glGenVertexArrays(1, &defVBA); glBindVertexArray(defVBA); - glEnable(GL_FRAMEBUFFER_SRGB); } diff --git a/gpu/internal/opengl/opengl.go b/gpu/internal/opengl/opengl.go index 85a98252..a758bdd2 100644 --- a/gpu/internal/opengl/opengl.go +++ b/gpu/internal/opengl/opengl.go @@ -33,8 +33,9 @@ type Backend struct { alphaTriple textureTriple srgbaTriple textureTriple - sRGBFBO *srgb.FBO - defFBO gl.Framebuffer + sRGBFBO *srgb.FBO + enabledSRGB bool + defFBO gl.Framebuffer } // State tracking. @@ -177,27 +178,33 @@ func (b *Backend) BeginFrame(clear bool, viewport image.Point) driver.Framebuffe // Assume GL state is reset between frames. b.state = glstate{} b.defFBO = gl.Framebuffer(b.funcs.GetBinding(gl.FRAMEBUFFER_BINDING)) - // Determine color encoding of the output framebuffer. - var fbEncoding int - if !b.defFBO.Valid() { - fbEncoding = b.funcs.GetFramebufferAttachmentParameteri(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) - } else { - fbEncoding = b.funcs.GetFramebufferAttachmentParameteri(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) - } renderFBO := b.defFBO - if fbEncoding == gl.LINEAR { - if b.sRGBFBO == nil { - // Framebuffer is not in sRGB format. Emulate it. - sfbo, err := srgb.New(b.funcs) - if err != nil { + if b.gles { + // If the output framebuffer is not in the sRGB colorspace already, emulate it. + var fbEncoding int + if !b.defFBO.Valid() { + fbEncoding = b.funcs.GetFramebufferAttachmentParameteri(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) + } else { + fbEncoding = b.funcs.GetFramebufferAttachmentParameteri(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) + } + if fbEncoding == gl.LINEAR { + if b.sRGBFBO == nil { + sfbo, err := srgb.New(b.funcs) + if err != nil { + panic(err) + } + b.sRGBFBO = sfbo + } + if err := b.sRGBFBO.Refresh(viewport); err != nil { panic(err) } - b.sRGBFBO = sfbo + renderFBO = b.sRGBFBO.Framebuffer() } - if err := b.sRGBFBO.Refresh(viewport); err != nil { - panic(err) + } else { + b.enabledSRGB = !b.funcs.IsEnabled(gl.FRAMEBUFFER_SRGB) + if b.enabledSRGB { + b.funcs.Enable(gl.FRAMEBUFFER_SRGB) } - renderFBO = b.sRGBFBO.Framebuffer() } b.funcs.BindFramebuffer(gl.FRAMEBUFFER, renderFBO) if b.sRGBFBO != nil && !clear { @@ -220,6 +227,9 @@ func (b *Backend) EndFrame() { } b.SetBlend(false) b.funcs.BindFramebuffer(gl.FRAMEBUFFER, b.defFBO) + if b.enabledSRGB { + b.funcs.Disable(gl.FRAMEBUFFER_SRGB) + } } func (b *Backend) Caps() driver.Caps { diff --git a/internal/gl/gl.go b/internal/gl/gl.go index be9de35f..f27b726b 100644 --- a/internal/gl/gl.go +++ b/internal/gl/gl.go @@ -36,6 +36,7 @@ const ( FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210 FRAMEBUFFER_BINDING = 0x8ca6 FRAMEBUFFER_COMPLETE = 0x8cd5 + FRAMEBUFFER_SRGB = 0x8db9 HALF_FLOAT = 0x140b HALF_FLOAT_OES = 0x8d61 INFO_LOG_LENGTH = 0x8B84 diff --git a/internal/gl/gl_js.go b/internal/gl/gl_js.go index efe3cb86..9781aa69 100644 --- a/internal/gl/gl_js.go +++ b/internal/gl/gl_js.go @@ -276,6 +276,9 @@ func (f *Functions) InvalidateFramebuffer(target, attachment Enum) { f.Ctx.Call("invalidateFramebuffer", int(target), f.int32Buf) } } +func (f *Functions) IsEnabled(cap Enum) bool { + return f.Ctx.Call("isEnabled", int(cap)).Truthy() +} func (f *Functions) LinkProgram(p Program) { f.Ctx.Call("linkProgram", js.Value(p)) } diff --git a/internal/gl/gl_unix.go b/internal/gl/gl_unix.go index 525cdd71..d5d1f3c9 100644 --- a/internal/gl/gl_unix.go +++ b/internal/gl/gl_unix.go @@ -83,6 +83,7 @@ typedef struct { void (*glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); const GLubyte *(*glGetString)(GLenum name); GLint (*glGetUniformLocation)(GLuint program, const GLchar *name); + GLboolean (*glIsEnabled)(GLenum cap); void (*glLinkProgram)(GLuint program); void (*glPixelStorei)(GLenum pname, GLint param); void (*glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); @@ -319,6 +320,10 @@ static GLint glGetUniformLocation(glFunctions *f, GLuint program, const GLchar * return f->glGetUniformLocation(program, name); } +static GLboolean glIsEnabled(glFunctions *f, GLenum cap) { + return f->glIsEnabled(cap); +} + static void glLinkProgram(glFunctions *f, GLuint program) { f->glLinkProgram(program); } @@ -588,6 +593,7 @@ func (f *Functions) load(forceES bool) error { f.f.glGetShaderInfoLog = must("glGetShaderInfoLog") f.f.glGetString = must("glGetString") f.f.glGetUniformLocation = must("glGetUniformLocation") + f.f.glIsEnabled = must("glIsEnabled") f.f.glLinkProgram = must("glLinkProgram") f.f.glPixelStorei = must("glPixelStorei") f.f.glReadPixels = must("glReadPixels") @@ -980,6 +986,10 @@ func (f *Functions) InvalidateFramebuffer(target, attachment Enum) { C.glInvalidateFramebuffer(&f.f, C.GLenum(target), C.GLenum(attachment)) } +func (f *Functions) IsEnabled(cap Enum) bool { + return C.glIsEnabled(&f.f, C.GLenum(cap)) == TRUE +} + func (f *Functions) LinkProgram(p Program) { C.glLinkProgram(&f.f, C.GLuint(p.V)) } diff --git a/internal/gl/gl_windows.go b/internal/gl/gl_windows.go index 0239b75a..aaf3c166 100644 --- a/internal/gl/gl_windows.go +++ b/internal/gl/gl_windows.go @@ -70,6 +70,7 @@ var ( _glGetString = LibGLESv2.NewProc("glGetString") _glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation") _glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer") + _glIsEnabled = LibGLESv2.NewProc("glIsEnabled") _glLinkProgram = LibGLESv2.NewProc("glLinkProgram") _glPixelStorei = LibGLESv2.NewProc("glPixelStorei") _glReadPixels = LibGLESv2.NewProc("glReadPixels") @@ -347,6 +348,10 @@ func (c *Functions) InvalidateFramebuffer(target, attachment Enum) { } syscall.Syscall(addr, 3, uintptr(target), 1, uintptr(unsafe.Pointer(&attachment))) } +func (f *Functions) IsEnabled(cap Enum) bool { + u, _, _ := syscall.Syscall(_glIsEnabled.Addr(), 1, uintptr(cap), 0, 0) + return u == TRUE +} func (c *Functions) LinkProgram(p Program) { syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0) }