mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 18:05:35 +00:00
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:
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user