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 <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-05-17 09:50:49 +02:00
parent b622412ac6
commit 03ee75fd72
6 changed files with 47 additions and 19 deletions
-1
View File
@@ -84,5 +84,4 @@ void gio_prepareContext(void) {
GLuint defVBA; GLuint defVBA;
glGenVertexArrays(1, &defVBA); glGenVertexArrays(1, &defVBA);
glBindVertexArray(defVBA); glBindVertexArray(defVBA);
glEnable(GL_FRAMEBUFFER_SRGB);
} }
+28 -18
View File
@@ -33,8 +33,9 @@ type Backend struct {
alphaTriple textureTriple alphaTriple textureTriple
srgbaTriple textureTriple srgbaTriple textureTriple
sRGBFBO *srgb.FBO sRGBFBO *srgb.FBO
defFBO gl.Framebuffer enabledSRGB bool
defFBO gl.Framebuffer
} }
// State tracking. // State tracking.
@@ -177,27 +178,33 @@ func (b *Backend) BeginFrame(clear bool, viewport image.Point) driver.Framebuffe
// Assume GL state is reset between frames. // Assume GL state is reset between frames.
b.state = glstate{} b.state = glstate{}
b.defFBO = gl.Framebuffer(b.funcs.GetBinding(gl.FRAMEBUFFER_BINDING)) 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 renderFBO := b.defFBO
if fbEncoding == gl.LINEAR { if b.gles {
if b.sRGBFBO == nil { // If the output framebuffer is not in the sRGB colorspace already, emulate it.
// Framebuffer is not in sRGB format. Emulate it. var fbEncoding int
sfbo, err := srgb.New(b.funcs) if !b.defFBO.Valid() {
if err != nil { 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) panic(err)
} }
b.sRGBFBO = sfbo renderFBO = b.sRGBFBO.Framebuffer()
} }
if err := b.sRGBFBO.Refresh(viewport); err != nil { } else {
panic(err) 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) b.funcs.BindFramebuffer(gl.FRAMEBUFFER, renderFBO)
if b.sRGBFBO != nil && !clear { if b.sRGBFBO != nil && !clear {
@@ -220,6 +227,9 @@ func (b *Backend) EndFrame() {
} }
b.SetBlend(false) b.SetBlend(false)
b.funcs.BindFramebuffer(gl.FRAMEBUFFER, b.defFBO) b.funcs.BindFramebuffer(gl.FRAMEBUFFER, b.defFBO)
if b.enabledSRGB {
b.funcs.Disable(gl.FRAMEBUFFER_SRGB)
}
} }
func (b *Backend) Caps() driver.Caps { func (b *Backend) Caps() driver.Caps {
+1
View File
@@ -36,6 +36,7 @@ const (
FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210 FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210
FRAMEBUFFER_BINDING = 0x8ca6 FRAMEBUFFER_BINDING = 0x8ca6
FRAMEBUFFER_COMPLETE = 0x8cd5 FRAMEBUFFER_COMPLETE = 0x8cd5
FRAMEBUFFER_SRGB = 0x8db9
HALF_FLOAT = 0x140b HALF_FLOAT = 0x140b
HALF_FLOAT_OES = 0x8d61 HALF_FLOAT_OES = 0x8d61
INFO_LOG_LENGTH = 0x8B84 INFO_LOG_LENGTH = 0x8B84
+3
View File
@@ -276,6 +276,9 @@ func (f *Functions) InvalidateFramebuffer(target, attachment Enum) {
f.Ctx.Call("invalidateFramebuffer", int(target), f.int32Buf) 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) { func (f *Functions) LinkProgram(p Program) {
f.Ctx.Call("linkProgram", js.Value(p)) f.Ctx.Call("linkProgram", js.Value(p))
} }
+10
View File
@@ -83,6 +83,7 @@ typedef struct {
void (*glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); void (*glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
const GLubyte *(*glGetString)(GLenum name); const GLubyte *(*glGetString)(GLenum name);
GLint (*glGetUniformLocation)(GLuint program, const GLchar *name); GLint (*glGetUniformLocation)(GLuint program, const GLchar *name);
GLboolean (*glIsEnabled)(GLenum cap);
void (*glLinkProgram)(GLuint program); void (*glLinkProgram)(GLuint program);
void (*glPixelStorei)(GLenum pname, GLint param); void (*glPixelStorei)(GLenum pname, GLint param);
void (*glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); 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); return f->glGetUniformLocation(program, name);
} }
static GLboolean glIsEnabled(glFunctions *f, GLenum cap) {
return f->glIsEnabled(cap);
}
static void glLinkProgram(glFunctions *f, GLuint program) { static void glLinkProgram(glFunctions *f, GLuint program) {
f->glLinkProgram(program); f->glLinkProgram(program);
} }
@@ -588,6 +593,7 @@ func (f *Functions) load(forceES bool) error {
f.f.glGetShaderInfoLog = must("glGetShaderInfoLog") f.f.glGetShaderInfoLog = must("glGetShaderInfoLog")
f.f.glGetString = must("glGetString") f.f.glGetString = must("glGetString")
f.f.glGetUniformLocation = must("glGetUniformLocation") f.f.glGetUniformLocation = must("glGetUniformLocation")
f.f.glIsEnabled = must("glIsEnabled")
f.f.glLinkProgram = must("glLinkProgram") f.f.glLinkProgram = must("glLinkProgram")
f.f.glPixelStorei = must("glPixelStorei") f.f.glPixelStorei = must("glPixelStorei")
f.f.glReadPixels = must("glReadPixels") 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)) 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) { func (f *Functions) LinkProgram(p Program) {
C.glLinkProgram(&f.f, C.GLuint(p.V)) C.glLinkProgram(&f.f, C.GLuint(p.V))
} }
+5
View File
@@ -70,6 +70,7 @@ var (
_glGetString = LibGLESv2.NewProc("glGetString") _glGetString = LibGLESv2.NewProc("glGetString")
_glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation") _glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation")
_glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer") _glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer")
_glIsEnabled = LibGLESv2.NewProc("glIsEnabled")
_glLinkProgram = LibGLESv2.NewProc("glLinkProgram") _glLinkProgram = LibGLESv2.NewProc("glLinkProgram")
_glPixelStorei = LibGLESv2.NewProc("glPixelStorei") _glPixelStorei = LibGLESv2.NewProc("glPixelStorei")
_glReadPixels = LibGLESv2.NewProc("glReadPixels") _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))) 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) { func (c *Functions) LinkProgram(p Program) {
syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0) syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0)
} }