internal/graphicsdriver/opengl/gles: integrate gles and glconst into gl

Updates #2451
This commit is contained in:
Hajime Hoshi 2022-11-13 13:24:54 +09:00
parent c4abaa32f5
commit 0c5a77eaa4
16 changed files with 244 additions and 295 deletions

View File

@ -22,7 +22,6 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
@ -92,14 +91,14 @@ func (c *context) reset() error {
c.lastViewportWidth = 0 c.lastViewportWidth = 0
c.lastViewportHeight = 0 c.lastViewportHeight = 0
c.lastBlend = graphicsdriver.Blend{} c.lastBlend = graphicsdriver.Blend{}
gl.Enable(glconst.BLEND) gl.Enable(gl.BLEND)
gl.Enable(glconst.SCISSOR_TEST) gl.Enable(gl.SCISSOR_TEST)
// Set the source over blending. // Set the source over blending.
c.blend(graphicsdriver.BlendSourceOver) c.blend(graphicsdriver.BlendSourceOver)
f := int32(0) f := int32(0)
gl.GetIntegerv(glconst.FRAMEBUFFER_BINDING, &f) gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
c.screenFramebuffer = framebufferNative(f) c.screenFramebuffer = framebufferNative(f)
return nil return nil
} }
@ -135,42 +134,42 @@ func (c *context) newTexture(width, height int) (textureNative, error) {
texture := textureNative(t) texture := textureNative(t)
c.bindTexture(texture) c.bindTexture(texture)
gl.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_MAG_FILTER, glconst.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_MIN_FILTER, glconst.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_S, glconst.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_T, glconst.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.PixelStorei(glconst.UNPACK_ALIGNMENT, 4) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4)
// If data is nil, this just allocates memory and the content is undefined. // If data is nil, this just allocates memory and the content is undefined.
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
gl.TexImage2D(glconst.TEXTURE_2D, 0, glconst.RGBA, int32(width), int32(height), 0, glconst.RGBA, glconst.UNSIGNED_BYTE, nil) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, nil)
return texture, nil return texture, nil
} }
func (c *context) bindFramebufferImpl(f framebufferNative) { func (c *context) bindFramebufferImpl(f framebufferNative) {
gl.BindFramebufferEXT(glconst.FRAMEBUFFER, uint32(f)) gl.BindFramebufferEXT(gl.FRAMEBUFFER, uint32(f))
} }
func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) { func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) {
gl.Flush() gl.Flush()
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
gl.ReadPixels(int32(x), int32(y), int32(width), int32(height), glconst.RGBA, glconst.UNSIGNED_BYTE, gl.Ptr(buf)) gl.ReadPixels(int32(x), int32(y), int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(buf))
} }
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) { func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {
gl.Flush() gl.Flush()
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
gl.BindBuffer(glconst.PIXEL_PACK_BUFFER, uint32(buffer)) gl.BindBuffer(gl.PIXEL_PACK_BUFFER, uint32(buffer))
gl.ReadPixels(0, 0, int32(width), int32(height), glconst.RGBA, glconst.UNSIGNED_BYTE, nil) gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, nil)
gl.BindBuffer(glconst.PIXEL_PACK_BUFFER, 0) gl.BindBuffer(gl.PIXEL_PACK_BUFFER, 0)
} }
func (c *context) activeTexture(idx int) { func (c *context) activeTexture(idx int) {
gl.ActiveTexture(glconst.TEXTURE0 + uint32(idx)) gl.ActiveTexture(gl.TEXTURE0 + uint32(idx))
} }
func (c *context) bindTextureImpl(t textureNative) { func (c *context) bindTextureImpl(t textureNative) {
gl.BindTexture(glconst.TEXTURE_2D, uint32(t)) gl.BindTexture(gl.TEXTURE_2D, uint32(t))
} }
func (c *context) deleteTexture(t textureNative) { func (c *context) deleteTexture(t textureNative) {
@ -200,13 +199,13 @@ func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error)
// GL_STENCIL_INDEX8 might not be available with OpenGL 2.1. // GL_STENCIL_INDEX8 might not be available with OpenGL 2.1.
// https://www.khronos.org/opengl/wiki/Image_Format // https://www.khronos.org/opengl/wiki/Image_Format
gl.RenderbufferStorageEXT(glconst.RENDERBUFFER, glconst.DEPTH24_STENCIL8, int32(width), int32(height)) gl.RenderbufferStorageEXT(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, int32(width), int32(height))
return renderbuffer, nil return renderbuffer, nil
} }
func (c *context) bindRenderbufferImpl(r renderbufferNative) { func (c *context) bindRenderbufferImpl(r renderbufferNative) {
gl.BindRenderbufferEXT(glconst.RENDERBUFFER, uint32(r)) gl.BindRenderbufferEXT(gl.RENDERBUFFER, uint32(r))
} }
func (c *context) deleteRenderbuffer(r renderbufferNative) { func (c *context) deleteRenderbuffer(r renderbufferNative) {
@ -227,13 +226,13 @@ func (c *context) newFramebuffer(texture textureNative) (framebufferNative, erro
return 0, errors.New("opengl: creating framebuffer failed") return 0, errors.New("opengl: creating framebuffer failed")
} }
c.bindFramebuffer(framebufferNative(f)) c.bindFramebuffer(framebufferNative(f))
gl.FramebufferTexture2DEXT(glconst.FRAMEBUFFER, glconst.COLOR_ATTACHMENT0, glconst.TEXTURE_2D, uint32(texture), 0) gl.FramebufferTexture2DEXT(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
s := gl.CheckFramebufferStatusEXT(glconst.FRAMEBUFFER) s := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER)
if s != glconst.FRAMEBUFFER_COMPLETE { if s != gl.FRAMEBUFFER_COMPLETE {
if s != 0 { if s != 0 {
return 0, fmt.Errorf("opengl: creating framebuffer failed: %v", s) return 0, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
} }
if e := gl.GetError(); e != glconst.NO_ERROR { if e := gl.GetError(); e != gl.NO_ERROR {
return 0, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e) return 0, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
} }
return 0, fmt.Errorf("opengl: creating framebuffer failed: unknown error") return 0, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
@ -244,8 +243,8 @@ func (c *context) newFramebuffer(texture textureNative) (framebufferNative, erro
func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error { func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error {
c.bindFramebuffer(f) c.bindFramebuffer(f)
gl.FramebufferRenderbufferEXT(glconst.FRAMEBUFFER, glconst.STENCIL_ATTACHMENT, glconst.RENDERBUFFER, uint32(r)) gl.FramebufferRenderbufferEXT(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, uint32(r))
if s := gl.CheckFramebufferStatusEXT(glconst.FRAMEBUFFER); s != glconst.FRAMEBUFFER_COMPLETE { if s := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s)) return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
} }
return nil return nil
@ -269,11 +268,11 @@ func (c *context) deleteFramebuffer(f framebufferNative) {
} }
func (c *context) newVertexShader(source string) (shader, error) { func (c *context) newVertexShader(source string) (shader, error) {
return c.newShader(glconst.VERTEX_SHADER, source) return c.newShader(gl.VERTEX_SHADER, source)
} }
func (c *context) newFragmentShader(source string) (shader, error) { func (c *context) newFragmentShader(source string) (shader, error) {
return c.newShader(glconst.FRAGMENT_SHADER, source) return c.newShader(gl.FRAGMENT_SHADER, source)
} }
func (c *context) newShader(shaderType uint32, source string) (shader, error) { func (c *context) newShader(shaderType uint32, source string) (shader, error) {
@ -287,11 +286,11 @@ func (c *context) newShader(shaderType uint32, source string) (shader, error) {
gl.CompileShader(s) gl.CompileShader(s)
var v int32 var v int32
gl.GetShaderiv(s, glconst.COMPILE_STATUS, &v) gl.GetShaderiv(s, gl.COMPILE_STATUS, &v)
if v == glconst.FALSE { if v == gl.FALSE {
var l int32 var l int32
var log []byte var log []byte
gl.GetShaderiv(uint32(s), glconst.INFO_LOG_LENGTH, &l) gl.GetShaderiv(uint32(s), gl.INFO_LOG_LENGTH, &l)
if l != 0 { if l != 0 {
log = make([]byte, l) log = make([]byte, l)
gl.GetShaderInfoLog(s, l, nil, (*uint8)(gl.Ptr(log))) gl.GetShaderInfoLog(s, l, nil, (*uint8)(gl.Ptr(log)))
@ -323,11 +322,11 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er
gl.LinkProgram(p) gl.LinkProgram(p)
var v int32 var v int32
gl.GetProgramiv(p, glconst.LINK_STATUS, &v) gl.GetProgramiv(p, gl.LINK_STATUS, &v)
if v == glconst.FALSE { if v == gl.FALSE {
var l int32 var l int32
var log []byte var log []byte
gl.GetProgramiv(p, glconst.INFO_LOG_LENGTH, &l) gl.GetProgramiv(p, gl.INFO_LOG_LENGTH, &l)
if l != 0 { if l != 0 {
log = make([]byte, l) log = make([]byte, l)
gl.GetProgramInfoLog(p, l, nil, (*uint8)(gl.Ptr(log))) gl.GetProgramInfoLog(p, l, nil, (*uint8)(gl.Ptr(log)))
@ -403,7 +402,7 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.
} }
func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) { func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) {
gl.VertexAttribPointer(uint32(index), int32(size), glconst.FLOAT, false, int32(stride), uintptr(offset)) gl.VertexAttribPointer(uint32(index), int32(size), gl.FLOAT, false, int32(stride), uintptr(offset))
} }
func (c *context) enableVertexAttribArray(index int) { func (c *context) enableVertexAttribArray(index int) {
@ -417,33 +416,33 @@ func (c *context) disableVertexAttribArray(index int) {
func (c *context) newArrayBuffer(size int) buffer { func (c *context) newArrayBuffer(size int) buffer {
var b uint32 var b uint32
gl.GenBuffers(1, &b) gl.GenBuffers(1, &b)
gl.BindBuffer(glconst.ARRAY_BUFFER, b) gl.BindBuffer(gl.ARRAY_BUFFER, b)
gl.BufferData(glconst.ARRAY_BUFFER, size, nil, glconst.DYNAMIC_DRAW) gl.BufferData(gl.ARRAY_BUFFER, size, nil, gl.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) newElementArrayBuffer(size int) buffer { func (c *context) newElementArrayBuffer(size int) buffer {
var b uint32 var b uint32
gl.GenBuffers(1, &b) gl.GenBuffers(1, &b)
gl.BindBuffer(glconst.ELEMENT_ARRAY_BUFFER, b) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b)
gl.BufferData(glconst.ELEMENT_ARRAY_BUFFER, size, nil, glconst.DYNAMIC_DRAW) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, size, nil, gl.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) bindArrayBuffer(b buffer) { func (c *context) bindArrayBuffer(b buffer) {
gl.BindBuffer(glconst.ARRAY_BUFFER, uint32(b)) gl.BindBuffer(gl.ARRAY_BUFFER, uint32(b))
} }
func (c *context) bindElementArrayBuffer(b buffer) { func (c *context) bindElementArrayBuffer(b buffer) {
gl.BindBuffer(glconst.ELEMENT_ARRAY_BUFFER, uint32(b)) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(b))
} }
func (c *context) arrayBufferSubData(data []float32) { func (c *context) arrayBufferSubData(data []float32) {
gl.BufferSubData(glconst.ARRAY_BUFFER, 0, len(data)*4, gl.Ptr(data)) gl.BufferSubData(gl.ARRAY_BUFFER, 0, len(data)*4, gl.Ptr(data))
} }
func (c *context) elementArrayBufferSubData(data []uint16) { func (c *context) elementArrayBufferSubData(data []uint16) {
gl.BufferSubData(glconst.ELEMENT_ARRAY_BUFFER, 0, len(data)*2, gl.Ptr(data)) gl.BufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, len(data)*2, gl.Ptr(data))
} }
func (c *context) deleteBuffer(b buffer) { func (c *context) deleteBuffer(b buffer) {
@ -452,12 +451,12 @@ func (c *context) deleteBuffer(b buffer) {
} }
func (c *context) drawElements(len int, offsetInBytes int) { func (c *context) drawElements(len int, offsetInBytes int) {
gl.DrawElements(glconst.TRIANGLES, int32(len), glconst.UNSIGNED_SHORT, uintptr(offsetInBytes)) gl.DrawElements(gl.TRIANGLES, int32(len), gl.UNSIGNED_SHORT, uintptr(offsetInBytes))
} }
func (c *context) maxTextureSizeImpl() int { func (c *context) maxTextureSizeImpl() int {
s := int32(0) s := int32(0)
gl.GetIntegerv(glconst.MAX_TEXTURE_SIZE, &s) gl.GetIntegerv(gl.MAX_TEXTURE_SIZE, &s)
return int(s) return int(s)
} }
@ -472,27 +471,27 @@ func (c *context) needsRestoring() bool {
func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) { func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) {
c.bindTexture(t) c.bindTexture(t)
for _, a := range args { for _, a := range args {
gl.TexSubImage2D(glconst.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), glconst.RGBA, glconst.UNSIGNED_BYTE, gl.Ptr(a.Pixels)) gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(a.Pixels))
} }
} }
func (c *context) enableStencilTest() { func (c *context) enableStencilTest() {
gl.Enable(glconst.STENCIL_TEST) gl.Enable(gl.STENCIL_TEST)
} }
func (c *context) disableStencilTest() { func (c *context) disableStencilTest() {
gl.Disable(glconst.STENCIL_TEST) gl.Disable(gl.STENCIL_TEST)
} }
func (c *context) beginStencilWithEvenOddRule() { func (c *context) beginStencilWithEvenOddRule() {
gl.Clear(glconst.STENCIL_BUFFER_BIT) gl.Clear(gl.STENCIL_BUFFER_BIT)
gl.StencilFunc(glconst.ALWAYS, 0x00, 0xff) gl.StencilFunc(gl.ALWAYS, 0x00, 0xff)
gl.StencilOp(glconst.KEEP, glconst.KEEP, glconst.INVERT) gl.StencilOp(gl.KEEP, gl.KEEP, gl.INVERT)
gl.ColorMask(false, false, false, false) gl.ColorMask(false, false, false, false)
} }
func (c *context) endStencilWithEvenOddRule() { func (c *context) endStencilWithEvenOddRule() {
gl.StencilFunc(glconst.NOTEQUAL, 0x00, 0xff) gl.StencilFunc(gl.NOTEQUAL, 0x00, 0xff)
gl.StencilOp(glconst.KEEP, glconst.KEEP, glconst.KEEP) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
gl.ColorMask(true, true, true, true) gl.ColorMask(true, true, true, true)
} }

View File

@ -22,8 +22,7 @@ import (
"unsafe" "unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gles"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
@ -84,7 +83,7 @@ func getProgramID(p program) programID {
} }
type contextImpl struct { type contextImpl struct {
ctx gles.Context ctx gl.Context
} }
func (c *context) reset() error { func (c *context) reset() error {
@ -94,11 +93,11 @@ func (c *context) reset() error {
c.lastViewportWidth = 0 c.lastViewportWidth = 0
c.lastViewportHeight = 0 c.lastViewportHeight = 0
c.lastBlend = graphicsdriver.Blend{} c.lastBlend = graphicsdriver.Blend{}
c.ctx.Enable(glconst.BLEND) c.ctx.Enable(gl.BLEND)
c.ctx.Enable(glconst.SCISSOR_TEST) c.ctx.Enable(gl.SCISSOR_TEST)
c.blend(graphicsdriver.BlendSourceOver) c.blend(graphicsdriver.BlendSourceOver)
f := make([]int32, 1) f := make([]int32, 1)
c.ctx.GetIntegerv(f, glconst.FRAMEBUFFER_BINDING) c.ctx.GetIntegerv(f, gl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = framebufferNative(f[0]) c.screenFramebuffer = framebufferNative(f[0])
// TODO: Need to update screenFramebufferWidth/Height? // TODO: Need to update screenFramebufferWidth/Height?
return nil return nil
@ -132,18 +131,18 @@ func (c *context) newTexture(width, height int) (textureNative, error) {
} }
c.bindTexture(textureNative(t)) c.bindTexture(textureNative(t))
c.ctx.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_MAG_FILTER, glconst.NEAREST) c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
c.ctx.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_MIN_FILTER, glconst.NEAREST) c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
c.ctx.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_S, glconst.CLAMP_TO_EDGE) c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
c.ctx.TexParameteri(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_T, glconst.CLAMP_TO_EDGE) c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
c.ctx.PixelStorei(glconst.UNPACK_ALIGNMENT, 4) c.ctx.PixelStorei(gl.UNPACK_ALIGNMENT, 4)
c.ctx.TexImage2D(glconst.TEXTURE_2D, 0, glconst.RGBA, int32(width), int32(height), glconst.RGBA, glconst.UNSIGNED_BYTE, nil) c.ctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, nil)
return textureNative(t), nil return textureNative(t), nil
} }
func (c *context) bindFramebufferImpl(f framebufferNative) { func (c *context) bindFramebufferImpl(f framebufferNative) {
c.ctx.BindFramebuffer(glconst.FRAMEBUFFER, uint32(f)) c.ctx.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
} }
func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) { func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) {
@ -151,7 +150,7 @@ func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, hei
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
c.ctx.ReadPixels(buf, int32(x), int32(y), int32(width), int32(height), glconst.RGBA, glconst.UNSIGNED_BYTE) c.ctx.ReadPixels(buf, int32(x), int32(y), int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE)
} }
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) { func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {
@ -159,17 +158,17 @@ func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
c.ctx.BindBuffer(glconst.PIXEL_PACK_BUFFER, uint32(buffer)) c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, uint32(buffer))
c.ctx.ReadPixels(nil, 0, 0, int32(width), int32(height), glconst.RGBA, glconst.UNSIGNED_BYTE) c.ctx.ReadPixels(nil, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE)
c.ctx.BindBuffer(glconst.PIXEL_PACK_BUFFER, 0) c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, 0)
} }
func (c *context) activeTexture(idx int) { func (c *context) activeTexture(idx int) {
c.ctx.ActiveTexture(uint32(glconst.TEXTURE0 + idx)) c.ctx.ActiveTexture(uint32(gl.TEXTURE0 + idx))
} }
func (c *context) bindTextureImpl(t textureNative) { func (c *context) bindTextureImpl(t textureNative) {
c.ctx.BindTexture(glconst.TEXTURE_2D, uint32(t)) c.ctx.BindTexture(gl.TEXTURE_2D, uint32(t))
} }
func (c *context) deleteTexture(t textureNative) { func (c *context) deleteTexture(t textureNative) {
@ -195,13 +194,13 @@ func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error)
renderbuffer := renderbufferNative(r) renderbuffer := renderbufferNative(r)
c.bindRenderbuffer(renderbuffer) c.bindRenderbuffer(renderbuffer)
c.ctx.RenderbufferStorage(glconst.RENDERBUFFER, glconst.STENCIL_INDEX8, int32(width), int32(height)) c.ctx.RenderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, int32(width), int32(height))
return renderbuffer, nil return renderbuffer, nil
} }
func (c *context) bindRenderbufferImpl(r renderbufferNative) { func (c *context) bindRenderbufferImpl(r renderbufferNative) {
c.ctx.BindRenderbuffer(glconst.RENDERBUFFER, uint32(r)) c.ctx.BindRenderbuffer(gl.RENDERBUFFER, uint32(r))
} }
func (c *context) deleteRenderbuffer(r renderbufferNative) { func (c *context) deleteRenderbuffer(r renderbufferNative) {
@ -221,13 +220,13 @@ func (c *context) newFramebuffer(texture textureNative) (framebufferNative, erro
} }
c.bindFramebuffer(framebufferNative(f)) c.bindFramebuffer(framebufferNative(f))
c.ctx.FramebufferTexture2D(glconst.FRAMEBUFFER, glconst.COLOR_ATTACHMENT0, glconst.TEXTURE_2D, uint32(texture), 0) c.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
s := c.ctx.CheckFramebufferStatus(glconst.FRAMEBUFFER) s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER)
if s != glconst.FRAMEBUFFER_COMPLETE { if s != gl.FRAMEBUFFER_COMPLETE {
if s != 0 { if s != 0 {
return 0, fmt.Errorf("opengl: creating framebuffer failed: %v", s) return 0, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
} }
if e := c.ctx.GetError(); e != glconst.NO_ERROR { if e := c.ctx.GetError(); e != gl.NO_ERROR {
return 0, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e) return 0, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
} }
return 0, fmt.Errorf("opengl: creating framebuffer failed: unknown error") return 0, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
@ -238,8 +237,8 @@ func (c *context) newFramebuffer(texture textureNative) (framebufferNative, erro
func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error { func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error {
c.bindFramebuffer(f) c.bindFramebuffer(f)
c.ctx.FramebufferRenderbuffer(glconst.FRAMEBUFFER, glconst.STENCIL_ATTACHMENT, glconst.RENDERBUFFER, uint32(r)) c.ctx.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, uint32(r))
if s := c.ctx.CheckFramebufferStatus(glconst.FRAMEBUFFER); s != glconst.FRAMEBUFFER_COMPLETE { if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s)) return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
} }
return nil return nil
@ -265,11 +264,11 @@ func (c *context) deleteFramebuffer(f framebufferNative) {
} }
func (c *context) newVertexShader(source string) (shader, error) { func (c *context) newVertexShader(source string) (shader, error) {
return c.newShader(glconst.VERTEX_SHADER, source) return c.newShader(gl.VERTEX_SHADER, source)
} }
func (c *context) newFragmentShader(source string) (shader, error) { func (c *context) newFragmentShader(source string) (shader, error) {
return c.newShader(glconst.FRAGMENT_SHADER, source) return c.newShader(gl.FRAGMENT_SHADER, source)
} }
func (c *context) newShader(shaderType uint32, source string) (shader, error) { func (c *context) newShader(shaderType uint32, source string) (shader, error) {
@ -281,8 +280,8 @@ func (c *context) newShader(shaderType uint32, source string) (shader, error) {
c.ctx.CompileShader(s) c.ctx.CompileShader(s)
v := make([]int32, 1) v := make([]int32, 1)
c.ctx.GetShaderiv(v, s, glconst.COMPILE_STATUS) c.ctx.GetShaderiv(v, s, gl.COMPILE_STATUS)
if v[0] == glconst.FALSE { if v[0] == gl.FALSE {
log := c.ctx.GetShaderInfoLog(s) log := c.ctx.GetShaderInfoLog(s)
return 0, fmt.Errorf("opengl: shader compile failed: %s", log) return 0, fmt.Errorf("opengl: shader compile failed: %s", log)
} }
@ -309,8 +308,8 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er
c.ctx.LinkProgram(p) c.ctx.LinkProgram(p)
v := make([]int32, 1) v := make([]int32, 1)
c.ctx.GetProgramiv(v, p, glconst.LINK_STATUS) c.ctx.GetProgramiv(v, p, gl.LINK_STATUS)
if v[0] == glconst.FALSE { if v[0] == gl.FALSE {
info := c.ctx.GetProgramInfoLog(p) info := c.ctx.GetProgramInfoLog(p)
return 0, fmt.Errorf("opengl: program error: %s", info) return 0, fmt.Errorf("opengl: program error: %s", info)
} }
@ -379,7 +378,7 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.
} }
func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) { func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) {
c.ctx.VertexAttribPointer(uint32(index), int32(size), glconst.FLOAT, false, int32(stride), offset) c.ctx.VertexAttribPointer(uint32(index), int32(size), gl.FLOAT, false, int32(stride), offset)
} }
func (c *context) enableVertexAttribArray(index int) { func (c *context) enableVertexAttribArray(index int) {
@ -392,34 +391,34 @@ func (c *context) disableVertexAttribArray(index int) {
func (c *context) newArrayBuffer(size int) buffer { func (c *context) newArrayBuffer(size int) buffer {
b := c.ctx.GenBuffers(1)[0] b := c.ctx.GenBuffers(1)[0]
c.ctx.BindBuffer(glconst.ARRAY_BUFFER, b) c.ctx.BindBuffer(gl.ARRAY_BUFFER, b)
c.ctx.BufferData(glconst.ARRAY_BUFFER, size, nil, glconst.DYNAMIC_DRAW) c.ctx.BufferData(gl.ARRAY_BUFFER, size, nil, gl.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) newElementArrayBuffer(size int) buffer { func (c *context) newElementArrayBuffer(size int) buffer {
b := c.ctx.GenBuffers(1)[0] b := c.ctx.GenBuffers(1)[0]
c.ctx.BindBuffer(glconst.ELEMENT_ARRAY_BUFFER, b) c.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b)
c.ctx.BufferData(glconst.ELEMENT_ARRAY_BUFFER, size, nil, glconst.DYNAMIC_DRAW) c.ctx.BufferData(gl.ELEMENT_ARRAY_BUFFER, size, nil, gl.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) bindArrayBuffer(b buffer) { func (c *context) bindArrayBuffer(b buffer) {
c.ctx.BindBuffer(glconst.ARRAY_BUFFER, uint32(b)) c.ctx.BindBuffer(gl.ARRAY_BUFFER, uint32(b))
} }
func (c *context) bindElementArrayBuffer(b buffer) { func (c *context) bindElementArrayBuffer(b buffer) {
c.ctx.BindBuffer(glconst.ELEMENT_ARRAY_BUFFER, uint32(b)) c.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(b))
} }
func (c *context) arrayBufferSubData(data []float32) { func (c *context) arrayBufferSubData(data []float32) {
s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*4) s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*4)
c.ctx.BufferSubData(glconst.ARRAY_BUFFER, 0, s) c.ctx.BufferSubData(gl.ARRAY_BUFFER, 0, s)
} }
func (c *context) elementArrayBufferSubData(data []uint16) { func (c *context) elementArrayBufferSubData(data []uint16) {
s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*2) s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*2)
c.ctx.BufferSubData(glconst.ELEMENT_ARRAY_BUFFER, 0, s) c.ctx.BufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, s)
} }
func (c *context) deleteBuffer(b buffer) { func (c *context) deleteBuffer(b buffer) {
@ -427,12 +426,12 @@ func (c *context) deleteBuffer(b buffer) {
} }
func (c *context) drawElements(len int, offsetInBytes int) { func (c *context) drawElements(len int, offsetInBytes int) {
c.ctx.DrawElements(glconst.TRIANGLES, int32(len), glconst.UNSIGNED_SHORT, offsetInBytes) c.ctx.DrawElements(gl.TRIANGLES, int32(len), gl.UNSIGNED_SHORT, offsetInBytes)
} }
func (c *context) maxTextureSizeImpl() int { func (c *context) maxTextureSizeImpl() int {
v := make([]int32, 1) v := make([]int32, 1)
c.ctx.GetIntegerv(v, glconst.MAX_TEXTURE_SIZE) c.ctx.GetIntegerv(v, gl.MAX_TEXTURE_SIZE)
return int(v[0]) return int(v[0])
} }
@ -447,27 +446,27 @@ func (c *context) needsRestoring() bool {
func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) { func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) {
c.bindTexture(t) c.bindTexture(t)
for _, a := range args { for _, a := range args {
c.ctx.TexSubImage2D(glconst.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), glconst.RGBA, glconst.UNSIGNED_BYTE, a.Pixels) c.ctx.TexSubImage2D(gl.TEXTURE_2D, 0, int32(a.X), int32(a.Y), int32(a.Width), int32(a.Height), gl.RGBA, gl.UNSIGNED_BYTE, a.Pixels)
} }
} }
func (c *context) enableStencilTest() { func (c *context) enableStencilTest() {
c.ctx.Enable(glconst.STENCIL_TEST) c.ctx.Enable(gl.STENCIL_TEST)
} }
func (c *context) disableStencilTest() { func (c *context) disableStencilTest() {
c.ctx.Disable(glconst.STENCIL_TEST) c.ctx.Disable(gl.STENCIL_TEST)
} }
func (c *context) beginStencilWithEvenOddRule() { func (c *context) beginStencilWithEvenOddRule() {
c.ctx.Clear(glconst.STENCIL_BUFFER_BIT) c.ctx.Clear(gl.STENCIL_BUFFER_BIT)
c.ctx.StencilFunc(glconst.ALWAYS, 0x00, 0xff) c.ctx.StencilFunc(gl.ALWAYS, 0x00, 0xff)
c.ctx.StencilOp(glconst.KEEP, glconst.KEEP, glconst.INVERT) c.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.INVERT)
c.ctx.ColorMask(false, false, false, false) c.ctx.ColorMask(false, false, false, false)
} }
func (c *context) endStencilWithEvenOddRule() { func (c *context) endStencilWithEvenOddRule() {
c.ctx.StencilFunc(glconst.NOTEQUAL, 0x00, 0xff) c.ctx.StencilFunc(gl.NOTEQUAL, 0x00, 0xff)
c.ctx.StencilOp(glconst.KEEP, glconst.KEEP, glconst.KEEP) c.ctx.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
c.ctx.ColorMask(true, true, true, true) c.ctx.ColorMask(true, true, true, true)
} }

View File

@ -22,7 +22,7 @@ import (
"syscall/js" "syscall/js"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/jsutil" "github.com/hajimehoshi/ebiten/v2/internal/jsutil"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
@ -108,7 +108,7 @@ func uint8ArrayToSlice(value js.Value, length int) []byte {
} }
type contextImpl struct { type contextImpl struct {
gl *gl gl *jsGL
canvas js.Value canvas js.Value
lastProgramID programID lastProgramID programID
webGLVersion webGLVersion webGLVersion webGLVersion
@ -153,7 +153,7 @@ func (c *context) initGL() error {
} }
} }
c.gl = c.newGL(gl) c.gl = c.newJSGL(gl)
return nil return nil
} }
@ -172,15 +172,14 @@ func (c *context) reset() error {
if c.gl.isContextLost.Invoke().Bool() { if c.gl.isContextLost.Invoke().Bool() {
return graphicsdriver.GraphicsNotReady return graphicsdriver.GraphicsNotReady
} }
gl := c.gl c.gl.enable.Invoke(gl.BLEND)
gl.enable.Invoke(glconst.BLEND) c.gl.enable.Invoke(gl.SCISSOR_TEST)
gl.enable.Invoke(glconst.SCISSOR_TEST)
c.blend(graphicsdriver.BlendSourceOver) c.blend(graphicsdriver.BlendSourceOver)
f := gl.getParameter.Invoke(glconst.FRAMEBUFFER_BINDING) f := c.gl.getParameter.Invoke(gl.FRAMEBUFFER_BINDING)
c.screenFramebuffer = framebufferNative(f) c.screenFramebuffer = framebufferNative(f)
if !c.usesWebGL2() { if !c.usesWebGL2() {
gl.getExtension.Invoke("OES_standard_derivatives") c.gl.getExtension.Invoke("OES_standard_derivatives")
} }
return nil return nil
} }
@ -190,38 +189,35 @@ func (c *context) blend(blend graphicsdriver.Blend) {
return return
} }
c.lastBlend = blend c.lastBlend = blend
gl := c.gl c.gl.blendFuncSeparate.Invoke(
gl.blendFuncSeparate.Invoke(
int(convertBlendFactor(blend.BlendFactorSourceRGB)), int(convertBlendFactor(blend.BlendFactorSourceRGB)),
int(convertBlendFactor(blend.BlendFactorDestinationRGB)), int(convertBlendFactor(blend.BlendFactorDestinationRGB)),
int(convertBlendFactor(blend.BlendFactorSourceAlpha)), int(convertBlendFactor(blend.BlendFactorSourceAlpha)),
int(convertBlendFactor(blend.BlendFactorDestinationAlpha)), int(convertBlendFactor(blend.BlendFactorDestinationAlpha)),
) )
gl.blendEquationSeparate.Invoke( c.gl.blendEquationSeparate.Invoke(
int(convertBlendOperation(blend.BlendOperationRGB)), int(convertBlendOperation(blend.BlendOperationRGB)),
int(convertBlendOperation(blend.BlendOperationAlpha)), int(convertBlendOperation(blend.BlendOperationAlpha)),
) )
} }
func (c *context) scissor(x, y, width, height int) { func (c *context) scissor(x, y, width, height int) {
gl := c.gl c.gl.scissor.Invoke(x, y, width, height)
gl.scissor.Invoke(x, y, width, height)
} }
func (c *context) newTexture(width, height int) (textureNative, error) { func (c *context) newTexture(width, height int) (textureNative, error) {
gl := c.gl t := c.gl.createTexture.Invoke()
t := gl.createTexture.Invoke()
if !t.Truthy() { if !t.Truthy() {
return textureNative(js.Null()), errors.New("opengl: createTexture failed") return textureNative(js.Null()), errors.New("opengl: createTexture failed")
} }
c.bindTexture(textureNative(t)) c.bindTexture(textureNative(t))
gl.texParameteri.Invoke(glconst.TEXTURE_2D, glconst.TEXTURE_MAG_FILTER, glconst.NEAREST) c.gl.texParameteri.Invoke(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri.Invoke(glconst.TEXTURE_2D, glconst.TEXTURE_MIN_FILTER, glconst.NEAREST) c.gl.texParameteri.Invoke(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.texParameteri.Invoke(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_S, glconst.CLAMP_TO_EDGE) c.gl.texParameteri.Invoke(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri.Invoke(glconst.TEXTURE_2D, glconst.TEXTURE_WRAP_T, glconst.CLAMP_TO_EDGE) c.gl.texParameteri.Invoke(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.pixelStorei.Invoke(glconst.UNPACK_ALIGNMENT, 4) c.gl.pixelStorei.Invoke(gl.UNPACK_ALIGNMENT, 4)
// Firefox warns the usage of textures without specifying pixels (#629) // Firefox warns the usage of textures without specifying pixels (#629)
// //
// Error: WebGL warning: drawElements: This operation requires zeroing texture data. This is slow. // Error: WebGL warning: drawElements: This operation requires zeroing texture data. This is slow.
@ -229,56 +225,48 @@ func (c *context) newTexture(width, height int) (textureNative, error) {
// In Ebitengine, textures are filled with pixels laster by the filter that ignores destination, so it is fine // In Ebitengine, textures are filled with pixels laster by the filter that ignores destination, so it is fine
// to leave textures as uninitialized here. Rather, extra memory allocating for initialization should be // to leave textures as uninitialized here. Rather, extra memory allocating for initialization should be
// avoided. // avoided.
gl.texImage2D.Invoke(glconst.TEXTURE_2D, 0, glconst.RGBA, width, height, 0, glconst.RGBA, glconst.UNSIGNED_BYTE, nil) c.gl.texImage2D.Invoke(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, nil)
return textureNative(t), nil return textureNative(t), nil
} }
func (c *context) bindFramebufferImpl(f framebufferNative) { func (c *context) bindFramebufferImpl(f framebufferNative) {
gl := c.gl c.gl.bindFramebuffer.Invoke(gl.FRAMEBUFFER, js.Value(f))
gl.bindFramebuffer.Invoke(glconst.FRAMEBUFFER, js.Value(f))
} }
func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) { func (c *context) framebufferPixels(buf []byte, f *framebuffer, x, y, width, height int) {
gl := c.gl
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
l := 4 * width * height l := 4 * width * height
p := jsutil.TemporaryUint8ArrayFromUint8Slice(l, nil) p := jsutil.TemporaryUint8ArrayFromUint8Slice(l, nil)
gl.readPixels.Invoke(x, y, width, height, glconst.RGBA, glconst.UNSIGNED_BYTE, p) c.gl.readPixels.Invoke(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, p)
copy(buf, uint8ArrayToSlice(p, l)) copy(buf, uint8ArrayToSlice(p, l))
} }
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) { func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {
gl := c.gl
c.bindFramebuffer(f.native) c.bindFramebuffer(f.native)
gl.bindBuffer.Invoke(glconst.PIXEL_PACK_BUFFER, js.Value(buffer)) c.gl.bindBuffer.Invoke(gl.PIXEL_PACK_BUFFER, js.Value(buffer))
// void gl.readPixels(x, y, width, height, format, type, GLintptr offset); // void gl.readPixels(x, y, width, height, format, type, GLintptr offset);
gl.readPixels.Invoke(0, 0, width, height, glconst.RGBA, glconst.UNSIGNED_BYTE, 0) c.gl.readPixels.Invoke(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0)
gl.bindBuffer.Invoke(glconst.PIXEL_PACK_BUFFER, nil) c.gl.bindBuffer.Invoke(gl.PIXEL_PACK_BUFFER, nil)
} }
func (c *context) activeTexture(idx int) { func (c *context) activeTexture(idx int) {
gl := c.gl c.gl.activeTexture.Invoke(gl.TEXTURE0 + idx)
gl.activeTexture.Invoke(glconst.TEXTURE0 + idx)
} }
func (c *context) bindTextureImpl(t textureNative) { func (c *context) bindTextureImpl(t textureNative) {
gl := c.gl c.gl.bindTexture.Invoke(gl.TEXTURE_2D, js.Value(t))
gl.bindTexture.Invoke(glconst.TEXTURE_2D, js.Value(t))
} }
func (c *context) deleteTexture(t textureNative) { func (c *context) deleteTexture(t textureNative) {
gl := c.gl if !c.gl.isTexture.Invoke(js.Value(t)).Bool() {
if !gl.isTexture.Invoke(js.Value(t)).Bool() {
return return
} }
if c.lastTexture.equal(t) { if c.lastTexture.equal(t) {
c.lastTexture = textureNative(js.Null()) c.lastTexture = textureNative(js.Null())
} }
gl.deleteTexture.Invoke(js.Value(t)) c.gl.deleteTexture.Invoke(js.Value(t))
} }
func (c *context) isTexture(t textureNative) bool { func (c *context) isTexture(t textureNative) bool {
@ -287,8 +275,7 @@ func (c *context) isTexture(t textureNative) bool {
} }
func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error) { func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error) {
gl := c.gl r := c.gl.createRenderbuffer.Invoke()
r := gl.createRenderbuffer.Invoke()
if !r.Truthy() { if !r.Truthy() {
return renderbufferNative(js.Null()), errors.New("opengl: createRenderbuffer failed") return renderbufferNative(js.Null()), errors.New("opengl: createRenderbuffer failed")
} }
@ -296,34 +283,31 @@ func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error)
c.bindRenderbuffer(renderbufferNative(r)) c.bindRenderbuffer(renderbufferNative(r))
// TODO: Is STENCIL_INDEX8 portable? // TODO: Is STENCIL_INDEX8 portable?
// https://stackoverflow.com/questions/11084961/binding-a-stencil-render-buffer-to-a-frame-buffer-in-opengl // https://stackoverflow.com/questions/11084961/binding-a-stencil-render-buffer-to-a-frame-buffer-in-opengl
gl.renderbufferStorage.Invoke(glconst.RENDERBUFFER, glconst.STENCIL_INDEX8, width, height) c.gl.renderbufferStorage.Invoke(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height)
return renderbufferNative(r), nil return renderbufferNative(r), nil
} }
func (c *context) bindRenderbufferImpl(r renderbufferNative) { func (c *context) bindRenderbufferImpl(r renderbufferNative) {
gl := c.gl c.gl.bindRenderbuffer.Invoke(gl.RENDERBUFFER, js.Value(r))
gl.bindRenderbuffer.Invoke(glconst.RENDERBUFFER, js.Value(r))
} }
func (c *context) deleteRenderbuffer(r renderbufferNative) { func (c *context) deleteRenderbuffer(r renderbufferNative) {
gl := c.gl if !c.gl.isRenderbuffer.Invoke(js.Value(r)).Bool() {
if !gl.isRenderbuffer.Invoke(js.Value(r)).Bool() {
return return
} }
if c.lastRenderbuffer.equal(r) { if c.lastRenderbuffer.equal(r) {
c.lastRenderbuffer = renderbufferNative(js.Null()) c.lastRenderbuffer = renderbufferNative(js.Null())
} }
gl.deleteRenderbuffer.Invoke(js.Value(r)) c.gl.deleteRenderbuffer.Invoke(js.Value(r))
} }
func (c *context) newFramebuffer(t textureNative) (framebufferNative, error) { func (c *context) newFramebuffer(t textureNative) (framebufferNative, error) {
gl := c.gl f := c.gl.createFramebuffer.Invoke()
f := gl.createFramebuffer.Invoke()
c.bindFramebuffer(framebufferNative(f)) c.bindFramebuffer(framebufferNative(f))
gl.framebufferTexture2D.Invoke(glconst.FRAMEBUFFER, glconst.COLOR_ATTACHMENT0, glconst.TEXTURE_2D, js.Value(t), 0) c.gl.framebufferTexture2D.Invoke(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, js.Value(t), 0)
if s := gl.checkFramebufferStatus.Invoke(glconst.FRAMEBUFFER); s.Int() != glconst.FRAMEBUFFER_COMPLETE { if s := c.gl.checkFramebufferStatus.Invoke(gl.FRAMEBUFFER); s.Int() != gl.FRAMEBUFFER_COMPLETE {
return framebufferNative(js.Null()), errors.New(fmt.Sprintf("opengl: creating framebuffer failed: %d", s.Int())) return framebufferNative(js.Null()), errors.New(fmt.Sprintf("opengl: creating framebuffer failed: %d", s.Int()))
} }
@ -331,24 +315,21 @@ func (c *context) newFramebuffer(t textureNative) (framebufferNative, error) {
} }
func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error { func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error {
gl := c.gl
c.bindFramebuffer(f) c.bindFramebuffer(f)
gl.framebufferRenderbuffer.Invoke(glconst.FRAMEBUFFER, glconst.STENCIL_ATTACHMENT, glconst.RENDERBUFFER, js.Value(r)) c.gl.framebufferRenderbuffer.Invoke(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, js.Value(r))
if s := gl.checkFramebufferStatus.Invoke(glconst.FRAMEBUFFER); s.Int() != glconst.FRAMEBUFFER_COMPLETE { if s := c.gl.checkFramebufferStatus.Invoke(gl.FRAMEBUFFER); s.Int() != gl.FRAMEBUFFER_COMPLETE {
return errors.New(fmt.Sprintf("opengl: framebufferRenderbuffer failed: %d", s.Int())) return errors.New(fmt.Sprintf("opengl: framebufferRenderbuffer failed: %d", s.Int()))
} }
return nil return nil
} }
func (c *context) setViewportImpl(width, height int) { func (c *context) setViewportImpl(width, height int) {
gl := c.gl c.gl.viewport.Invoke(0, 0, width, height)
gl.viewport.Invoke(0, 0, width, height)
} }
func (c *context) deleteFramebuffer(f framebufferNative) { func (c *context) deleteFramebuffer(f framebufferNative) {
gl := c.gl if !c.gl.isFramebuffer.Invoke(js.Value(f)).Bool() {
if !gl.isFramebuffer.Invoke(js.Value(f)).Bool() {
return return
} }
// If a framebuffer to be deleted is bound, a newly bound framebuffer // If a framebuffer to be deleted is bound, a newly bound framebuffer
@ -359,57 +340,54 @@ func (c *context) deleteFramebuffer(f framebufferNative) {
c.lastViewportWidth = 0 c.lastViewportWidth = 0
c.lastViewportHeight = 0 c.lastViewportHeight = 0
} }
gl.deleteFramebuffer.Invoke(js.Value(f)) c.gl.deleteFramebuffer.Invoke(js.Value(f))
} }
func (c *context) newVertexShader(source string) (shader, error) { func (c *context) newVertexShader(source string) (shader, error) {
return c.newShader(glconst.VERTEX_SHADER, source) return c.newShader(gl.VERTEX_SHADER, source)
} }
func (c *context) newFragmentShader(source string) (shader, error) { func (c *context) newFragmentShader(source string) (shader, error) {
return c.newShader(glconst.FRAGMENT_SHADER, source) return c.newShader(gl.FRAGMENT_SHADER, source)
} }
func (c *context) newShader(shaderType int, source string) (shader, error) { func (c *context) newShader(shaderType int, source string) (shader, error) {
gl := c.gl s := c.gl.createShader.Invoke(int(shaderType))
s := gl.createShader.Invoke(int(shaderType))
if !s.Truthy() { if !s.Truthy() {
return shader(js.Null()), fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType) return shader(js.Null()), fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
} }
gl.shaderSource.Invoke(js.Value(s), source) c.gl.shaderSource.Invoke(js.Value(s), source)
gl.compileShader.Invoke(js.Value(s)) c.gl.compileShader.Invoke(js.Value(s))
if !gl.getShaderParameter.Invoke(js.Value(s), glconst.COMPILE_STATUS).Bool() { if !c.gl.getShaderParameter.Invoke(js.Value(s), gl.COMPILE_STATUS).Bool() {
log := gl.getShaderInfoLog.Invoke(js.Value(s)) log := c.gl.getShaderInfoLog.Invoke(js.Value(s))
return shader(js.Null()), fmt.Errorf("opengl: shader compile failed: %s", log) return shader(js.Null()), fmt.Errorf("opengl: shader compile failed: %s", log)
} }
return shader(s), nil return shader(s), nil
} }
func (c *context) deleteShader(s shader) { func (c *context) deleteShader(s shader) {
gl := c.gl c.gl.deleteShader.Invoke(js.Value(s))
gl.deleteShader.Invoke(js.Value(s))
} }
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) { func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
gl := c.gl v := c.gl.createProgram.Invoke()
v := gl.createProgram.Invoke()
if !v.Truthy() { if !v.Truthy() {
return program{}, errors.New("opengl: glCreateProgram failed") return program{}, errors.New("opengl: glCreateProgram failed")
} }
for _, shader := range shaders { for _, shader := range shaders {
gl.attachShader.Invoke(v, js.Value(shader)) c.gl.attachShader.Invoke(v, js.Value(shader))
} }
for i, name := range attributes { for i, name := range attributes {
gl.bindAttribLocation.Invoke(v, i, name) c.gl.bindAttribLocation.Invoke(v, i, name)
} }
gl.linkProgram.Invoke(v) c.gl.linkProgram.Invoke(v)
if !gl.getProgramParameter.Invoke(v, glconst.LINK_STATUS).Bool() { if !c.gl.getProgramParameter.Invoke(v, gl.LINK_STATUS).Bool() {
info := gl.getProgramInfoLog.Invoke(v).String() info := c.gl.getProgramInfoLog.Invoke(v).String()
return program{}, fmt.Errorf("opengl: program error: %s", info) return program{}, fmt.Errorf("opengl: program error: %s", info)
} }
@ -422,37 +400,32 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er
} }
func (c *context) useProgram(p program) { func (c *context) useProgram(p program) {
gl := c.gl c.gl.useProgram.Invoke(p.value)
gl.useProgram.Invoke(p.value)
} }
func (c *context) deleteProgram(p program) { func (c *context) deleteProgram(p program) {
c.locationCache.deleteProgram(p) c.locationCache.deleteProgram(p)
gl := c.gl if !c.gl.isProgram.Invoke(p.value).Bool() {
if !gl.isProgram.Invoke(p.value).Bool() {
return return
} }
gl.deleteProgram.Invoke(p.value) c.gl.deleteProgram.Invoke(p.value)
} }
func (c *context) getUniformLocationImpl(p program, location string) uniformLocation { func (c *context) getUniformLocationImpl(p program, location string) uniformLocation {
gl := c.gl return uniformLocation(c.gl.getUniformLocation.Invoke(p.value, location))
return uniformLocation(gl.getUniformLocation.Invoke(p.value, location))
} }
func (c *context) uniformInt(p program, location string, v int) bool { func (c *context) uniformInt(p program, location string, v int) bool {
gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location) l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) { if l.equal(invalidUniform) {
return false return false
} }
gl.uniform1i.Invoke(js.Value(l), v) c.gl.uniform1i.Invoke(js.Value(l), v)
return true return true
} }
func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.Type) bool { func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.Type) bool {
gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location) l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) { if l.equal(invalidUniform) {
return false return false
@ -467,58 +440,58 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.
case shaderir.Float: case shaderir.Float:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniform1fv.Invoke(js.Value(l), arr, 0, len(v)) c.gl.uniform1fv.Invoke(js.Value(l), arr, 0, len(v))
} else { } else {
gl.uniform1fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) c.gl.uniform1fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
} }
case shaderir.Int: case shaderir.Int:
arr := jsutil.TemporaryInt32Array(len(v), uint32sToInt32s(v)) arr := jsutil.TemporaryInt32Array(len(v), uint32sToInt32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniform1iv.Invoke(js.Value(l), arr, 0, len(v)) c.gl.uniform1iv.Invoke(js.Value(l), arr, 0, len(v))
} else { } else {
gl.uniform1iv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) c.gl.uniform1iv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
} }
case shaderir.Vec2: case shaderir.Vec2:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniform2fv.Invoke(js.Value(l), arr, 0, len(v)) c.gl.uniform2fv.Invoke(js.Value(l), arr, 0, len(v))
} else { } else {
gl.uniform2fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) c.gl.uniform2fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
} }
case shaderir.Vec3: case shaderir.Vec3:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniform3fv.Invoke(js.Value(l), arr, 0, len(v)) c.gl.uniform3fv.Invoke(js.Value(l), arr, 0, len(v))
} else { } else {
gl.uniform3fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) c.gl.uniform3fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
} }
case shaderir.Vec4: case shaderir.Vec4:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniform4fv.Invoke(js.Value(l), arr, 0, len(v)) c.gl.uniform4fv.Invoke(js.Value(l), arr, 0, len(v))
} else { } else {
gl.uniform4fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v))) c.gl.uniform4fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
} }
case shaderir.Mat2: case shaderir.Mat2:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr, 0, len(v)) c.gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr, 0, len(v))
} else { } else {
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) c.gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
} }
case shaderir.Mat3: case shaderir.Mat3:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr, 0, len(v)) c.gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr, 0, len(v))
} else { } else {
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) c.gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
} }
case shaderir.Mat4: case shaderir.Mat4:
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v)) arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
if c.usesWebGL2() { if c.usesWebGL2() {
gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr, 0, len(v)) c.gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr, 0, len(v))
} else { } else {
gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v))) c.gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
} }
default: default:
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String())) panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
@ -528,86 +501,73 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.
} }
func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) { func (c *context) vertexAttribPointer(index int, size int, stride int, offset int) {
gl := c.gl c.gl.vertexAttribPointer.Invoke(index, size, gl.FLOAT, false, stride, offset)
gl.vertexAttribPointer.Invoke(index, size, glconst.FLOAT, false, stride, offset)
} }
func (c *context) enableVertexAttribArray(index int) { func (c *context) enableVertexAttribArray(index int) {
gl := c.gl c.gl.enableVertexAttribArray.Invoke(index)
gl.enableVertexAttribArray.Invoke(index)
} }
func (c *context) disableVertexAttribArray(index int) { func (c *context) disableVertexAttribArray(index int) {
gl := c.gl c.gl.disableVertexAttribArray.Invoke(index)
gl.disableVertexAttribArray.Invoke(index)
} }
func (c *context) newArrayBuffer(size int) buffer { func (c *context) newArrayBuffer(size int) buffer {
gl := c.gl b := c.gl.createBuffer.Invoke()
b := gl.createBuffer.Invoke() c.gl.bindBuffer.Invoke(gl.ARRAY_BUFFER, js.Value(b))
gl.bindBuffer.Invoke(glconst.ARRAY_BUFFER, js.Value(b)) c.gl.bufferData.Invoke(gl.ARRAY_BUFFER, size, gl.DYNAMIC_DRAW)
gl.bufferData.Invoke(glconst.ARRAY_BUFFER, size, glconst.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) newElementArrayBuffer(size int) buffer { func (c *context) newElementArrayBuffer(size int) buffer {
gl := c.gl b := c.gl.createBuffer.Invoke()
b := gl.createBuffer.Invoke() c.gl.bindBuffer.Invoke(gl.ELEMENT_ARRAY_BUFFER, js.Value(b))
gl.bindBuffer.Invoke(glconst.ELEMENT_ARRAY_BUFFER, js.Value(b)) c.gl.bufferData.Invoke(gl.ELEMENT_ARRAY_BUFFER, size, gl.DYNAMIC_DRAW)
gl.bufferData.Invoke(glconst.ELEMENT_ARRAY_BUFFER, size, glconst.DYNAMIC_DRAW)
return buffer(b) return buffer(b)
} }
func (c *context) bindArrayBuffer(b buffer) { func (c *context) bindArrayBuffer(b buffer) {
gl := c.gl c.gl.bindBuffer.Invoke(gl.ARRAY_BUFFER, js.Value(b))
gl.bindBuffer.Invoke(glconst.ARRAY_BUFFER, js.Value(b))
} }
func (c *context) bindElementArrayBuffer(b buffer) { func (c *context) bindElementArrayBuffer(b buffer) {
gl := c.gl c.gl.bindBuffer.Invoke(gl.ELEMENT_ARRAY_BUFFER, js.Value(b))
gl.bindBuffer.Invoke(glconst.ELEMENT_ARRAY_BUFFER, js.Value(b))
} }
func (c *context) arrayBufferSubData(data []float32) { func (c *context) arrayBufferSubData(data []float32) {
gl := c.gl
l := len(data) * 4 l := len(data) * 4
arr := jsutil.TemporaryUint8ArrayFromFloat32Slice(l, data) arr := jsutil.TemporaryUint8ArrayFromFloat32Slice(l, data)
if c.usesWebGL2() { if c.usesWebGL2() {
gl.bufferSubData.Invoke(glconst.ARRAY_BUFFER, 0, arr, 0, l) c.gl.bufferSubData.Invoke(gl.ARRAY_BUFFER, 0, arr, 0, l)
} else { } else {
gl.bufferSubData.Invoke(glconst.ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) c.gl.bufferSubData.Invoke(gl.ARRAY_BUFFER, 0, arr.Call("subarray", 0, l))
} }
} }
func (c *context) elementArrayBufferSubData(data []uint16) { func (c *context) elementArrayBufferSubData(data []uint16) {
gl := c.gl
l := len(data) * 2 l := len(data) * 2
arr := jsutil.TemporaryUint8ArrayFromUint16Slice(l, data) arr := jsutil.TemporaryUint8ArrayFromUint16Slice(l, data)
if c.usesWebGL2() { if c.usesWebGL2() {
gl.bufferSubData.Invoke(glconst.ELEMENT_ARRAY_BUFFER, 0, arr, 0, l) c.gl.bufferSubData.Invoke(gl.ELEMENT_ARRAY_BUFFER, 0, arr, 0, l)
} else { } else {
gl.bufferSubData.Invoke(glconst.ELEMENT_ARRAY_BUFFER, 0, arr.Call("subarray", 0, l)) c.gl.bufferSubData.Invoke(gl.ELEMENT_ARRAY_BUFFER, 0, arr.Call("subarray", 0, l))
} }
} }
func (c *context) deleteBuffer(b buffer) { func (c *context) deleteBuffer(b buffer) {
gl := c.gl c.gl.deleteBuffer.Invoke(js.Value(b))
gl.deleteBuffer.Invoke(js.Value(b))
} }
func (c *context) drawElements(len int, offsetInBytes int) { func (c *context) drawElements(len int, offsetInBytes int) {
gl := c.gl c.gl.drawElements.Invoke(gl.TRIANGLES, len, gl.UNSIGNED_SHORT, offsetInBytes)
gl.drawElements.Invoke(glconst.TRIANGLES, len, glconst.UNSIGNED_SHORT, offsetInBytes)
} }
func (c *context) maxTextureSizeImpl() int { func (c *context) maxTextureSizeImpl() int {
gl := c.gl return c.gl.getParameter.Invoke(gl.MAX_TEXTURE_SIZE).Int()
return gl.getParameter.Invoke(glconst.MAX_TEXTURE_SIZE).Int()
} }
func (c *context) flush() { func (c *context) flush() {
gl := c.gl c.gl.flush.Invoke()
gl.flush.Invoke()
} }
func (c *context) needsRestoring() bool { func (c *context) needsRestoring() bool {
@ -617,44 +577,39 @@ func (c *context) needsRestoring() bool {
func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) { func (c *context) texSubImage2D(t textureNative, args []*graphicsdriver.WritePixelsArgs) {
c.bindTexture(t) c.bindTexture(t)
gl := c.gl
for _, a := range args { for _, a := range args {
arr := jsutil.TemporaryUint8ArrayFromUint8Slice(len(a.Pixels), a.Pixels) arr := jsutil.TemporaryUint8ArrayFromUint8Slice(len(a.Pixels), a.Pixels)
if c.usesWebGL2() { if c.usesWebGL2() {
// void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
// GLsizei width, GLsizei height, // GLsizei width, GLsizei height,
// GLenum format, GLenum type, ArrayBufferView pixels, srcOffset); // GLenum format, GLenum type, ArrayBufferView pixels, srcOffset);
gl.texSubImage2D.Invoke(glconst.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, glconst.RGBA, glconst.UNSIGNED_BYTE, arr, 0) c.gl.texSubImage2D.Invoke(gl.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gl.RGBA, gl.UNSIGNED_BYTE, arr, 0)
} else { } else {
// void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
// GLsizei width, GLsizei height, // GLsizei width, GLsizei height,
// GLenum format, GLenum type, ArrayBufferView? pixels); // GLenum format, GLenum type, ArrayBufferView? pixels);
gl.texSubImage2D.Invoke(glconst.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, glconst.RGBA, glconst.UNSIGNED_BYTE, arr) c.gl.texSubImage2D.Invoke(gl.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, gl.RGBA, gl.UNSIGNED_BYTE, arr)
} }
} }
} }
func (c *context) enableStencilTest() { func (c *context) enableStencilTest() {
gl := c.gl c.gl.enable.Invoke(gl.STENCIL_TEST)
gl.enable.Invoke(glconst.STENCIL_TEST)
} }
func (c *context) disableStencilTest() { func (c *context) disableStencilTest() {
gl := c.gl c.gl.disable.Invoke(gl.STENCIL_TEST)
gl.disable.Invoke(glconst.STENCIL_TEST)
} }
func (c *context) beginStencilWithEvenOddRule() { func (c *context) beginStencilWithEvenOddRule() {
gl := c.gl c.gl.clear.Invoke(gl.STENCIL_BUFFER_BIT)
gl.clear.Invoke(glconst.STENCIL_BUFFER_BIT) c.gl.stencilFunc.Invoke(gl.ALWAYS, 0x00, 0xff)
gl.stencilFunc.Invoke(glconst.ALWAYS, 0x00, 0xff) c.gl.stencilOp.Invoke(gl.KEEP, gl.KEEP, gl.INVERT)
gl.stencilOp.Invoke(glconst.KEEP, glconst.KEEP, glconst.INVERT) c.gl.colorMask.Invoke(false, false, false, false)
gl.colorMask.Invoke(false, false, false, false)
} }
func (c *context) endStencilWithEvenOddRule() { func (c *context) endStencilWithEvenOddRule() {
gl := c.gl c.gl.stencilFunc.Invoke(gl.NOTEQUAL, 0x00, 0xff)
gl.stencilFunc.Invoke(glconst.NOTEQUAL, 0x00, 0xff) c.gl.stencilOp.Invoke(gl.KEEP, gl.KEEP, gl.KEEP)
gl.stencilOp.Invoke(glconst.KEEP, glconst.KEEP, glconst.KEEP) c.gl.colorMask.Invoke(true, true, true, true)
gl.colorMask.Invoke(true, true, true, true)
} }

View File

@ -12,9 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// Package glconst provides constants to the implementations of Go bindings to package gl
// OpenGL and OpenGL ES, for packages gl and gles respectively.
package glconst
const ( const (
ALWAYS = 0x0207 ALWAYS = 0x0207

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//go:build !android && !ios && !js && !opengles
package gl package gl
import ( import (
@ -14,7 +16,7 @@ import (
// //
// var data []byte // var data []byte
// ... // ...
// gl.TexImage2D(glconst.TEXTURE_2D, ..., glconst.UNSIGNED_BYTE, gl.Ptr(&data[0])) // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
func Ptr(data any) unsafe.Pointer { func Ptr(data any) unsafe.Pointer {
if data == nil { if data == nil {
return unsafe.Pointer(nil) return unsafe.Pointer(nil)

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//go:build !darwin && !windows //go:build !android && !darwin && !js && !windows && !opengles
package gl package gl

View File

@ -14,7 +14,7 @@
//go:build android || ios || opengles //go:build android || ios || opengles
package gles package gl
// #cgo !darwin CFLAGS: -Dos_notdarwin // #cgo !darwin CFLAGS: -Dos_notdarwin
// #cgo darwin CFLAGS: -Dos_darwin // #cgo darwin CFLAGS: -Dos_darwin
@ -36,15 +36,13 @@ import "C"
import ( import (
"unsafe" "unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst"
) )
func glBool(x bool) C.GLboolean { func glBool(x bool) C.GLboolean {
if x { if x {
return glconst.TRUE return TRUE
} }
return glconst.FALSE return FALSE
} }
type DefaultContext struct{} type DefaultContext struct{}
@ -213,7 +211,7 @@ func (DefaultContext) GetIntegerv(dst []int32, pname uint32) {
func (d DefaultContext) GetProgramInfoLog(program uint32) string { func (d DefaultContext) GetProgramInfoLog(program uint32) string {
buflens := make([]int32, 1) buflens := make([]int32, 1)
d.GetProgramiv(buflens, program, glconst.INFO_LOG_LENGTH) d.GetProgramiv(buflens, program, INFO_LOG_LENGTH)
buflen := buflens[0] buflen := buflens[0]
if buflen == 0 { if buflen == 0 {
return "" return ""
@ -230,7 +228,7 @@ func (DefaultContext) GetProgramiv(dst []int32, program uint32, pname uint32) {
func (d DefaultContext) GetShaderInfoLog(shader uint32) string { func (d DefaultContext) GetShaderInfoLog(shader uint32) string {
buflens := make([]int32, 1) buflens := make([]int32, 1)
d.GetShaderiv(buflens, shader, glconst.INFO_LOG_LENGTH) d.GetShaderiv(buflens, shader, INFO_LOG_LENGTH)
buflen := buflens[0] buflen := buflens[0]
if buflen == 0 { if buflen == 0 {
return "" return ""
@ -252,19 +250,19 @@ func (DefaultContext) GetUniformLocation(program uint32, name string) int32 {
} }
func (DefaultContext) IsFramebuffer(framebuffer uint32) bool { func (DefaultContext) IsFramebuffer(framebuffer uint32) bool {
return C.glIsFramebuffer(C.GLuint(framebuffer)) != glconst.FALSE return C.glIsFramebuffer(C.GLuint(framebuffer)) != FALSE
} }
func (DefaultContext) IsProgram(program uint32) bool { func (DefaultContext) IsProgram(program uint32) bool {
return C.glIsProgram(C.GLuint(program)) != glconst.FALSE return C.glIsProgram(C.GLuint(program)) != FALSE
} }
func (DefaultContext) IsRenderbuffer(renderbuffer uint32) bool { func (DefaultContext) IsRenderbuffer(renderbuffer uint32) bool {
return C.glIsRenderbuffer(C.GLuint(renderbuffer)) != glconst.FALSE return C.glIsRenderbuffer(C.GLuint(renderbuffer)) != FALSE
} }
func (DefaultContext) IsTexture(texture uint32) bool { func (DefaultContext) IsTexture(texture uint32) bool {
return C.glIsTexture(C.GLuint(texture)) != glconst.FALSE return C.glIsTexture(C.GLuint(texture)) != FALSE
} }
func (DefaultContext) LinkProgram(program uint32) { func (DefaultContext) LinkProgram(program uint32) {

View File

@ -14,7 +14,7 @@
//go:build android || ios //go:build android || ios
package gles package gl
import ( import (
"golang.org/x/mobile/gl" "golang.org/x/mobile/gl"
@ -76,7 +76,7 @@ func (g *GomobileContext) BufferData(target uint32, size int, data []byte, usage
g.ctx.BufferInit(gl.Enum(target), size, gl.Enum(usage)) g.ctx.BufferInit(gl.Enum(target), size, gl.Enum(usage))
} else { } else {
if size != len(data) { if size != len(data) {
panic("gles: size and len(data) must be same at BufferData") panic("gl: size and len(data) must be same at BufferData")
} }
g.ctx.BufferData(gl.Enum(target), data, gl.Enum(usage)) g.ctx.BufferData(gl.Enum(target), data, gl.Enum(usage))
} }
@ -320,21 +320,21 @@ func (g *GomobileContext) Uniform4fv(location int32, value []float32) {
func (g *GomobileContext) UniformMatrix2fv(location int32, transpose bool, value []float32) { func (g *GomobileContext) UniformMatrix2fv(location int32, transpose bool, value []float32) {
if transpose { if transpose {
panic("gles: UniformMatrix2fv with transpose is not implemented") panic("gl: UniformMatrix2fv with transpose is not implemented")
} }
g.ctx.UniformMatrix2fv(gl.Uniform{Value: location}, value) g.ctx.UniformMatrix2fv(gl.Uniform{Value: location}, value)
} }
func (g *GomobileContext) UniformMatrix3fv(location int32, transpose bool, value []float32) { func (g *GomobileContext) UniformMatrix3fv(location int32, transpose bool, value []float32) {
if transpose { if transpose {
panic("gles: UniformMatrix3fv with transpose is not implemented") panic("gl: UniformMatrix3fv with transpose is not implemented")
} }
g.ctx.UniformMatrix3fv(gl.Uniform{Value: location}, value) g.ctx.UniformMatrix3fv(gl.Uniform{Value: location}, value)
} }
func (g *GomobileContext) UniformMatrix4fv(location int32, transpose bool, value []float32) { func (g *GomobileContext) UniformMatrix4fv(location int32, transpose bool, value []float32) {
if transpose { if transpose {
panic("gles: UniformMatrix4fv with transpose is not implemented") panic("gl: UniformMatrix4fv with transpose is not implemented")
} }
g.ctx.UniformMatrix4fv(gl.Uniform{Value: location}, value) g.ctx.UniformMatrix4fv(gl.Uniform{Value: location}, value)
} }

View File

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// Package gles implements Go bindings to OpenGL ES. package gl
package gles
type Context interface { type Context interface {
ActiveTexture(texture uint32) ActiveTexture(texture uint32)

View File

@ -9,7 +9,7 @@
// This document is licensed under the SGI Free Software B License. // This document is licensed under the SGI Free Software B License.
// For details, see http://oss.sgi.com/projects/FreeB. // For details, see http://oss.sgi.com/projects/FreeB.
//go:build !js //go:build !android && !ios && !js && !opengles
// Package gl implements Go bindings to OpenGL. // Package gl implements Go bindings to OpenGL.
package gl package gl

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//go:build !darwin && !windows //go:build !android && !darwin && !js && !windows && !opengles
package gl package gl
@ -320,8 +320,6 @@ import "C"
import ( import (
"errors" "errors"
"unsafe" "unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst"
) )
var ( var (
@ -578,22 +576,22 @@ func GetUniformLocation(program uint32, name *uint8) int32 {
func IsFramebufferEXT(framebuffer uint32) bool { func IsFramebufferEXT(framebuffer uint32) bool {
ret := C.glowIsFramebufferEXT(gpIsFramebufferEXT, (C.GLuint)(framebuffer)) ret := C.glowIsFramebufferEXT(gpIsFramebufferEXT, (C.GLuint)(framebuffer))
return ret == glconst.TRUE return ret == TRUE
} }
func IsProgram(program uint32) bool { func IsProgram(program uint32) bool {
ret := C.glowIsProgram(gpIsProgram, (C.GLuint)(program)) ret := C.glowIsProgram(gpIsProgram, (C.GLuint)(program))
return ret == glconst.TRUE return ret == TRUE
} }
func IsRenderbufferEXT(renderbuffer uint32) bool { func IsRenderbufferEXT(renderbuffer uint32) bool {
ret := C.glowIsRenderbufferEXT(gpIsRenderbufferEXT, (C.GLuint)(renderbuffer)) ret := C.glowIsRenderbufferEXT(gpIsRenderbufferEXT, (C.GLuint)(renderbuffer))
return ret == glconst.TRUE return ret == TRUE
} }
func IsTexture(texture uint32) bool { func IsTexture(texture uint32) bool {
ret := C.glowIsTexture(gpIsTexture, (C.GLuint)(texture)) ret := C.glowIsTexture(gpIsTexture, (C.GLuint)(texture))
return ret == glconst.TRUE return ret == TRUE
} }
func LinkProgram(program uint32) { func LinkProgram(program uint32) {

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//go:build !darwin && !windows //go:build !android && !darwin && !js && !windows && !opengles
// This file implements GlowGetProcAddress for every supported platform. The // This file implements GlowGetProcAddress for every supported platform. The
// correct version is chosen automatically based on build tags: // correct version is chosen automatically based on build tags:
@ -40,6 +40,7 @@ package gl
#endif #endif
*/ */
import "C" import "C"
import "unsafe" import "unsafe"
func getProcAddress(namea string) unsafe.Pointer { func getProcAddress(namea string) unsafe.Pointer {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package gles package gl
// #include <stdlib.h> // #include <stdlib.h>
import "C" import "C"

View File

@ -18,7 +18,7 @@ import (
"syscall/js" "syscall/js"
) )
type gl struct { type jsGL struct {
activeTexture js.Value activeTexture js.Value
attachShader js.Value attachShader js.Value
bindAttribLocation js.Value bindAttribLocation js.Value
@ -92,10 +92,10 @@ type gl struct {
viewport js.Value viewport js.Value
} }
func (c *context) newGL(v js.Value) *gl { func (c *context) newJSGL(v js.Value) *jsGL {
// Passing a Go string to the JS world is expensive. This causes conversion to UTF-16 (#1438). // Passing a Go string to the JS world is expensive. This causes conversion to UTF-16 (#1438).
// In order to reduce the cost when calling functions, create the function objects by bind and use them. // In order to reduce the cost when calling functions, create the function objects by bind and use them.
g := &gl{ g := &jsGL{
activeTexture: v.Get("activeTexture").Call("bind", v), activeTexture: v.Get("activeTexture").Call("bind", v),
attachShader: v.Get("attachShader").Call("bind", v), attachShader: v.Get("attachShader").Call("bind", v),
bindAttribLocation: v.Get("bindAttribLocation").Call("bind", v), bindAttribLocation: v.Get("bindAttribLocation").Call("bind", v),

View File

@ -17,10 +17,10 @@
package opengl package opengl
import ( import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gles" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
) )
func (g *Graphics) init() error { func (g *Graphics) init() error {
g.context.ctx = gles.DefaultContext{} g.context.ctx = gl.DefaultContext{}
return nil return nil
} }

View File

@ -17,11 +17,11 @@
package opengl package opengl
import ( import (
"golang.org/x/mobile/gl" mgl "golang.org/x/mobile/gl"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gles" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
) )
func (g *Graphics) SetGomobileGLContext(context gl.Context) { func (g *Graphics) SetGomobileGLContext(context mgl.Context) {
g.context.ctx = gles.NewGomobileContext(context) g.context.ctx = gl.NewGomobileContext(context)
} }