diff --git a/app/internal/wm/gl_macos.go b/app/internal/wm/gl_macos.go index 0bede035..e652dd58 100644 --- a/app/internal/wm/gl_macos.go +++ b/app/internal/wm/gl_macos.go @@ -15,10 +15,8 @@ import ( #include #include #include -#include __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLContext(void); -__attribute__ ((visibility ("hidden"))) void gio_prepareContext(void); __attribute__ ((visibility ("hidden"))) void gio_setContextView(CFTypeRef ctx, CFTypeRef view); __attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx); __attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx); @@ -29,10 +27,9 @@ __attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef) import "C" type context struct { - c *gl.Functions - ctx C.CFTypeRef - view C.CFTypeRef - prepared bool + c *gl.Functions + ctx C.CFTypeRef + view C.CFTypeRef } func newContext(w *window) (*context, error) { @@ -66,8 +63,6 @@ func (c *context) Release() { } func (c *context) Present() error { - // Assume the caller already locked the context. - C.glFlush() return nil } @@ -83,10 +78,6 @@ func (c *context) MakeCurrent() error { c.Lock() defer c.Unlock() C.gio_makeCurrentContext(c.ctx) - if !c.prepared { - c.prepared = true - C.gio_prepareContext() - } return nil } diff --git a/app/internal/wm/gl_macos.m b/app/internal/wm/gl_macos.m index 61943daf..965f64e6 100644 --- a/app/internal/wm/gl_macos.m +++ b/app/internal/wm/gl_macos.m @@ -6,7 +6,6 @@ #include #include -#include #include "_cgo_export.h" @interface GioGLContext : NSOpenGLContext @@ -79,10 +78,3 @@ void gio_unlockContext(CFTypeRef ctxRef) { CGLUnlockContext([ctx CGLContextObj]); } } - -void gio_prepareContext(void) { - // Bind a default VBA to emulate OpenGL ES 2. - GLuint defVBA; - glGenVertexArrays(1, &defVBA); - glBindVertexArray(defVBA); -} diff --git a/gpu/internal/opengl/opengl.go b/gpu/internal/opengl/opengl.go index a758bdd2..969c5e71 100644 --- a/gpu/internal/opengl/opengl.go +++ b/gpu/internal/opengl/opengl.go @@ -36,6 +36,10 @@ type Backend struct { sRGBFBO *srgb.FBO enabledSRGB bool defFBO gl.Framebuffer + + // defVertArray is bound during a frame. We don't need it, but + // core desktop OpenGL profile 3.3 requires some array bound. + defVertArray gl.VertexArray } // State tracking. @@ -205,6 +209,10 @@ func (b *Backend) BeginFrame(clear bool, viewport image.Point) driver.Framebuffe if b.enabledSRGB { b.funcs.Enable(gl.FRAMEBUFFER_SRGB) } + if !b.defVertArray.Valid() { + b.defVertArray = b.funcs.CreateVertexArray() + } + b.funcs.BindVertexArray(b.defVertArray) } b.funcs.BindFramebuffer(gl.FRAMEBUFFER, renderFBO) if b.sRGBFBO != nil && !clear { @@ -230,6 +238,8 @@ func (b *Backend) EndFrame() { if b.enabledSRGB { b.funcs.Disable(gl.FRAMEBUFFER_SRGB) } + // For single-buffered framebuffers such as on macOS. + b.funcs.Flush() } func (b *Backend) Caps() driver.Caps { @@ -368,6 +378,9 @@ func (b *Backend) Release() { if b.sRGBFBO != nil { b.sRGBFBO.Release() } + if b.defVertArray.Valid() { + b.funcs.DeleteVertexArray(b.defVertArray) + } *b = Backend{} } diff --git a/internal/gl/gl.go b/internal/gl/gl.go index f27b726b..53f31238 100644 --- a/internal/gl/gl.go +++ b/internal/gl/gl.go @@ -101,84 +101,3 @@ const ( TIME_ELAPSED_EXT = 0x88BF GPU_DISJOINT_EXT = 0x8FBB ) - -var _ interface { - ActiveTexture(texture Enum) - AttachShader(p Program, s Shader) - BeginQuery(target Enum, query Query) - BindAttribLocation(p Program, a Attrib, name string) - BindBuffer(target Enum, b Buffer) - BindBufferBase(target Enum, index int, buffer Buffer) - BindFramebuffer(target Enum, fb Framebuffer) - BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) - BindRenderbuffer(target Enum, fb Renderbuffer) - BindTexture(target Enum, t Texture) - BlendEquation(mode Enum) - BlendFunc(sfactor, dfactor Enum) - BlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int, mask Enum, filter Enum) - BufferData(target Enum, size int, usage Enum) - BufferSubData(target Enum, offset int, src []byte) - CheckFramebufferStatus(target Enum) Enum - Clear(mask Enum) - ClearColor(red, green, blue, alpha float32) - ClearDepthf(d float32) - CompileShader(s Shader) - CreateBuffer() Buffer - CreateFramebuffer() Framebuffer - CreateProgram() Program - CreateQuery() Query - CreateRenderbuffer() Renderbuffer - CreateShader(ty Enum) Shader - CreateTexture() Texture - DeleteBuffer(v Buffer) - DeleteFramebuffer(v Framebuffer) - DeleteProgram(p Program) - DeleteQuery(query Query) - DeleteRenderbuffer(r Renderbuffer) - DeleteShader(s Shader) - DeleteTexture(v Texture) - DepthFunc(f Enum) - DepthMask(mask bool) - DisableVertexAttribArray(a Attrib) - Disable(cap Enum) - DispatchCompute(x, y, z int) - DrawArrays(mode Enum, first, count int) - DrawElements(mode Enum, count int, ty Enum, offset int) - Enable(cap Enum) - EnableVertexAttribArray(a Attrib) - EndQuery(target Enum) - FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) - FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) - GetBinding(pname Enum) Object - GetError() Enum - GetInteger(pname Enum) int - GetProgrami(p Program, pname Enum) int - GetProgramInfoLog(p Program) string - GetQueryObjectuiv(query Query, pname Enum) uint - GetShaderi(s Shader, pname Enum) int - GetShaderInfoLog(s Shader) string - GetString(pname Enum) string - GetUniformBlockIndex(p Program, name string) uint - GetUniformLocation(p Program, name string) Uniform - InvalidateFramebuffer(target, attachment Enum) - LinkProgram(p Program) - MapBufferRange(target Enum, offset, length int, access Enum) []byte - MemoryBarrier(barriers Enum) - ReadPixels(x, y, width, height int, format, ty Enum, data []byte) - RenderbufferStorage(target, internalformat Enum, width, height int) - ShaderSource(s Shader, src string) - TexImage2D(target Enum, level int, internalFormat Enum, width, height int, format, ty Enum) - TexParameteri(target, pname Enum, param int) - TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) - TexSubImage2D(target Enum, level, xoff, yoff int, width, height int, format, ty Enum, data []byte) - UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint) - Uniform1f(dst Uniform, v float32) - Uniform1i(dst Uniform, v int) - Uniform2f(dst Uniform, v0, v1 float32) - Uniform3f(dst Uniform, v0, v1, v2 float32) - Uniform4f(dst Uniform, v0, v1, v2, v3 float32) - UseProgram(p Program) - UnmapBuffer(target Enum) bool - VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) - Viewport(x, y, width, height int) -} = (*Functions)(nil) diff --git a/internal/gl/gl_js.go b/internal/gl/gl_js.go index 9781aa69..cd49820e 100644 --- a/internal/gl/gl_js.go +++ b/internal/gl/gl_js.go @@ -93,6 +93,9 @@ func (f *Functions) BindTexture(target Enum, t Texture) { func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) { panic("not implemented") } +func (f *Functions) BindVertexArray(a VertexArray) { + panic("not supported") +} func (f *Functions) BlendEquation(mode Enum) { f.Ctx.Call("blendEquation", int(mode)) } @@ -144,6 +147,9 @@ func (f *Functions) CreateShader(ty Enum) Shader { func (f *Functions) CreateTexture() Texture { return Texture(f.Ctx.Call("createTexture")) } +func (f *Functions) CreateVertexArray() VertexArray { + panic("not supported") +} func (f *Functions) DeleteBuffer(v Buffer) { f.Ctx.Call("deleteBuffer", js.Value(v)) } @@ -169,6 +175,9 @@ func (f *Functions) DeleteRenderbuffer(v Renderbuffer) { func (f *Functions) DeleteTexture(v Texture) { f.Ctx.Call("deleteTexture", js.Value(v)) } +func (f *Functions) DeleteVertexArray(a VertexArray) { + panic("not implemented") +} func (f *Functions) DepthFunc(fn Enum) { f.Ctx.Call("depthFunc", int(fn)) } @@ -206,6 +215,9 @@ func (f *Functions) EndQuery(target Enum) { func (f *Functions) Finish() { f.Ctx.Call("finish") } +func (f *Functions) Flush() { + f.Ctx.Call("flush") +} func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) { f.Ctx.Call("framebufferRenderbuffer", int(target), int(attachment), int(renderbuffertarget), js.Value(renderbuffer)) } diff --git a/internal/gl/gl_unix.go b/internal/gl/gl_unix.go index d5d1f3c9..d7bfbbc0 100644 --- a/internal/gl/gl_unix.go +++ b/internal/gl/gl_unix.go @@ -67,6 +67,7 @@ typedef struct { void (*glEnable)(GLenum cap); void (*glEnableVertexAttribArray)(GLuint index); void (*glFinish)(void); + void (*glFlush)(void); void (*glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void (*glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void (*glGenBuffers)(GLsizei n, GLuint *buffers); @@ -102,15 +103,17 @@ typedef struct { void (*glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); void (*glViewport)(GLint x, GLint y, GLsizei width, GLsizei height); + void (*glBindVertexArray)(GLuint array); void (*glBindBufferBase)(GLenum target, GLuint index, GLuint buffer); GLuint (*glGetUniformBlockIndex)(GLuint program, const GLchar *uniformBlockName); void (*glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); void (*glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments); - void (*glBeginQuery)(GLenum target, GLuint id); void (*glDeleteQueries)(GLsizei n, const GLuint *ids); + void (*glDeleteVertexArrays)(GLsizei n, const GLuint *ids); void (*glEndQuery)(GLenum target); void (*glGenQueries)(GLsizei n, GLuint *ids); + void (*glGenVertexArrays)(GLsizei n, GLuint *ids); void (*glGetProgramBinary)(GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary); void (*glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params); const GLubyte* (*glGetStringi)(GLenum name, GLuint index); @@ -151,6 +154,10 @@ static void glBindTexture(glFunctions *f, GLenum target, GLuint texture) { f->glBindTexture(target, texture); } +static void glBindVertexArray(glFunctions *f, GLuint array) { + f->glBindVertexArray(array); +} + static void glBlendEquation(glFunctions *f, GLenum mode) { f->glBlendEquation(mode); } @@ -256,6 +263,10 @@ static void glFinish(glFunctions *f) { f->glFinish(); } +static void glFlush(glFunctions *f) { + f->glFlush(); +} + static void glFramebufferRenderbuffer(glFunctions *f, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { f->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); } @@ -420,6 +431,10 @@ static void glDeleteQueries(glFunctions *f, GLsizei n, const GLuint *ids) { f->glDeleteQueries(n, ids); } +static void glDeleteVertexArrays(glFunctions *f, GLsizei n, const GLuint *ids) { + f->glDeleteVertexArrays(n, ids); +} + static void glEndQuery(glFunctions *f, GLenum target) { f->glEndQuery(target); } @@ -432,6 +447,10 @@ static void glGenQueries(glFunctions *f, GLsizei n, GLuint *ids) { f->glGenQueries(n, ids); } +static void glGenVertexArrays(glFunctions *f, GLsizei n, GLuint *ids) { + f->glGenVertexArrays(n, ids); +} + static void glGetProgramBinary(glFunctions *f, GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary) { f->glGetProgramBinary(program, bufsize, length, binaryFormat, binary); } @@ -577,6 +596,7 @@ func (f *Functions) load(forceES bool) error { f.f.glEnable = must("glEnable") f.f.glEnableVertexAttribArray = must("glEnableVertexAttribArray") f.f.glFinish = must("glFinish") + f.f.glFlush = must("glFlush") f.f.glFramebufferRenderbuffer = must("glFramebufferRenderbuffer") f.f.glFramebufferTexture2D = must("glFramebufferTexture2D") f.f.glGenBuffers = must("glGenBuffers") @@ -614,6 +634,7 @@ func (f *Functions) load(forceES bool) error { // Extensions and GL ES 3 functions. f.f.glBindBufferBase = load("glBindBufferBase") + f.f.glBindVertexArray = must("glBindVertexArray") f.f.glGetUniformBlockIndex = load("glGetUniformBlockIndex") f.f.glUniformBlockBinding = load("glUniformBlockBinding") f.f.glInvalidateFramebuffer = load("glInvalidateFramebuffer") @@ -644,6 +665,8 @@ func (f *Functions) load(forceES bool) error { f.f.glGetQueryObjectuiv = load("glGetQueryObjectuivEXT") } + f.f.glDeleteVertexArrays = load("glDeleteVertexArrays") + f.f.glGenVertexArrays = load("glGenVertexArrays") f.f.glMemoryBarrier = load("glMemoryBarrier") f.f.glDispatchCompute = load("glDispatchCompute") f.f.glMapBufferRange = load("glMapBufferRange") @@ -702,6 +725,10 @@ func (f *Functions) BindTexture(target Enum, t Texture) { C.glBindTexture(&f.f, C.GLenum(target), C.GLuint(t.V)) } +func (f *Functions) BindVertexArray(a VertexArray) { + C.glBindVertexArray(&f.f, C.GLuint(a.V)) +} + func (f *Functions) BlendEquation(mode Enum) { C.glBlendEquation(&f.f, C.GLenum(mode)) } @@ -783,6 +810,11 @@ func (f *Functions) CreateTexture() Texture { return Texture{uint(f.uints[0])} } +func (f *Functions) CreateVertexArray() VertexArray { + C.glGenVertexArrays(&f.f, 1, &f.uints[0]) + return VertexArray{uint(f.uints[0])} +} + func (f *Functions) DeleteBuffer(v Buffer) { f.uints[0] = C.GLuint(v.V) C.glDeleteBuffers(&f.f, 1, &f.uints[0]) @@ -802,6 +834,11 @@ func (f *Functions) DeleteQuery(query Query) { C.glDeleteQueries(&f.f, 1, &f.uints[0]) } +func (f *Functions) DeleteVertexArray(array VertexArray) { + f.uints[0] = C.GLuint(array.V) + C.glDeleteVertexArrays(&f.f, 1, &f.uints[0]) +} + func (f *Functions) DeleteRenderbuffer(v Renderbuffer) { f.uints[0] = C.GLuint(v.V) C.glDeleteRenderbuffers(&f.f, 1, &f.uints[0]) @@ -864,6 +901,10 @@ func (f *Functions) Finish() { C.glFinish(&f.f) } +func (f *Functions) Flush() { + C.glFlush(&f.f) +} + func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) { C.glFramebufferRenderbuffer(&f.f, C.GLenum(target), C.GLenum(attachment), C.GLenum(renderbuffertarget), C.GLuint(renderbuffer.V)) } diff --git a/internal/gl/gl_windows.go b/internal/gl/gl_windows.go index 4773f019..e5305b14 100644 --- a/internal/gl/gl_windows.go +++ b/internal/gl/gl_windows.go @@ -22,6 +22,7 @@ var ( _glBindFramebuffer = LibGLESv2.NewProc("glBindFramebuffer") _glBindRenderbuffer = LibGLESv2.NewProc("glBindRenderbuffer") _glBindTexture = LibGLESv2.NewProc("glBindTexture") + _glBindVertexArray = LibGLESv2.NewProc("glBindVertexArray") _glBlendEquation = LibGLESv2.NewProc("glBlendEquation") _glBlendFunc = LibGLESv2.NewProc("glBlendFunc") _glBufferData = LibGLESv2.NewProc("glBufferData") @@ -31,9 +32,11 @@ var ( _glClearColor = LibGLESv2.NewProc("glClearColor") _glClearDepthf = LibGLESv2.NewProc("glClearDepthf") _glDeleteQueries = LibGLESv2.NewProc("glDeleteQueries") + _glDeleteVertexArrays = LibGLESv2.NewProc("glDeleteVertexArrays") _glCompileShader = LibGLESv2.NewProc("glCompileShader") _glGenBuffers = LibGLESv2.NewProc("glGenBuffers") _glGenFramebuffers = LibGLESv2.NewProc("glGenFramebuffers") + _glGenVertexArrays = LibGLESv2.NewProc("glGenVertexArrays") _glGetUniformBlockIndex = LibGLESv2.NewProc("glGetUniformBlockIndex") _glCreateProgram = LibGLESv2.NewProc("glCreateProgram") _glGenRenderbuffers = LibGLESv2.NewProc("glGenRenderbuffers") @@ -55,6 +58,7 @@ var ( _glEnableVertexAttribArray = LibGLESv2.NewProc("glEnableVertexAttribArray") _glEndQuery = LibGLESv2.NewProc("glEndQuery") _glFinish = LibGLESv2.NewProc("glFinish") + _glFlush = LibGLESv2.NewProc("glFlush") _glFramebufferRenderbuffer = LibGLESv2.NewProc("glFramebufferRenderbuffer") _glFramebufferTexture2D = LibGLESv2.NewProc("glFramebufferTexture2D") _glGenQueries = LibGLESv2.NewProc("glGenQueries") @@ -139,6 +143,9 @@ func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered boo func (c *Functions) BindTexture(target Enum, t Texture) { syscall.Syscall(_glBindTexture.Addr(), 2, uintptr(target), uintptr(t.V), 0) } +func (c *Functions) BindVertexArray(a VertexArray) { + syscall.Syscall(_glBindVertexArray.Addr(), 1, uintptr(a.V), 0, 0) +} func (c *Functions) BlendEquation(mode Enum) { syscall.Syscall(_glBlendEquation.Addr(), 1, uintptr(mode), 0, 0) } @@ -207,6 +214,11 @@ func (c *Functions) CreateTexture() Texture { syscall.Syscall(_glGenTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&t)), 0) return Texture{uint(t)} } +func (c *Functions) CreateVertexArray() VertexArray { + var t uintptr + syscall.Syscall(_glGenVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&t)), 0) + return VertexArray{uint(t)} +} func (c *Functions) DeleteBuffer(v Buffer) { syscall.Syscall(_glDeleteBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v)), 0) } @@ -228,6 +240,9 @@ func (c *Functions) DeleteRenderbuffer(v Renderbuffer) { func (c *Functions) DeleteTexture(v Texture) { syscall.Syscall(_glDeleteTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0) } +func (f *Functions) DeleteVertexArray(array VertexArray) { + syscall.Syscall(_glDeleteVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&array.V)), 0) +} func (c *Functions) DepthFunc(f Enum) { syscall.Syscall(_glDepthFunc.Addr(), 1, uintptr(f), 0, 0) } @@ -265,6 +280,9 @@ func (f *Functions) EndQuery(target Enum) { func (c *Functions) Finish() { syscall.Syscall(_glFinish.Addr(), 0, 0, 0, 0) } +func (c *Functions) Flush() { + syscall.Syscall(_glFlush.Addr(), 0, 0, 0, 0) +} func (c *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) { syscall.Syscall6(_glFramebufferRenderbuffer.Addr(), 4, uintptr(target), uintptr(attachment), uintptr(renderbuffertarget), uintptr(renderbuffer.V), 0, 0) } diff --git a/internal/gl/types.go b/internal/gl/types.go index bbd28951..f7b04b48 100644 --- a/internal/gl/types.go +++ b/internal/gl/types.go @@ -11,6 +11,7 @@ type ( Texture struct{ V uint } Query struct{ V uint } Uniform struct{ V int } + VertexArray struct{ V uint } Object struct{ V uint } ) @@ -29,3 +30,7 @@ func (p Program) Valid() bool { func (s Shader) Valid() bool { return s.V != 0 } + +func (a VertexArray) Valid() bool { + return a.V != 0 +} diff --git a/internal/gl/types_js.go b/internal/gl/types_js.go index a1d27f2e..392b3c0d 100644 --- a/internal/gl/types_js.go +++ b/internal/gl/types_js.go @@ -13,6 +13,7 @@ type ( Texture js.Value Query js.Value Uniform js.Value + VertexArray js.Value Object js.Value ) @@ -31,3 +32,7 @@ func (s Shader) Valid() bool { func (u Uniform) Valid() bool { return !js.Value(u).IsUndefined() && !js.Value(u).IsNull() } + +func (a VertexArray) Valid() bool { + return !js.Value(a).IsUndefined() && !js.Value(a).IsNull() +}