vendor dependencies, make some changes to how input is done

This commit is contained in:
2026-06-15 18:54:00 +02:00
parent 535130933c
commit 4800eb28d9
759 changed files with 360941 additions and 30 deletions
@@ -0,0 +1,498 @@
// Copyright 2016 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
import (
"errors"
"fmt"
"image"
"sync"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
)
type blendFactor int
type blendOperation int
func convertBlendFactor(f graphicsdriver.BlendFactor) blendFactor {
switch f {
case graphicsdriver.BlendFactorZero:
return gl.ZERO
case graphicsdriver.BlendFactorOne:
return gl.ONE
case graphicsdriver.BlendFactorSourceColor:
return gl.SRC_COLOR
case graphicsdriver.BlendFactorOneMinusSourceColor:
return gl.ONE_MINUS_SRC_COLOR
case graphicsdriver.BlendFactorSourceAlpha:
return gl.SRC_ALPHA
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
return gl.ONE_MINUS_SRC_ALPHA
case graphicsdriver.BlendFactorDestinationColor:
return gl.DST_COLOR
case graphicsdriver.BlendFactorOneMinusDestinationColor:
return gl.ONE_MINUS_DST_COLOR
case graphicsdriver.BlendFactorDestinationAlpha:
return gl.DST_ALPHA
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
return gl.ONE_MINUS_DST_ALPHA
case graphicsdriver.BlendFactorSourceAlphaSaturated:
return gl.SRC_ALPHA_SATURATE
default:
panic(fmt.Sprintf("opengl: invalid blend factor %d", f))
}
}
func convertBlendOperation(o graphicsdriver.BlendOperation) blendOperation {
switch o {
case graphicsdriver.BlendOperationAdd:
return gl.FUNC_ADD
case graphicsdriver.BlendOperationSubtract:
return gl.FUNC_SUBTRACT
case graphicsdriver.BlendOperationReverseSubtract:
return gl.FUNC_REVERSE_SUBTRACT
case graphicsdriver.BlendOperationMin:
return gl.MIN
case graphicsdriver.BlendOperationMax:
return gl.MAX
default:
panic(fmt.Sprintf("opengl: invalid blend operation %d", o))
}
}
type (
textureNative uint32
renderbufferNative uint32
framebufferNative uint32
shader uint32
program uint32
buffer uint32
)
type (
uniformLocation int32
attribLocation int32
)
const (
invalidFramebuffer = (1 << 32) - 1
invalidUniform = -1
)
type context struct {
ctx gl.Context
locationCache *locationCache
screenFramebuffer framebufferNative // This might not be the default frame buffer '0' (e.g. iOS).
lastFramebuffer framebufferNative
lastTexture textureNative
lastRenderbuffer renderbufferNative
lastViewportWidth int
lastViewportHeight int
lastBlend graphicsdriver.Blend
maxTextureSize int
maxTextureSizeOnce sync.Once
highp bool
highpOnce sync.Once
initOnce sync.Once
}
func (c *context) bindTexture(t textureNative) {
if c.lastTexture == t {
return
}
c.ctx.BindTexture(gl.TEXTURE_2D, uint32(t))
c.lastTexture = t
}
func (c *context) bindRenderbuffer(r renderbufferNative) {
if c.lastRenderbuffer == r {
return
}
c.ctx.BindRenderbuffer(gl.RENDERBUFFER, uint32(r))
c.lastRenderbuffer = r
}
func (c *context) bindFramebuffer(f framebufferNative) {
if c.lastFramebuffer == f {
return
}
c.ctx.BindFramebuffer(gl.FRAMEBUFFER, uint32(f))
c.lastFramebuffer = f
}
func (c *context) setViewport(f *framebuffer) {
c.bindFramebuffer(f.native)
if c.lastViewportWidth == f.width && c.lastViewportHeight == f.height {
return
}
// On some environments, viewport size must be within the framebuffer size.
// e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691).
// Use the same size of the framebuffer here.
c.ctx.Viewport(0, 0, int32(f.width), int32(f.height))
// glViewport must be called at least at every frame on iOS.
// As the screen framebuffer is the last render target, next SetViewport should be
// the first call at a frame.
if f.native == c.screenFramebuffer {
c.lastViewportWidth = 0
c.lastViewportHeight = 0
} else {
c.lastViewportWidth = f.width
c.lastViewportHeight = f.height
}
}
func (c *context) newScreenFramebuffer(width, height int) *framebuffer {
return &framebuffer{
native: c.screenFramebuffer,
width: width,
height: height,
}
}
func (c *context) getMaxTextureSize() int {
c.maxTextureSizeOnce.Do(func() {
c.maxTextureSize = c.ctx.GetInteger(gl.MAX_TEXTURE_SIZE)
})
return c.maxTextureSize
}
func (c *context) reset() error {
var err1 error
c.initOnce.Do(func() {
// Load OpenGL functions after WGL is initialized especially for Windows (#2452).
if err := c.ctx.LoadFunctions(); err != nil {
err1 = err
return
}
})
if err1 != nil {
return err1
}
c.locationCache = newLocationCache()
c.lastTexture = 0
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
c.lastBlend = graphicsdriver.Blend{}
c.ctx.Enable(gl.BLEND)
c.ctx.Enable(gl.SCISSOR_TEST)
c.blend(graphicsdriver.BlendSourceOver)
c.screenFramebuffer = framebufferNative(c.ctx.GetInteger(gl.FRAMEBUFFER_BINDING))
// TODO: Need to update screenFramebufferWidth/Height?
return nil
}
func (c *context) blend(blend graphicsdriver.Blend) {
if c.lastBlend == blend {
return
}
c.lastBlend = blend
c.ctx.BlendFuncSeparate(
uint32(convertBlendFactor(blend.BlendFactorSourceRGB)),
uint32(convertBlendFactor(blend.BlendFactorDestinationRGB)),
uint32(convertBlendFactor(blend.BlendFactorSourceAlpha)),
uint32(convertBlendFactor(blend.BlendFactorDestinationAlpha)),
)
c.ctx.BlendEquationSeparate(
uint32(convertBlendOperation(blend.BlendOperationRGB)),
uint32(convertBlendOperation(blend.BlendOperationAlpha)),
)
}
func (c *context) newTexture(width, height int) (textureNative, error) {
t := c.ctx.CreateTexture()
if t <= 0 {
return 0, errors.New("opengl: creating texture failed")
}
c.bindTexture(textureNative(t))
c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
c.ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
c.ctx.PixelStorei(gl.UNPACK_ALIGNMENT, 4)
// Firefox warns the usage of textures without specifying pixels (#629, #2077)
//
// Error: WebGL warning: drawElements: This operation requires zeroing texture data. This is slow.
//
// In Ebitengine, textures are filled with pixels later by the filter that ignores destination, so it is fine
// to leave textures as uninitialized here. Rather, extra memory allocating for initialization should be
// avoided.
//
// See also https://stackoverflow.com/questions/57734645.
c.ctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, nil)
return textureNative(t), nil
}
func (c *context) framebufferPixels(buf []byte, f *framebuffer, region image.Rectangle) error {
if got, want := len(buf), 4*region.Dx()*region.Dy(); got != want {
return fmt.Errorf("opengl: len(buf) must be %d but was %d at framebufferPixels", got, want)
}
c.ctx.Flush()
c.bindFramebuffer(f.native)
x := int32(region.Min.X)
y := int32(region.Min.Y)
width := int32(region.Dx())
height := int32(region.Dy())
c.ctx.ReadPixels(buf, x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE)
return nil
}
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {
c.ctx.Flush()
c.bindFramebuffer(f.native)
c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, uint32(buffer))
c.ctx.ReadPixels(nil, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE)
c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, 0)
}
func (c *context) deleteTexture(t textureNative) {
if c.lastTexture == t {
c.lastTexture = 0
}
c.ctx.DeleteTexture(uint32(t))
}
func (c *context) newRenderbuffer(width, height int) (renderbufferNative, error) {
r := c.ctx.CreateRenderbuffer()
if r <= 0 {
return 0, errors.New("opengl: creating renderbuffer failed")
}
renderbuffer := renderbufferNative(r)
c.bindRenderbuffer(renderbuffer)
var stencilFormat uint32
if c.ctx.IsES() {
// https://docs.gl/es2/glRenderbufferStorage
// > Must be one of the following symbolic constants: GL_RGBA4, GL_RGB565, GL_RGB5_A1,
// > GL_DEPTH_COMPONENT16, or GL_STENCIL_INDEX8.
//
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/renderbufferStorage
// > A GLenum specifying the internal format of the renderbuffer. Possible values:
// > * gl.RGBA4: 4 red bits, 4 green bits, 4 blue bits 4 alpha bits.
// > * gl.RGB565: 5 red bits, 6 green bits, 5 blue bits.
// > * gl.RGB5_A1: 5 red bits, 5 green bits, 5 blue bits, 1 alpha bit.
// > * gl.DEPTH_COMPONENT16: 16 depth bits.
// > * gl.STENCIL_INDEX8: 8 stencil bits.
// > * gl.DEPTH_STENCIL
stencilFormat = gl.STENCIL_INDEX8
} else {
// GL_STENCIL_INDEX8 might not be available with OpenGL 2.1.
// https://www.khronos.org/opengl/wiki/Image_Format
// > There are only 2 depth/stencil formats, each providing 8 stencil bits: GL_DEPTH24_STENCIL8 and GL_DEPTH32F_STENCIL8.
// > [...]
// > Stencil formats can only be used for Textures if OpenGL 4.4 or ARB_texture_stencil8 is available.
stencilFormat = gl.DEPTH24_STENCIL8
}
c.ctx.RenderbufferStorage(gl.RENDERBUFFER, stencilFormat, int32(width), int32(height))
return renderbuffer, nil
}
func (c *context) deleteRenderbuffer(r renderbufferNative) {
if !c.ctx.IsRenderbuffer(uint32(r)) {
return
}
if c.lastRenderbuffer == r {
c.lastRenderbuffer = 0
}
c.ctx.DeleteRenderbuffer(uint32(r))
}
func (c *context) newFramebuffer(texture textureNative, width, height int) (*framebuffer, error) {
f := c.ctx.CreateFramebuffer()
if f <= 0 {
return nil, fmt.Errorf("opengl: creating framebuffer failed: the returned value is not positive but %d", f)
}
c.bindFramebuffer(framebufferNative(f))
c.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
if s != 0 {
return nil, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
}
if e := c.ctx.GetError(); e != gl.NO_ERROR {
return nil, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
}
return nil, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
}
return &framebuffer{
native: framebufferNative(f),
width: width,
height: height,
}, nil
}
func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) error {
c.bindFramebuffer(f)
c.ctx.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, uint32(r))
if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
}
return nil
}
func (c *context) deleteFramebuffer(f framebufferNative) {
if f == c.screenFramebuffer {
return
}
if !c.ctx.IsFramebuffer(uint32(f)) {
return
}
// If a framebuffer to be deleted is bound, a newly bound framebuffer
// will be a default framebuffer.
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
if c.lastFramebuffer == f {
c.lastFramebuffer = invalidFramebuffer
c.lastViewportWidth = 0
c.lastViewportHeight = 0
}
c.ctx.DeleteFramebuffer(uint32(f))
}
func (c *context) newShader(shaderType uint32, source string) (shader, error) {
s := c.ctx.CreateShader(shaderType)
if s == 0 {
return 0, fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
}
c.ctx.ShaderSource(s, source)
c.ctx.CompileShader(s)
if c.ctx.GetShaderi(s, gl.COMPILE_STATUS) == gl.FALSE {
log := c.ctx.GetShaderInfoLog(s)
return 0, fmt.Errorf("opengl: shader compile failed: %s", log)
}
return shader(s), nil
}
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
p := c.ctx.CreateProgram()
if p == 0 {
return 0, errors.New("opengl: glCreateProgram failed")
}
for _, shader := range shaders {
c.ctx.AttachShader(p, uint32(shader))
}
for i, name := range attributes {
c.ctx.BindAttribLocation(p, uint32(i), name)
}
c.ctx.LinkProgram(p)
if c.ctx.GetProgrami(p, gl.LINK_STATUS) == gl.FALSE {
info := c.ctx.GetProgramInfoLog(p)
return 0, fmt.Errorf("opengl: program error: %s", info)
}
return program(p), nil
}
func (c *context) deleteProgram(p program) {
c.locationCache.deleteProgram(p)
if !c.ctx.IsProgram(uint32(p)) {
return
}
c.ctx.DeleteProgram(uint32(p))
}
func (c *context) uniformInt(p program, location string, v int) bool {
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
return false
}
c.ctx.Uniform1i(int32(l), int32(v))
return true
}
func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.Type) bool {
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
return false
}
base := typ.Main
if base == shaderir.Array {
base = typ.Sub[0].Main
}
switch base {
case shaderir.Float:
c.ctx.Uniform1fv(int32(l), uint32sToFloat32s(v))
case shaderir.Int:
c.ctx.Uniform1iv(int32(l), uint32sToInt32s(v))
case shaderir.Vec2:
c.ctx.Uniform2fv(int32(l), uint32sToFloat32s(v))
case shaderir.Vec3:
c.ctx.Uniform3fv(int32(l), uint32sToFloat32s(v))
case shaderir.Vec4:
c.ctx.Uniform4fv(int32(l), uint32sToFloat32s(v))
case shaderir.IVec2:
c.ctx.Uniform2iv(int32(l), uint32sToInt32s(v))
case shaderir.IVec3:
c.ctx.Uniform3iv(int32(l), uint32sToInt32s(v))
case shaderir.IVec4:
c.ctx.Uniform4iv(int32(l), uint32sToInt32s(v))
case shaderir.Mat2:
c.ctx.UniformMatrix2fv(int32(l), uint32sToFloat32s(v))
case shaderir.Mat3:
c.ctx.UniformMatrix3fv(int32(l), uint32sToFloat32s(v))
case shaderir.Mat4:
c.ctx.UniformMatrix4fv(int32(l), uint32sToFloat32s(v))
default:
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
}
return true
}
func (c *context) newArrayBuffer(size int) buffer {
b := c.ctx.CreateBuffer()
c.ctx.BindBuffer(gl.ARRAY_BUFFER, b)
c.ctx.BufferInit(gl.ARRAY_BUFFER, size, gl.DYNAMIC_DRAW)
return buffer(b)
}
func (c *context) newElementArrayBuffer(size int) buffer {
b := c.ctx.CreateBuffer()
c.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b)
c.ctx.BufferInit(gl.ELEMENT_ARRAY_BUFFER, size, gl.DYNAMIC_DRAW)
return buffer(b)
}
func (c *context) glslVersion() glsl.GLSLVersion {
if c.ctx.IsES() {
return glsl.GLSLVersionES300
}
return glsl.GLSLVersionDefault
}
@@ -0,0 +1,100 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build nintendosdk
package opengl
// #cgo !darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all
// #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup
//
// #include <EGL/egl.h>
// #include <EGL/eglext.h>
import "C"
import (
"fmt"
)
type egl struct {
display C.EGLDisplay
surface C.EGLSurface
context C.EGLContext
}
func newEGL(nativeWindowHandle uintptr) (*egl, error) {
e := &egl{}
e.display = C.eglGetDisplay(C.NativeDisplayType(C.EGL_DEFAULT_DISPLAY))
if e.display == 0 {
return nil, fmt.Errorf("opengl: eglGetDisplay failed")
}
if r := C.eglInitialize(e.display, nil, nil); r == 0 {
return nil, fmt.Errorf("opengl: eglInitialize failed")
}
configAttribs := []C.EGLint{
C.EGL_RENDERABLE_TYPE, C.EGL_OPENGL_BIT,
C.EGL_SURFACE_TYPE, C.EGL_WINDOW_BIT,
C.EGL_RED_SIZE, 8,
C.EGL_GREEN_SIZE, 8,
C.EGL_BLUE_SIZE, 8,
C.EGL_ALPHA_SIZE, 8,
C.EGL_NONE}
var numConfigs C.EGLint
var config C.EGLConfig
if r := C.eglChooseConfig(e.display, &configAttribs[0], &config, 1, &numConfigs); r == 0 {
return nil, fmt.Errorf("opengl: eglChooseConfig failed")
}
if numConfigs != 1 {
return nil, fmt.Errorf("opengl: eglChooseConfig failed: numConfigs must be 1 but %d", numConfigs)
}
e.surface = C.eglCreateWindowSurface(e.display, config, C.NativeWindowType(nativeWindowHandle), nil)
if e.surface == C.EGLSurface(C.EGL_NO_SURFACE) {
return nil, fmt.Errorf("opengl: eglCreateWindowSurface failed")
}
// Set the current rendering API.
if r := C.eglBindAPI(C.EGL_OPENGL_API); r == 0 {
return nil, fmt.Errorf("opengl: eglBindAPI failed")
}
// Create new context and set it as current.
contextAttribs := []C.EGLint{
// Set target graphics api version.
C.EGL_CONTEXT_MAJOR_VERSION, 3,
C.EGL_CONTEXT_MINOR_VERSION, 2,
// For debug callback
C.EGL_CONTEXT_FLAGS_KHR, C.EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
C.EGL_NONE}
e.context = C.eglCreateContext(e.display, config, C.EGLContext(C.EGL_NO_CONTEXT), &contextAttribs[0])
if e.context == C.EGLContext(C.EGL_NO_CONTEXT) {
return nil, fmt.Errorf("opengl: eglCreateContext failed: error: %d", C.eglGetError())
}
return e, nil
}
func (e *egl) makeContextCurrent() error {
if r := C.eglMakeCurrent(e.display, e.surface, e.surface, e.context); r == 0 {
return fmt.Errorf("opengl: eglMakeCurrent failed")
}
return nil
}
func (e *egl) swapBuffers() {
C.eglSwapBuffers(e.display, e.surface)
}
@@ -0,0 +1,5 @@
This is a fork of `github.com/go-gl/gl/v2.1/gl` with the below patch. This is now modified manually.
The original version is generated from `github.com/hajimehoshi/glow`'s `nocgo` branch. This enables to remove dependencies on Cgo on Windows.
Now we are working on committing this 'no-cgo' change to the official gl package. See https://github.com/go-gl/glow/pull/102.
@@ -0,0 +1,90 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package gl
const (
ALWAYS = 0x0207
ARRAY_BUFFER = 0x8892
BACK = 0x0405
BLEND = 0x0BE2
CLAMP_TO_EDGE = 0x812F
COLOR_ATTACHMENT0 = 0x8CE0
COMPILE_STATUS = 0x8B81
DECR_WRAP = 0x8508
DEPTH24_STENCIL8 = 0x88F0
DST_ALPHA = 0x0304
DST_COLOR = 0x0306
DYNAMIC_DRAW = 0x88E8
ELEMENT_ARRAY_BUFFER = 0x8893
FALSE = 0
FLOAT = 0x1406
FRAGMENT_SHADER = 0x8B30
FRAMEBUFFER = 0x8D40
FRAMEBUFFER_BINDING = 0x8CA6
FRAMEBUFFER_COMPLETE = 0x8CD5
FRONT = 0x0404
FRONT_AND_BACK = 0x0408
FUNC_ADD = 0x8006
FUNC_REVERSE_SUBTRACT = 0x800b
FUNC_SUBTRACT = 0x800a
HIGH_FLOAT = 0x8DF2
INCR_WRAP = 0x8507
INFO_LOG_LENGTH = 0x8B84
INVERT = 0x150A
KEEP = 0x1E00
LINK_STATUS = 0x8B82
MAX = 0x8008
MAX_TEXTURE_SIZE = 0x0D33
MIN = 0x8007
NEAREST = 0x2600
NO_ERROR = 0
NOTEQUAL = 0x0205
ONE = 1
ONE_MINUS_DST_ALPHA = 0x0305
ONE_MINUS_DST_COLOR = 0x0307
ONE_MINUS_SRC_ALPHA = 0x0303
ONE_MINUS_SRC_COLOR = 0x0301
PIXEL_PACK_BUFFER = 0x88EB
PIXEL_UNPACK_BUFFER = 0x88EC
READ_WRITE = 0x88BA
RENDERBUFFER = 0x8D41
RGBA = 0x1908
SCISSOR_TEST = 0x0C11
SHORT = 0x1402
SRC_ALPHA = 0x0302
SRC_ALPHA_SATURATE = 0x0308
SRC_COLOR = 0x0300
STENCIL_ATTACHMENT = 0x8D20
STENCIL_BUFFER_BIT = 0x0400
STENCIL_INDEX8 = 0x8D48
STENCIL_TEST = 0x0B90
STREAM_DRAW = 0x88E0
TEXTURE0 = 0x84C0
TEXTURE_2D = 0x0DE1
TEXTURE_MAG_FILTER = 0x2800
TEXTURE_MIN_FILTER = 0x2801
TEXTURE_WRAP_S = 0x2802
TEXTURE_WRAP_T = 0x2803
TRIANGLES = 0x0004
TRUE = 1
UNPACK_ALIGNMENT = 0x0CF5
UNSIGNED_BYTE = 0x1401
UNSIGNED_INT = 0x1405
VERTEX_SHADER = 0x8B31
WRITE_ONLY = 0x88B9
ZERO = 0
)
@@ -0,0 +1,647 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by genkeys.go using 'go generate'. DO NOT EDIT.
//go:build !playstation5
package gl
import (
"fmt"
"os"
)
type DebugContext struct {
Context Context
}
var _ Context = (*DebugContext)(nil)
func (d *DebugContext) ActiveTexture(arg0 uint32) {
d.Context.ActiveTexture(arg0)
fmt.Fprintln(os.Stderr, "ActiveTexture")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at ActiveTexture", e))
}
}
func (d *DebugContext) AttachShader(arg0 uint32, arg1 uint32) {
d.Context.AttachShader(arg0, arg1)
fmt.Fprintln(os.Stderr, "AttachShader")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at AttachShader", e))
}
}
func (d *DebugContext) BindAttribLocation(arg0 uint32, arg1 uint32, arg2 string) {
d.Context.BindAttribLocation(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "BindAttribLocation")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindAttribLocation", e))
}
}
func (d *DebugContext) BindBuffer(arg0 uint32, arg1 uint32) {
d.Context.BindBuffer(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindBuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindBuffer", e))
}
}
func (d *DebugContext) BindFramebuffer(arg0 uint32, arg1 uint32) {
d.Context.BindFramebuffer(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindFramebuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindFramebuffer", e))
}
}
func (d *DebugContext) BindRenderbuffer(arg0 uint32, arg1 uint32) {
d.Context.BindRenderbuffer(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindRenderbuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindRenderbuffer", e))
}
}
func (d *DebugContext) BindTexture(arg0 uint32, arg1 uint32) {
d.Context.BindTexture(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindTexture")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindTexture", e))
}
}
func (d *DebugContext) BindVertexArray(arg0 uint32) {
d.Context.BindVertexArray(arg0)
fmt.Fprintln(os.Stderr, "BindVertexArray")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindVertexArray", e))
}
}
func (d *DebugContext) BlendEquationSeparate(arg0 uint32, arg1 uint32) {
d.Context.BlendEquationSeparate(arg0, arg1)
fmt.Fprintln(os.Stderr, "BlendEquationSeparate")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BlendEquationSeparate", e))
}
}
func (d *DebugContext) BlendFuncSeparate(arg0 uint32, arg1 uint32, arg2 uint32, arg3 uint32) {
d.Context.BlendFuncSeparate(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "BlendFuncSeparate")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BlendFuncSeparate", e))
}
}
func (d *DebugContext) BufferInit(arg0 uint32, arg1 int, arg2 uint32) {
d.Context.BufferInit(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "BufferInit")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BufferInit", e))
}
}
func (d *DebugContext) BufferSubData(arg0 uint32, arg1 int, arg2 []uint8) {
d.Context.BufferSubData(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "BufferSubData")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BufferSubData", e))
}
}
func (d *DebugContext) CheckFramebufferStatus(arg0 uint32) uint32 {
out0 := d.Context.CheckFramebufferStatus(arg0)
fmt.Fprintln(os.Stderr, "CheckFramebufferStatus")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CheckFramebufferStatus", e))
}
return out0
}
func (d *DebugContext) Clear(arg0 uint32) {
d.Context.Clear(arg0)
fmt.Fprintln(os.Stderr, "Clear")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Clear", e))
}
}
func (d *DebugContext) ColorMask(arg0 bool, arg1 bool, arg2 bool, arg3 bool) {
d.Context.ColorMask(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "ColorMask")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at ColorMask", e))
}
}
func (d *DebugContext) CompileShader(arg0 uint32) {
d.Context.CompileShader(arg0)
fmt.Fprintln(os.Stderr, "CompileShader")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CompileShader", e))
}
}
func (d *DebugContext) CreateBuffer() uint32 {
out0 := d.Context.CreateBuffer()
fmt.Fprintln(os.Stderr, "CreateBuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateBuffer", e))
}
return out0
}
func (d *DebugContext) CreateFramebuffer() uint32 {
out0 := d.Context.CreateFramebuffer()
fmt.Fprintln(os.Stderr, "CreateFramebuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateFramebuffer", e))
}
return out0
}
func (d *DebugContext) CreateProgram() uint32 {
out0 := d.Context.CreateProgram()
fmt.Fprintln(os.Stderr, "CreateProgram")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateProgram", e))
}
return out0
}
func (d *DebugContext) CreateRenderbuffer() uint32 {
out0 := d.Context.CreateRenderbuffer()
fmt.Fprintln(os.Stderr, "CreateRenderbuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateRenderbuffer", e))
}
return out0
}
func (d *DebugContext) CreateShader(arg0 uint32) uint32 {
out0 := d.Context.CreateShader(arg0)
fmt.Fprintln(os.Stderr, "CreateShader")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateShader", e))
}
return out0
}
func (d *DebugContext) CreateTexture() uint32 {
out0 := d.Context.CreateTexture()
fmt.Fprintln(os.Stderr, "CreateTexture")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateTexture", e))
}
return out0
}
func (d *DebugContext) CreateVertexArray() uint32 {
out0 := d.Context.CreateVertexArray()
fmt.Fprintln(os.Stderr, "CreateVertexArray")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at CreateVertexArray", e))
}
return out0
}
func (d *DebugContext) DeleteBuffer(arg0 uint32) {
d.Context.DeleteBuffer(arg0)
fmt.Fprintln(os.Stderr, "DeleteBuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteBuffer", e))
}
}
func (d *DebugContext) DeleteFramebuffer(arg0 uint32) {
d.Context.DeleteFramebuffer(arg0)
fmt.Fprintln(os.Stderr, "DeleteFramebuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteFramebuffer", e))
}
}
func (d *DebugContext) DeleteProgram(arg0 uint32) {
d.Context.DeleteProgram(arg0)
fmt.Fprintln(os.Stderr, "DeleteProgram")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteProgram", e))
}
}
func (d *DebugContext) DeleteRenderbuffer(arg0 uint32) {
d.Context.DeleteRenderbuffer(arg0)
fmt.Fprintln(os.Stderr, "DeleteRenderbuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteRenderbuffer", e))
}
}
func (d *DebugContext) DeleteShader(arg0 uint32) {
d.Context.DeleteShader(arg0)
fmt.Fprintln(os.Stderr, "DeleteShader")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteShader", e))
}
}
func (d *DebugContext) DeleteTexture(arg0 uint32) {
d.Context.DeleteTexture(arg0)
fmt.Fprintln(os.Stderr, "DeleteTexture")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteTexture", e))
}
}
func (d *DebugContext) DeleteVertexArray(arg0 uint32) {
d.Context.DeleteVertexArray(arg0)
fmt.Fprintln(os.Stderr, "DeleteVertexArray")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DeleteVertexArray", e))
}
}
func (d *DebugContext) Disable(arg0 uint32) {
d.Context.Disable(arg0)
fmt.Fprintln(os.Stderr, "Disable")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Disable", e))
}
}
func (d *DebugContext) DisableVertexAttribArray(arg0 uint32) {
d.Context.DisableVertexAttribArray(arg0)
fmt.Fprintln(os.Stderr, "DisableVertexAttribArray")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DisableVertexAttribArray", e))
}
}
func (d *DebugContext) DrawElements(arg0 uint32, arg1 int32, arg2 uint32, arg3 int) {
d.Context.DrawElements(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "DrawElements")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at DrawElements", e))
}
}
func (d *DebugContext) Enable(arg0 uint32) {
d.Context.Enable(arg0)
fmt.Fprintln(os.Stderr, "Enable")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Enable", e))
}
}
func (d *DebugContext) EnableVertexAttribArray(arg0 uint32) {
d.Context.EnableVertexAttribArray(arg0)
fmt.Fprintln(os.Stderr, "EnableVertexAttribArray")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at EnableVertexAttribArray", e))
}
}
func (d *DebugContext) Flush() {
d.Context.Flush()
fmt.Fprintln(os.Stderr, "Flush")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Flush", e))
}
}
func (d *DebugContext) FramebufferRenderbuffer(arg0 uint32, arg1 uint32, arg2 uint32, arg3 uint32) {
d.Context.FramebufferRenderbuffer(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "FramebufferRenderbuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at FramebufferRenderbuffer", e))
}
}
func (d *DebugContext) FramebufferTexture2D(arg0 uint32, arg1 uint32, arg2 uint32, arg3 uint32, arg4 int32) {
d.Context.FramebufferTexture2D(arg0, arg1, arg2, arg3, arg4)
fmt.Fprintln(os.Stderr, "FramebufferTexture2D")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at FramebufferTexture2D", e))
}
}
func (d *DebugContext) GetError() uint32 {
out0 := d.Context.GetError()
fmt.Fprintln(os.Stderr, "GetError")
return out0
}
func (d *DebugContext) GetInteger(arg0 uint32) int {
out0 := d.Context.GetInteger(arg0)
fmt.Fprintln(os.Stderr, "GetInteger")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetInteger", e))
}
return out0
}
func (d *DebugContext) GetProgramInfoLog(arg0 uint32) string {
out0 := d.Context.GetProgramInfoLog(arg0)
fmt.Fprintln(os.Stderr, "GetProgramInfoLog")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetProgramInfoLog", e))
}
return out0
}
func (d *DebugContext) GetProgrami(arg0 uint32, arg1 uint32) int {
out0 := d.Context.GetProgrami(arg0, arg1)
fmt.Fprintln(os.Stderr, "GetProgrami")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetProgrami", e))
}
return out0
}
func (d *DebugContext) GetShaderInfoLog(arg0 uint32) string {
out0 := d.Context.GetShaderInfoLog(arg0)
fmt.Fprintln(os.Stderr, "GetShaderInfoLog")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetShaderInfoLog", e))
}
return out0
}
func (d *DebugContext) GetShaderi(arg0 uint32, arg1 uint32) int {
out0 := d.Context.GetShaderi(arg0, arg1)
fmt.Fprintln(os.Stderr, "GetShaderi")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetShaderi", e))
}
return out0
}
func (d *DebugContext) GetUniformLocation(arg0 uint32, arg1 string) int32 {
out0 := d.Context.GetUniformLocation(arg0, arg1)
fmt.Fprintln(os.Stderr, "GetUniformLocation")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at GetUniformLocation", e))
}
return out0
}
func (d *DebugContext) IsES() bool {
out0 := d.Context.IsES()
return out0
}
func (d *DebugContext) IsFramebuffer(arg0 uint32) bool {
out0 := d.Context.IsFramebuffer(arg0)
fmt.Fprintln(os.Stderr, "IsFramebuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at IsFramebuffer", e))
}
return out0
}
func (d *DebugContext) IsProgram(arg0 uint32) bool {
out0 := d.Context.IsProgram(arg0)
fmt.Fprintln(os.Stderr, "IsProgram")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at IsProgram", e))
}
return out0
}
func (d *DebugContext) IsRenderbuffer(arg0 uint32) bool {
out0 := d.Context.IsRenderbuffer(arg0)
fmt.Fprintln(os.Stderr, "IsRenderbuffer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at IsRenderbuffer", e))
}
return out0
}
func (d *DebugContext) LinkProgram(arg0 uint32) {
d.Context.LinkProgram(arg0)
fmt.Fprintln(os.Stderr, "LinkProgram")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at LinkProgram", e))
}
}
func (d *DebugContext) LoadFunctions() error {
out0 := d.Context.LoadFunctions()
return out0
}
func (d *DebugContext) PixelStorei(arg0 uint32, arg1 int32) {
d.Context.PixelStorei(arg0, arg1)
fmt.Fprintln(os.Stderr, "PixelStorei")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at PixelStorei", e))
}
}
func (d *DebugContext) ReadPixels(arg0 []uint8, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 uint32, arg6 uint32) {
d.Context.ReadPixels(arg0, arg1, arg2, arg3, arg4, arg5, arg6)
fmt.Fprintln(os.Stderr, "ReadPixels")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at ReadPixels", e))
}
}
func (d *DebugContext) RenderbufferStorage(arg0 uint32, arg1 uint32, arg2 int32, arg3 int32) {
d.Context.RenderbufferStorage(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "RenderbufferStorage")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at RenderbufferStorage", e))
}
}
func (d *DebugContext) Scissor(arg0 int32, arg1 int32, arg2 int32, arg3 int32) {
d.Context.Scissor(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "Scissor")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Scissor", e))
}
}
func (d *DebugContext) ShaderSource(arg0 uint32, arg1 string) {
d.Context.ShaderSource(arg0, arg1)
fmt.Fprintln(os.Stderr, "ShaderSource")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at ShaderSource", e))
}
}
func (d *DebugContext) StencilFunc(arg0 uint32, arg1 int32, arg2 uint32) {
d.Context.StencilFunc(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "StencilFunc")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at StencilFunc", e))
}
}
func (d *DebugContext) StencilOpSeparate(arg0 uint32, arg1 uint32, arg2 uint32, arg3 uint32) {
d.Context.StencilOpSeparate(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "StencilOpSeparate")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at StencilOpSeparate", e))
}
}
func (d *DebugContext) TexImage2D(arg0 uint32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 uint32, arg6 uint32, arg7 []uint8) {
d.Context.TexImage2D(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
fmt.Fprintln(os.Stderr, "TexImage2D")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at TexImage2D", e))
}
}
func (d *DebugContext) TexParameteri(arg0 uint32, arg1 uint32, arg2 int32) {
d.Context.TexParameteri(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "TexParameteri")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at TexParameteri", e))
}
}
func (d *DebugContext) TexSubImage2D(arg0 uint32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 int32, arg6 uint32, arg7 uint32, arg8 []uint8) {
d.Context.TexSubImage2D(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
fmt.Fprintln(os.Stderr, "TexSubImage2D")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at TexSubImage2D", e))
}
}
func (d *DebugContext) Uniform1fv(arg0 int32, arg1 []float32) {
d.Context.Uniform1fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform1fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform1fv", e))
}
}
func (d *DebugContext) Uniform1i(arg0 int32, arg1 int32) {
d.Context.Uniform1i(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform1i")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform1i", e))
}
}
func (d *DebugContext) Uniform1iv(arg0 int32, arg1 []int32) {
d.Context.Uniform1iv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform1iv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform1iv", e))
}
}
func (d *DebugContext) Uniform2fv(arg0 int32, arg1 []float32) {
d.Context.Uniform2fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform2fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform2fv", e))
}
}
func (d *DebugContext) Uniform2iv(arg0 int32, arg1 []int32) {
d.Context.Uniform2iv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform2iv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform2iv", e))
}
}
func (d *DebugContext) Uniform3fv(arg0 int32, arg1 []float32) {
d.Context.Uniform3fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform3fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform3fv", e))
}
}
func (d *DebugContext) Uniform3iv(arg0 int32, arg1 []int32) {
d.Context.Uniform3iv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform3iv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform3iv", e))
}
}
func (d *DebugContext) Uniform4fv(arg0 int32, arg1 []float32) {
d.Context.Uniform4fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform4fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform4fv", e))
}
}
func (d *DebugContext) Uniform4iv(arg0 int32, arg1 []int32) {
d.Context.Uniform4iv(arg0, arg1)
fmt.Fprintln(os.Stderr, "Uniform4iv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Uniform4iv", e))
}
}
func (d *DebugContext) UniformMatrix2fv(arg0 int32, arg1 []float32) {
d.Context.UniformMatrix2fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "UniformMatrix2fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at UniformMatrix2fv", e))
}
}
func (d *DebugContext) UniformMatrix3fv(arg0 int32, arg1 []float32) {
d.Context.UniformMatrix3fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "UniformMatrix3fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at UniformMatrix3fv", e))
}
}
func (d *DebugContext) UniformMatrix4fv(arg0 int32, arg1 []float32) {
d.Context.UniformMatrix4fv(arg0, arg1)
fmt.Fprintln(os.Stderr, "UniformMatrix4fv")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at UniformMatrix4fv", e))
}
}
func (d *DebugContext) UseProgram(arg0 uint32) {
d.Context.UseProgram(arg0)
fmt.Fprintln(os.Stderr, "UseProgram")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at UseProgram", e))
}
}
func (d *DebugContext) VertexAttribPointer(arg0 uint32, arg1 int32, arg2 uint32, arg3 bool, arg4 int32, arg5 int) {
d.Context.VertexAttribPointer(arg0, arg1, arg2, arg3, arg4, arg5)
fmt.Fprintln(os.Stderr, "VertexAttribPointer")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at VertexAttribPointer", e))
}
}
func (d *DebugContext) Viewport(arg0 int32, arg1 int32, arg2 int32, arg3 int32) {
d.Context.Viewport(arg0, arg1, arg2, arg3)
fmt.Fprintln(os.Stderr, "Viewport")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at Viewport", e))
}
}
@@ -0,0 +1,853 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2014 Eric Woroshow
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
//go:build !darwin && !js && !windows && !playstation5
package gl
// #include <stdint.h>
// #include <stdlib.h>
//
// typedef unsigned int GLenum;
// typedef unsigned char GLboolean;
// typedef unsigned int GLbitfield;
// typedef int GLint;
// typedef unsigned int GLuint;
// typedef int GLsizei;
// typedef float GLfloat;
// typedef char GLchar;
// typedef ptrdiff_t GLintptr;
// typedef ptrdiff_t GLsizeiptr;
//
// static void glowActiveTexture(uintptr_t fnptr, GLenum texture) {
// typedef void (*fn)(GLenum texture);
// ((fn)(fnptr))(texture);
// }
// static void glowAttachShader(uintptr_t fnptr, GLuint program, GLuint shader) {
// typedef void (*fn)(GLuint program, GLuint shader);
// ((fn)(fnptr))(program, shader);
// }
// static void glowBindAttribLocation(uintptr_t fnptr, GLuint program, GLuint index, const GLchar* name) {
// typedef void (*fn)(GLuint program, GLuint index, const GLchar* name);
// ((fn)(fnptr))(program, index, name);
// }
// static void glowBindBuffer(uintptr_t fnptr, GLenum target, GLuint buffer) {
// typedef void (*fn)(GLenum target, GLuint buffer);
// ((fn)(fnptr))(target, buffer);
// }
// static void glowBindFramebuffer(uintptr_t fnptr, GLenum target, GLuint framebuffer) {
// typedef void (*fn)(GLenum target, GLuint framebuffer);
// ((fn)(fnptr))(target, framebuffer);
// }
// static void glowBindRenderbuffer(uintptr_t fnptr, GLenum target, GLuint renderbuffer) {
// typedef void (*fn)(GLenum target, GLuint renderbuffer);
// ((fn)(fnptr))(target, renderbuffer);
// }
// static void glowBindTexture(uintptr_t fnptr, GLenum target, GLuint texture) {
// typedef void (*fn)(GLenum target, GLuint texture);
// ((fn)(fnptr))(target, texture);
// }
// static void glowBindVertexArray(uintptr_t fnptr, GLuint array) {
// typedef void (*fn)(GLuint array);
// ((fn)(fnptr))(array);
// }
// static void glowBlendEquationSeparate(uintptr_t fnptr, GLenum modeRGB, GLenum modeAlpha) {
// typedef void (*fn)(GLenum modeRGB, GLenum modeAlpha);
// ((fn)(fnptr))(modeRGB, modeAlpha);
// }
// static void glowBlendFuncSeparate(uintptr_t fnptr, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
// typedef void (*fn)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
// ((fn)(fnptr))(srcRGB, dstRGB, srcAlpha, dstAlpha);
// }
// static void glowBufferData(uintptr_t fnptr, GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
// typedef void (*fn)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
// ((fn)(fnptr))(target, size, data, usage);
// }
// static void glowBufferSubData(uintptr_t fnptr, GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
// typedef void (*fn)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
// ((fn)(fnptr))(target, offset, size, data);
// }
// static GLenum glowCheckFramebufferStatus(uintptr_t fnptr, GLenum target) {
// typedef GLenum (*fn)(GLenum target);
// return ((fn)(fnptr))(target);
// }
// static void glowClear(uintptr_t fnptr, GLbitfield mask) {
// typedef void (*fn)(GLbitfield mask);
// ((fn)(fnptr))(mask);
// }
// static void glowColorMask(uintptr_t fnptr, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
// typedef void (*fn)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
// ((fn)(fnptr))(red, green, blue, alpha);
// }
// static void glowCompileShader(uintptr_t fnptr, GLuint shader) {
// typedef void (*fn)(GLuint shader);
// ((fn)(fnptr))(shader);
// }
// static GLuint glowCreateProgram(uintptr_t fnptr) {
// typedef GLuint (*fn)();
// return ((fn)(fnptr))();
// }
// static GLuint glowCreateShader(uintptr_t fnptr, GLenum type) {
// typedef GLuint (*fn)(GLenum type);
// return ((fn)(fnptr))(type);
// }
// static void glowDeleteBuffers(uintptr_t fnptr, GLsizei n, const GLuint* buffers) {
// typedef void (*fn)(GLsizei n, const GLuint* buffers);
// ((fn)(fnptr))(n, buffers);
// }
// static void glowDeleteFramebuffers(uintptr_t fnptr, GLsizei n, const GLuint* framebuffers) {
// typedef void (*fn)(GLsizei n, const GLuint* framebuffers);
// ((fn)(fnptr))(n, framebuffers);
// }
// static void glowDeleteProgram(uintptr_t fnptr, GLuint program) {
// typedef void (*fn)(GLuint program);
// ((fn)(fnptr))(program);
// }
// static void glowDeleteRenderbuffers(uintptr_t fnptr, GLsizei n, const GLuint* renderbuffers) {
// typedef void (*fn)(GLsizei n, const GLuint* renderbuffers);
// ((fn)(fnptr))(n, renderbuffers);
// }
// static void glowDeleteShader(uintptr_t fnptr, GLuint shader) {
// typedef void (*fn)(GLuint shader);
// ((fn)(fnptr))(shader);
// }
// static void glowDeleteTextures(uintptr_t fnptr, GLsizei n, const GLuint* textures) {
// typedef void (*fn)(GLsizei n, const GLuint* textures);
// ((fn)(fnptr))(n, textures);
// }
// static void glowDeleteVertexArrays(uintptr_t fnptr, GLsizei n, const GLuint* arrays) {
// typedef void (*fn)(GLsizei n, const GLuint* arrays);
// ((fn)(fnptr))(n, arrays);
// }
// static void glowDisable(uintptr_t fnptr, GLenum cap) {
// typedef void (*fn)(GLenum cap);
// ((fn)(fnptr))(cap);
// }
// static void glowDisableVertexAttribArray(uintptr_t fnptr, GLuint index) {
// typedef void (*fn)(GLuint index);
// ((fn)(fnptr))(index);
// }
// static void glowDrawElements(uintptr_t fnptr, GLenum mode, GLsizei count, GLenum type, const uintptr_t indices) {
// typedef void (*fn)(GLenum mode, GLsizei count, GLenum type, const uintptr_t indices);
// ((fn)(fnptr))(mode, count, type, indices);
// }
// static void glowEnable(uintptr_t fnptr, GLenum cap) {
// typedef void (*fn)(GLenum cap);
// ((fn)(fnptr))(cap);
// }
// static void glowEnableVertexAttribArray(uintptr_t fnptr, GLuint index) {
// typedef void (*fn)(GLuint index);
// ((fn)(fnptr))(index);
// }
// static void glowFlush(uintptr_t fnptr) {
// typedef void (*fn)();
// ((fn)(fnptr))();
// }
// static void glowFramebufferRenderbuffer(uintptr_t fnptr, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
// typedef void (*fn)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
// ((fn)(fnptr))(target, attachment, renderbuffertarget, renderbuffer);
// }
// static void glowFramebufferTexture2D(uintptr_t fnptr, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
// typedef void (*fn)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
// ((fn)(fnptr))(target, attachment, textarget, texture, level);
// }
// static void glowGenBuffers(uintptr_t fnptr, GLsizei n, GLuint* buffers) {
// typedef void (*fn)(GLsizei n, GLuint* buffers);
// ((fn)(fnptr))(n, buffers);
// }
// static void glowGenFramebuffers(uintptr_t fnptr, GLsizei n, GLuint* framebuffers) {
// typedef void (*fn)(GLsizei n, GLuint* framebuffers);
// ((fn)(fnptr))(n, framebuffers);
// }
// static void glowGenRenderbuffers(uintptr_t fnptr, GLsizei n, GLuint* renderbuffers) {
// typedef void (*fn)(GLsizei n, GLuint* renderbuffers);
// ((fn)(fnptr))(n, renderbuffers);
// }
// static void glowGenTextures(uintptr_t fnptr, GLsizei n, GLuint* textures) {
// typedef void (*fn)(GLsizei n, GLuint* textures);
// ((fn)(fnptr))(n, textures);
// }
// static void glowGenVertexArrays(uintptr_t fnptr, GLsizei n, GLuint* arrays) {
// typedef void (*fn)(GLsizei n, GLuint* arrays);
// ((fn)(fnptr))(n, arrays);
// }
// static GLenum glowGetError(uintptr_t fnptr) {
// typedef GLenum (*fn)();
// return ((fn)(fnptr))();
// }
// static void glowGetIntegerv(uintptr_t fnptr, GLenum pname, GLint* data) {
// typedef void (*fn)(GLenum pname, GLint* data);
// ((fn)(fnptr))(pname, data);
// }
// static void glowGetProgramInfoLog(uintptr_t fnptr, GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
// typedef void (*fn)(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
// ((fn)(fnptr))(program, bufSize, length, infoLog);
// }
// static void glowGetProgramiv(uintptr_t fnptr, GLuint program, GLenum pname, GLint* params) {
// typedef void (*fn)(GLuint program, GLenum pname, GLint* params);
// ((fn)(fnptr))(program, pname, params);
// }
// static void glowGetShaderInfoLog(uintptr_t fnptr, GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
// typedef void (*fn)(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
// ((fn)(fnptr))(shader, bufSize, length, infoLog);
// }
// static void glowGetShaderiv(uintptr_t fnptr, GLuint shader, GLenum pname, GLint* params) {
// typedef void (*fn)(GLuint shader, GLenum pname, GLint* params);
// ((fn)(fnptr))(shader, pname, params);
// }
// static GLint glowGetUniformLocation(uintptr_t fnptr, GLuint program, const GLchar* name) {
// typedef GLint (*fn)(GLuint program, const GLchar* name);
// return ((fn)(fnptr))(program, name);
// }
// static GLboolean glowIsFramebuffer(uintptr_t fnptr, GLuint framebuffer) {
// typedef GLboolean (*fn)(GLuint framebuffer);
// return ((fn)(fnptr))(framebuffer);
// }
// static GLboolean glowIsProgram(uintptr_t fnptr, GLuint program) {
// typedef GLboolean (*fn)(GLuint program);
// return ((fn)(fnptr))(program);
// }
// static GLboolean glowIsRenderbuffer(uintptr_t fnptr, GLuint renderbuffer) {
// typedef GLboolean (*fn)(GLuint renderbuffer);
// return ((fn)(fnptr))(renderbuffer);
// }
// static void glowLinkProgram(uintptr_t fnptr, GLuint program) {
// typedef void (*fn)(GLuint program);
// ((fn)(fnptr))(program);
// }
// static void glowPixelStorei(uintptr_t fnptr, GLenum pname, GLint param) {
// typedef void (*fn)(GLenum pname, GLint param);
// ((fn)(fnptr))(pname, param);
// }
// static void glowReadPixels(uintptr_t fnptr, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
// typedef void (*fn)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
// ((fn)(fnptr))(x, y, width, height, format, type, pixels);
// }
// static void glowRenderbufferStorage(uintptr_t fnptr, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
// typedef void (*fn)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
// ((fn)(fnptr))(target, internalformat, width, height);
// }
// static void glowScissor(uintptr_t fnptr, GLint x, GLint y, GLsizei width, GLsizei height) {
// typedef void (*fn)(GLint x, GLint y, GLsizei width, GLsizei height);
// ((fn)(fnptr))(x, y, width, height);
// }
// static void glowShaderSource(uintptr_t fnptr, GLuint shader, GLsizei count, const GLchar*const* string, const GLint* length) {
// typedef void (*fn)(GLuint shader, GLsizei count, const GLchar*const* string, const GLint* length);
// ((fn)(fnptr))(shader, count, string, length);
// }
// static void glowStencilFunc(uintptr_t fnptr, GLenum func, GLint ref, GLuint mask) {
// typedef void (*fn)(GLenum func, GLint ref, GLuint mask);
// ((fn)(fnptr))(func, ref, mask);
// }
// static void glowStencilOpSeparate(uintptr_t fnptr, GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
// typedef void (*fn)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
// ((fn)(fnptr))(face, fail, zfail, zpass);
// }
// static void glowTexImage2D(uintptr_t fnptr, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) {
// typedef void (*fn)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
// ((fn)(fnptr))(target, level, internalformat, width, height, border, format, type, pixels);
// }
// static void glowTexParameteri(uintptr_t fnptr, GLenum target, GLenum pname, GLint param) {
// typedef void (*fn)(GLenum target, GLenum pname, GLint param);
// ((fn)(fnptr))(target, pname, param);
// }
// static void glowTexSubImage2D(uintptr_t fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) {
// typedef void (*fn)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
// ((fn)(fnptr))(target, level, xoffset, yoffset, width, height, format, type, pixels);
// }
// static void glowUniform1fv(uintptr_t fnptr, GLint location, GLsizei count, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLfloat* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform1i(uintptr_t fnptr, GLint location, GLint v0) {
// typedef void (*fn)(GLint location, GLint v0);
// ((fn)(fnptr))(location, v0);
// }
// static void glowUniform1iv(uintptr_t fnptr, GLint location, GLsizei count, const GLint* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLint* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform2fv(uintptr_t fnptr, GLint location, GLsizei count, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLfloat* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform2iv(uintptr_t fnptr, GLint location, GLsizei count, const GLint* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLint* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform3fv(uintptr_t fnptr, GLint location, GLsizei count, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLfloat* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform3iv(uintptr_t fnptr, GLint location, GLsizei count, const GLint* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLint* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform4fv(uintptr_t fnptr, GLint location, GLsizei count, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLfloat* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniform4iv(uintptr_t fnptr, GLint location, GLsizei count, const GLint* value) {
// typedef void (*fn)(GLint location, GLsizei count, const GLint* value);
// ((fn)(fnptr))(location, count, value);
// }
// static void glowUniformMatrix2fv(uintptr_t fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
// ((fn)(fnptr))(location, count, transpose, value);
// }
// static void glowUniformMatrix3fv(uintptr_t fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
// ((fn)(fnptr))(location, count, transpose, value);
// }
// static void glowUniformMatrix4fv(uintptr_t fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
// typedef void (*fn)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
// ((fn)(fnptr))(location, count, transpose, value);
// }
// static void glowUseProgram(uintptr_t fnptr, GLuint program) {
// typedef void (*fn)(GLuint program);
// ((fn)(fnptr))(program);
// }
// static void glowVertexAttribPointer(uintptr_t fnptr, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const uintptr_t pointer) {
// typedef void (*fn)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const uintptr_t pointer);
// ((fn)(fnptr))(index, size, type, normalized, stride, pointer);
// }
// static void glowViewport(uintptr_t fnptr, GLint x, GLint y, GLsizei width, GLsizei height) {
// typedef void (*fn)(GLint x, GLint y, GLsizei width, GLsizei height);
// ((fn)(fnptr))(x, y, width, height);
// }
import "C"
import (
"runtime"
"unsafe"
)
type defaultContext struct {
gpActiveTexture C.uintptr_t
gpAttachShader C.uintptr_t
gpBindAttribLocation C.uintptr_t
gpBindBuffer C.uintptr_t
gpBindFramebuffer C.uintptr_t
gpBindRenderbuffer C.uintptr_t
gpBindTexture C.uintptr_t
gpBindVertexArray C.uintptr_t
gpBlendEquationSeparate C.uintptr_t
gpBlendFuncSeparate C.uintptr_t
gpBufferData C.uintptr_t
gpBufferSubData C.uintptr_t
gpCheckFramebufferStatus C.uintptr_t
gpClear C.uintptr_t
gpColorMask C.uintptr_t
gpCompileShader C.uintptr_t
gpCreateProgram C.uintptr_t
gpCreateShader C.uintptr_t
gpDeleteBuffers C.uintptr_t
gpDeleteFramebuffers C.uintptr_t
gpDeleteProgram C.uintptr_t
gpDeleteRenderbuffers C.uintptr_t
gpDeleteShader C.uintptr_t
gpDeleteTextures C.uintptr_t
gpDeleteVertexArrays C.uintptr_t
gpDisable C.uintptr_t
gpDisableVertexAttribArray C.uintptr_t
gpDrawElements C.uintptr_t
gpEnable C.uintptr_t
gpEnableVertexAttribArray C.uintptr_t
gpFlush C.uintptr_t
gpFramebufferRenderbuffer C.uintptr_t
gpFramebufferTexture2D C.uintptr_t
gpGenBuffers C.uintptr_t
gpGenFramebuffers C.uintptr_t
gpGenRenderbuffers C.uintptr_t
gpGenTextures C.uintptr_t
gpGenVertexArrays C.uintptr_t
gpGetError C.uintptr_t
gpGetIntegerv C.uintptr_t
gpGetProgramInfoLog C.uintptr_t
gpGetProgramiv C.uintptr_t
gpGetShaderInfoLog C.uintptr_t
gpGetShaderiv C.uintptr_t
gpGetUniformLocation C.uintptr_t
gpIsFramebuffer C.uintptr_t
gpIsProgram C.uintptr_t
gpIsRenderbuffer C.uintptr_t
gpLinkProgram C.uintptr_t
gpPixelStorei C.uintptr_t
gpReadPixels C.uintptr_t
gpRenderbufferStorage C.uintptr_t
gpScissor C.uintptr_t
gpShaderSource C.uintptr_t
gpStencilFunc C.uintptr_t
gpStencilOpSeparate C.uintptr_t
gpTexImage2D C.uintptr_t
gpTexParameteri C.uintptr_t
gpTexSubImage2D C.uintptr_t
gpUniform1fv C.uintptr_t
gpUniform1i C.uintptr_t
gpUniform1iv C.uintptr_t
gpUniform2fv C.uintptr_t
gpUniform2iv C.uintptr_t
gpUniform3fv C.uintptr_t
gpUniform3iv C.uintptr_t
gpUniform4fv C.uintptr_t
gpUniform4iv C.uintptr_t
gpUniformMatrix2fv C.uintptr_t
gpUniformMatrix3fv C.uintptr_t
gpUniformMatrix4fv C.uintptr_t
gpUseProgram C.uintptr_t
gpVertexAttribPointer C.uintptr_t
gpViewport C.uintptr_t
isES bool
}
func NewDefaultContext() (Context, error) {
ctx := &defaultContext{}
if err := ctx.init(); err != nil {
return nil, err
}
return ctx, nil
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}
func (c *defaultContext) IsES() bool {
return c.isES
}
func (c *defaultContext) ActiveTexture(texture uint32) {
C.glowActiveTexture(c.gpActiveTexture, C.GLenum(texture))
}
func (c *defaultContext) AttachShader(program uint32, shader uint32) {
C.glowAttachShader(c.gpAttachShader, C.GLuint(program), C.GLuint(shader))
}
func (c *defaultContext) BindAttribLocation(program uint32, index uint32, name string) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
C.glowBindAttribLocation(c.gpBindAttribLocation, C.GLuint(program), C.GLuint(index), (*C.GLchar)(unsafe.Pointer(cname)))
}
func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
C.glowBindBuffer(c.gpBindBuffer, C.GLenum(target), C.GLuint(buffer))
}
func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) {
C.glowBindFramebuffer(c.gpBindFramebuffer, C.GLenum(target), C.GLuint(framebuffer))
}
func (c *defaultContext) BindRenderbuffer(target uint32, renderbuffer uint32) {
C.glowBindRenderbuffer(c.gpBindRenderbuffer, C.GLenum(target), C.GLuint(renderbuffer))
}
func (c *defaultContext) BindTexture(target uint32, texture uint32) {
C.glowBindTexture(c.gpBindTexture, C.GLenum(target), C.GLuint(texture))
}
func (c *defaultContext) BindVertexArray(array uint32) {
C.glowBindVertexArray(c.gpBindVertexArray, C.GLuint(array))
}
func (c *defaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
C.glowBlendEquationSeparate(c.gpBlendEquationSeparate, C.GLenum(modeRGB), C.GLenum(modeAlpha))
}
func (c *defaultContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
C.glowBlendFuncSeparate(c.gpBlendFuncSeparate, C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
}
func (c *defaultContext) BufferInit(target uint32, size int, usage uint32) {
C.glowBufferData(c.gpBufferData, C.GLenum(target), C.GLsizeiptr(size), nil, C.GLenum(usage))
}
func (c *defaultContext) BufferSubData(target uint32, offset int, data []byte) {
C.glowBufferSubData(c.gpBufferSubData, C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(len(data)), unsafe.Pointer(&data[0]))
runtime.KeepAlive(data)
}
func (c *defaultContext) CheckFramebufferStatus(target uint32) uint32 {
ret := C.glowCheckFramebufferStatus(c.gpCheckFramebufferStatus, C.GLenum(target))
return uint32(ret)
}
func (c *defaultContext) Clear(mask uint32) {
C.glowClear(c.gpClear, C.GLbitfield(mask))
}
func (c *defaultContext) ColorMask(red bool, green bool, blue bool, alpha bool) {
C.glowColorMask(c.gpColorMask, C.GLboolean(boolToInt(red)), C.GLboolean(boolToInt(green)), C.GLboolean(boolToInt(blue)), C.GLboolean(boolToInt(alpha)))
}
func (c *defaultContext) CompileShader(shader uint32) {
C.glowCompileShader(c.gpCompileShader, C.GLuint(shader))
}
func (c *defaultContext) CreateBuffer() uint32 {
var buffer uint32
C.glowGenBuffers(c.gpGenBuffers, 1, (*C.GLuint)(unsafe.Pointer(&buffer)))
return buffer
}
func (c *defaultContext) CreateFramebuffer() uint32 {
var framebuffer uint32
C.glowGenFramebuffers(c.gpGenFramebuffers, 1, (*C.GLuint)(unsafe.Pointer(&framebuffer)))
return framebuffer
}
func (c *defaultContext) CreateProgram() uint32 {
ret := C.glowCreateProgram(c.gpCreateProgram)
return uint32(ret)
}
func (c *defaultContext) CreateRenderbuffer() uint32 {
var renderbuffer uint32
C.glowGenRenderbuffers(c.gpGenRenderbuffers, 1, (*C.GLuint)(unsafe.Pointer(&renderbuffer)))
return renderbuffer
}
func (c *defaultContext) CreateShader(xtype uint32) uint32 {
ret := C.glowCreateShader(c.gpCreateShader, C.GLenum(xtype))
return uint32(ret)
}
func (c *defaultContext) CreateTexture() uint32 {
var texture uint32
C.glowGenTextures(c.gpGenTextures, 1, (*C.GLuint)(unsafe.Pointer(&texture)))
return texture
}
func (c *defaultContext) CreateVertexArray() uint32 {
var array uint32
C.glowGenVertexArrays(c.gpGenVertexArrays, 1, (*C.GLuint)(unsafe.Pointer(&array)))
return array
}
func (c *defaultContext) DeleteBuffer(buffer uint32) {
C.glowDeleteBuffers(c.gpDeleteBuffers, 1, (*C.GLuint)(unsafe.Pointer(&buffer)))
}
func (c *defaultContext) DeleteFramebuffer(framebuffer uint32) {
C.glowDeleteFramebuffers(c.gpDeleteFramebuffers, 1, (*C.GLuint)(unsafe.Pointer(&framebuffer)))
}
func (c *defaultContext) DeleteProgram(program uint32) {
C.glowDeleteProgram(c.gpDeleteProgram, C.GLuint(program))
}
func (c *defaultContext) DeleteRenderbuffer(renderbuffer uint32) {
C.glowDeleteRenderbuffers(c.gpDeleteRenderbuffers, 1, (*C.GLuint)(unsafe.Pointer(&renderbuffer)))
}
func (c *defaultContext) DeleteShader(shader uint32) {
C.glowDeleteShader(c.gpDeleteShader, C.GLuint(shader))
}
func (c *defaultContext) DeleteTexture(texture uint32) {
C.glowDeleteTextures(c.gpDeleteTextures, 1, (*C.GLuint)(unsafe.Pointer(&texture)))
}
func (c *defaultContext) DeleteVertexArray(array uint32) {
C.glowDeleteVertexArrays(c.gpDeleteVertexArrays, 1, (*C.GLuint)(unsafe.Pointer(&array)))
}
func (c *defaultContext) Disable(cap uint32) {
C.glowDisable(c.gpDisable, C.GLenum(cap))
}
func (c *defaultContext) DisableVertexAttribArray(index uint32) {
C.glowDisableVertexAttribArray(c.gpDisableVertexAttribArray, C.GLuint(index))
}
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
C.glowDrawElements(c.gpDrawElements, C.GLenum(mode), C.GLsizei(count), C.GLenum(xtype), C.uintptr_t(offset))
}
func (c *defaultContext) Enable(cap uint32) {
C.glowEnable(c.gpEnable, C.GLenum(cap))
}
func (c *defaultContext) EnableVertexAttribArray(index uint32) {
C.glowEnableVertexAttribArray(c.gpEnableVertexAttribArray, C.GLuint(index))
}
func (c *defaultContext) Flush() {
C.glowFlush(c.gpFlush)
}
func (c *defaultContext) FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32) {
C.glowFramebufferRenderbuffer(c.gpFramebufferRenderbuffer, C.GLenum(target), C.GLenum(attachment), C.GLenum(renderbuffertarget), C.GLuint(renderbuffer))
}
func (c *defaultContext) FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32) {
C.glowFramebufferTexture2D(c.gpFramebufferTexture2D, C.GLenum(target), C.GLenum(attachment), C.GLenum(textarget), C.GLuint(texture), C.GLint(level))
}
func (c *defaultContext) GetError() uint32 {
ret := C.glowGetError(c.gpGetError)
return uint32(ret)
}
func (c *defaultContext) GetInteger(pname uint32) int {
var dst int32
C.glowGetIntegerv(c.gpGetIntegerv, C.GLenum(pname), (*C.GLint)(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
bufSize := c.GetProgrami(program, INFO_LOG_LENGTH)
infoLog := make([]byte, bufSize)
C.glowGetProgramInfoLog(c.gpGetProgramInfoLog, C.GLuint(program), C.GLsizei(bufSize), nil, (*C.GLchar)(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
}
func (c *defaultContext) GetProgrami(program uint32, pname uint32) int {
var dst int32
C.glowGetProgramiv(c.gpGetProgramiv, C.GLuint(program), C.GLenum(pname), (*C.GLint)(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
bufSize := c.GetShaderi(shader, INFO_LOG_LENGTH)
infoLog := make([]byte, bufSize)
C.glowGetShaderInfoLog(c.gpGetShaderInfoLog, C.GLuint(shader), C.GLsizei(bufSize), nil, (*C.GLchar)(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
}
func (c *defaultContext) GetShaderi(shader uint32, pname uint32) int {
var dst int32
C.glowGetShaderiv(c.gpGetShaderiv, C.GLuint(shader), C.GLenum(pname), (*C.GLint)(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetUniformLocation(program uint32, name string) int32 {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
ret := C.glowGetUniformLocation(c.gpGetUniformLocation, C.GLuint(program), (*C.GLchar)(unsafe.Pointer(cname)))
return int32(ret)
}
func (c *defaultContext) IsFramebuffer(framebuffer uint32) bool {
ret := C.glowIsFramebuffer(c.gpIsFramebuffer, C.GLuint(framebuffer))
return ret == TRUE
}
func (c *defaultContext) IsProgram(program uint32) bool {
ret := C.glowIsProgram(c.gpIsProgram, C.GLuint(program))
return ret == TRUE
}
func (c *defaultContext) IsRenderbuffer(renderbuffer uint32) bool {
ret := C.glowIsRenderbuffer(c.gpIsRenderbuffer, C.GLuint(renderbuffer))
return ret == TRUE
}
func (c *defaultContext) LinkProgram(program uint32) {
C.glowLinkProgram(c.gpLinkProgram, C.GLuint(program))
}
func (c *defaultContext) PixelStorei(pname uint32, param int32) {
C.glowPixelStorei(c.gpPixelStorei, C.GLenum(pname), C.GLint(param))
}
func (c *defaultContext) ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32) {
C.glowReadPixels(c.gpReadPixels, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(xtype), unsafe.Pointer(&dst[0]))
}
func (c *defaultContext) RenderbufferStorage(target uint32, internalformat uint32, width int32, height int32) {
C.glowRenderbufferStorage(c.gpRenderbufferStorage, C.GLenum(target), C.GLenum(internalformat), C.GLsizei(width), C.GLsizei(height))
}
func (c *defaultContext) Scissor(x int32, y int32, width int32, height int32) {
C.glowScissor(c.gpScissor, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
}
func (c *defaultContext) ShaderSource(shader uint32, xstring string) {
cstring := C.CString(xstring)
defer C.free(unsafe.Pointer(cstring))
C.glowShaderSource(c.gpShaderSource, C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(&cstring)), nil)
}
func (c *defaultContext) StencilFunc(xfunc uint32, ref int32, mask uint32) {
C.glowStencilFunc(c.gpStencilFunc, C.GLenum(xfunc), C.GLint(ref), C.GLuint(mask))
}
func (c *defaultContext) StencilOpSeparate(face uint32, fail uint32, zfail uint32, zpass uint32) {
C.glowStencilOpSeparate(c.gpStencilOpSeparate, C.GLenum(face), C.GLenum(fail), C.GLenum(zfail), C.GLenum(zpass))
}
func (c *defaultContext) TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
var ptr *byte
if len(pixels) > 0 {
ptr = &pixels[0]
}
C.glowTexImage2D(c.gpTexImage2D, C.GLenum(target), C.GLint(level), C.GLint(internalformat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(format), C.GLenum(xtype), unsafe.Pointer(ptr))
runtime.KeepAlive(pixels)
}
func (c *defaultContext) TexParameteri(target uint32, pname uint32, param int32) {
C.glowTexParameteri(c.gpTexParameteri, C.GLenum(target), C.GLenum(pname), C.GLint(param))
}
func (c *defaultContext) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
C.glowTexSubImage2D(c.gpTexSubImage2D, C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(xtype), unsafe.Pointer(&pixels[0]))
runtime.KeepAlive(pixels)
}
func (c *defaultContext) Uniform1fv(location int32, value []float32) {
C.glowUniform1fv(c.gpUniform1fv, C.GLint(location), C.GLsizei(len(value)), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform1i(location int32, v0 int32) {
C.glowUniform1i(c.gpUniform1i, C.GLint(location), C.GLint(v0))
}
func (c *defaultContext) Uniform1iv(location int32, value []int32) {
C.glowUniform1iv(c.gpUniform1iv, C.GLint(location), C.GLsizei(len(value)), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform2fv(location int32, value []float32) {
C.glowUniform2fv(c.gpUniform2fv, C.GLint(location), C.GLsizei(len(value)/2), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
C.glowUniform2iv(c.gpUniform2iv, C.GLint(location), C.GLsizei(len(value)/2), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) {
C.glowUniform3fv(c.gpUniform3fv, C.GLint(location), C.GLsizei(len(value)/3), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
C.glowUniform3iv(c.gpUniform3iv, C.GLint(location), C.GLsizei(len(value)/3), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) {
C.glowUniform4fv(c.gpUniform4fv, C.GLint(location), C.GLsizei(len(value)/4), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
C.glowUniform4iv(c.gpUniform4iv, C.GLint(location), C.GLsizei(len(value)/4), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
C.glowUniformMatrix2fv(c.gpUniformMatrix2fv, C.GLint(location), C.GLsizei(len(value)/4), 0, (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix3fv(location int32, value []float32) {
C.glowUniformMatrix3fv(c.gpUniformMatrix3fv, C.GLint(location), C.GLsizei(len(value)/9), 0, (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix4fv(location int32, value []float32) {
C.glowUniformMatrix4fv(c.gpUniformMatrix4fv, C.GLint(location), C.GLsizei(len(value)/16), 0, (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UseProgram(program uint32) {
C.glowUseProgram(c.gpUseProgram, C.GLuint(program))
}
func (c *defaultContext) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset int) {
C.glowVertexAttribPointer(c.gpVertexAttribPointer, C.GLuint(index), C.GLint(size), C.GLenum(xtype), C.GLboolean(boolToInt(normalized)), C.GLsizei(stride), C.uintptr_t(offset))
}
func (c *defaultContext) Viewport(x int32, y int32, width int32, height int32) {
C.glowViewport(c.gpViewport, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
}
func (c *defaultContext) LoadFunctions() error {
g := procAddressGetter{ctx: c}
c.gpActiveTexture = C.uintptr_t(g.get("glActiveTexture"))
c.gpAttachShader = C.uintptr_t(g.get("glAttachShader"))
c.gpBindAttribLocation = C.uintptr_t(g.get("glBindAttribLocation"))
c.gpBindBuffer = C.uintptr_t(g.get("glBindBuffer"))
c.gpBindFramebuffer = C.uintptr_t(g.get("glBindFramebuffer"))
c.gpBindRenderbuffer = C.uintptr_t(g.get("glBindRenderbuffer"))
c.gpBindTexture = C.uintptr_t(g.get("glBindTexture"))
c.gpBindVertexArray = C.uintptr_t(g.get("glBindVertexArray"))
c.gpBlendEquationSeparate = C.uintptr_t(g.get("glBlendEquationSeparate"))
c.gpBlendFuncSeparate = C.uintptr_t(g.get("glBlendFuncSeparate"))
c.gpBufferData = C.uintptr_t(g.get("glBufferData"))
c.gpBufferSubData = C.uintptr_t(g.get("glBufferSubData"))
c.gpCheckFramebufferStatus = C.uintptr_t(g.get("glCheckFramebufferStatus"))
c.gpClear = C.uintptr_t(g.get("glClear"))
c.gpColorMask = C.uintptr_t(g.get("glColorMask"))
c.gpCompileShader = C.uintptr_t(g.get("glCompileShader"))
c.gpCreateProgram = C.uintptr_t(g.get("glCreateProgram"))
c.gpCreateShader = C.uintptr_t(g.get("glCreateShader"))
c.gpDeleteBuffers = C.uintptr_t(g.get("glDeleteBuffers"))
c.gpDeleteFramebuffers = C.uintptr_t(g.get("glDeleteFramebuffers"))
c.gpDeleteProgram = C.uintptr_t(g.get("glDeleteProgram"))
c.gpDeleteRenderbuffers = C.uintptr_t(g.get("glDeleteRenderbuffers"))
c.gpDeleteShader = C.uintptr_t(g.get("glDeleteShader"))
c.gpDeleteTextures = C.uintptr_t(g.get("glDeleteTextures"))
c.gpDeleteVertexArrays = C.uintptr_t(g.get("glDeleteVertexArrays"))
c.gpDisable = C.uintptr_t(g.get("glDisable"))
c.gpDisableVertexAttribArray = C.uintptr_t(g.get("glDisableVertexAttribArray"))
c.gpDrawElements = C.uintptr_t(g.get("glDrawElements"))
c.gpEnable = C.uintptr_t(g.get("glEnable"))
c.gpEnableVertexAttribArray = C.uintptr_t(g.get("glEnableVertexAttribArray"))
c.gpFlush = C.uintptr_t(g.get("glFlush"))
c.gpFramebufferRenderbuffer = C.uintptr_t(g.get("glFramebufferRenderbuffer"))
c.gpFramebufferTexture2D = C.uintptr_t(g.get("glFramebufferTexture2D"))
c.gpGenBuffers = C.uintptr_t(g.get("glGenBuffers"))
c.gpGenFramebuffers = C.uintptr_t(g.get("glGenFramebuffers"))
c.gpGenRenderbuffers = C.uintptr_t(g.get("glGenRenderbuffers"))
c.gpGenTextures = C.uintptr_t(g.get("glGenTextures"))
c.gpGenVertexArrays = C.uintptr_t(g.get("glGenVertexArrays"))
c.gpGetError = C.uintptr_t(g.get("glGetError"))
c.gpGetIntegerv = C.uintptr_t(g.get("glGetIntegerv"))
c.gpGetProgramInfoLog = C.uintptr_t(g.get("glGetProgramInfoLog"))
c.gpGetProgramiv = C.uintptr_t(g.get("glGetProgramiv"))
c.gpGetShaderInfoLog = C.uintptr_t(g.get("glGetShaderInfoLog"))
c.gpGetShaderiv = C.uintptr_t(g.get("glGetShaderiv"))
c.gpGetUniformLocation = C.uintptr_t(g.get("glGetUniformLocation"))
c.gpIsFramebuffer = C.uintptr_t(g.get("glIsFramebuffer"))
c.gpIsProgram = C.uintptr_t(g.get("glIsProgram"))
c.gpIsRenderbuffer = C.uintptr_t(g.get("glIsRenderbuffer"))
c.gpLinkProgram = C.uintptr_t(g.get("glLinkProgram"))
c.gpPixelStorei = C.uintptr_t(g.get("glPixelStorei"))
c.gpReadPixels = C.uintptr_t(g.get("glReadPixels"))
c.gpRenderbufferStorage = C.uintptr_t(g.get("glRenderbufferStorage"))
c.gpScissor = C.uintptr_t(g.get("glScissor"))
c.gpShaderSource = C.uintptr_t(g.get("glShaderSource"))
c.gpStencilFunc = C.uintptr_t(g.get("glStencilFunc"))
c.gpStencilOpSeparate = C.uintptr_t(g.get("glStencilOpSeparate"))
c.gpTexImage2D = C.uintptr_t(g.get("glTexImage2D"))
c.gpTexParameteri = C.uintptr_t(g.get("glTexParameteri"))
c.gpTexSubImage2D = C.uintptr_t(g.get("glTexSubImage2D"))
c.gpUniform1fv = C.uintptr_t(g.get("glUniform1fv"))
c.gpUniform1i = C.uintptr_t(g.get("glUniform1i"))
c.gpUniform1iv = C.uintptr_t(g.get("glUniform1iv"))
c.gpUniform2fv = C.uintptr_t(g.get("glUniform2fv"))
c.gpUniform2iv = C.uintptr_t(g.get("glUniform2iv"))
c.gpUniform3fv = C.uintptr_t(g.get("glUniform3fv"))
c.gpUniform3iv = C.uintptr_t(g.get("glUniform3iv"))
c.gpUniform4fv = C.uintptr_t(g.get("glUniform4fv"))
c.gpUniform4iv = C.uintptr_t(g.get("glUniform4iv"))
c.gpUniformMatrix2fv = C.uintptr_t(g.get("glUniformMatrix2fv"))
c.gpUniformMatrix3fv = C.uintptr_t(g.get("glUniformMatrix3fv"))
c.gpUniformMatrix4fv = C.uintptr_t(g.get("glUniformMatrix4fv"))
c.gpUseProgram = C.uintptr_t(g.get("glUseProgram"))
c.gpVertexAttribPointer = C.uintptr_t(g.get("glVertexAttribPointer"))
c.gpViewport = C.uintptr_t(g.get("glViewport"))
return g.error()
}
@@ -0,0 +1,634 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gl
import (
"fmt"
"syscall/js"
"github.com/hajimehoshi/ebiten/v2/internal/jsutil"
)
type defaultContext struct {
fnActiveTexture js.Value
fnAttachShader js.Value
fnBindAttribLocation js.Value
fnBindBuffer js.Value
fnBindFramebuffer js.Value
fnBindRenderbuffer js.Value
fnBindTexture js.Value
fnBindVertexArray js.Value
fnBlendEquationSeparate js.Value
fnBlendFuncSeparate js.Value
fnBufferData js.Value
fnBufferSubData js.Value
fnCheckFramebufferStatus js.Value
fnClear js.Value
fnColorMask js.Value
fnCompileShader js.Value
fnCreateBuffer js.Value
fnCreateFramebuffer js.Value
fnCreateProgram js.Value
fnCreateRenderbuffer js.Value
fnCreateShader js.Value
fnCreateTexture js.Value
fnCreateVertexArray js.Value
fnDeleteBuffer js.Value
fnDeleteFramebuffer js.Value
fnDeleteProgram js.Value
fnDeleteRenderbuffer js.Value
fnDeleteShader js.Value
fnDeleteTexture js.Value
fnDeleteVertexArray js.Value
fnDisable js.Value
fnDisableVertexAttribArray js.Value
fnDrawElements js.Value
fnEnable js.Value
fnEnableVertexAttribArray js.Value
fnFramebufferRenderbuffer js.Value
fnFramebufferTexture2D js.Value
fnFlush js.Value
fnGetError js.Value
fnGetParameter js.Value
fnGetProgramInfoLog js.Value
fnGetProgramParameter js.Value
fnGetShaderInfoLog js.Value
fnGetShaderParameter js.Value
fnGetUniformLocation js.Value
fnIsFramebuffer js.Value
fnIsProgram js.Value
fnIsRenderbuffer js.Value
fnLinkProgram js.Value
fnPixelStorei js.Value
fnReadPixels js.Value
fnRenderbufferStorage js.Value
fnScissor js.Value
fnShaderSource js.Value
fnStencilFunc js.Value
fnStencilMask js.Value
fnStencilOpSeparate js.Value
fnTexImage2D js.Value
fnTexSubImage2D js.Value
fnTexParameteri js.Value
fnUniform1fv js.Value
fnUniform1i js.Value
fnUniform1iv js.Value
fnUniform2fv js.Value
fnUniform2iv js.Value
fnUniform3fv js.Value
fnUniform3iv js.Value
fnUniform4fv js.Value
fnUniform4iv js.Value
fnUniformMatrix2fv js.Value
fnUniformMatrix3fv js.Value
fnUniformMatrix4fv js.Value
fnUseProgram js.Value
fnVertexAttribPointer js.Value
fnViewport js.Value
buffers values
framebuffers values
programs values
renderbuffers values
shaders values
textures values
vertexArrays values
uniformLocations map[uint32]*values
}
type values struct {
idToValue map[uint32]js.Value
lastID uint32
}
func (v *values) create(value js.Value) uint32 {
v.lastID++
id := v.lastID
if v.idToValue == nil {
v.idToValue = map[uint32]js.Value{}
}
v.idToValue[id] = value
return id
}
func (v *values) get(id uint32) js.Value {
return v.idToValue[id]
}
func (v *values) getID(value js.Value) (uint32, bool) {
for id, v := range v.idToValue {
if v.Equal(value) {
return id, true
}
}
return 0, false
}
func (v *values) getOrCreate(value js.Value) uint32 {
id, ok := v.getID(value)
if ok {
return id
}
return v.create(value)
}
func (v *values) delete(id uint32) {
delete(v.idToValue, id)
}
func NewDefaultContext(v js.Value) (Context, error) {
// 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.
g := &defaultContext{
fnActiveTexture: v.Get("activeTexture").Call("bind", v),
fnAttachShader: v.Get("attachShader").Call("bind", v),
fnBindAttribLocation: v.Get("bindAttribLocation").Call("bind", v),
fnBindBuffer: v.Get("bindBuffer").Call("bind", v),
fnBindFramebuffer: v.Get("bindFramebuffer").Call("bind", v),
fnBindRenderbuffer: v.Get("bindRenderbuffer").Call("bind", v),
fnBindTexture: v.Get("bindTexture").Call("bind", v),
fnBindVertexArray: v.Get("bindVertexArray").Call("bind", v),
fnBlendEquationSeparate: v.Get("blendEquationSeparate").Call("bind", v),
fnBlendFuncSeparate: v.Get("blendFuncSeparate").Call("bind", v),
fnBufferData: v.Get("bufferData").Call("bind", v),
fnBufferSubData: v.Get("bufferSubData").Call("bind", v),
fnCheckFramebufferStatus: v.Get("checkFramebufferStatus").Call("bind", v),
fnClear: v.Get("clear").Call("bind", v),
fnColorMask: v.Get("colorMask").Call("bind", v),
fnCompileShader: v.Get("compileShader").Call("bind", v),
fnCreateBuffer: v.Get("createBuffer").Call("bind", v),
fnCreateFramebuffer: v.Get("createFramebuffer").Call("bind", v),
fnCreateProgram: v.Get("createProgram").Call("bind", v),
fnCreateRenderbuffer: v.Get("createRenderbuffer").Call("bind", v),
fnCreateShader: v.Get("createShader").Call("bind", v),
fnCreateTexture: v.Get("createTexture").Call("bind", v),
fnCreateVertexArray: v.Get("createVertexArray").Call("bind", v),
fnDeleteBuffer: v.Get("deleteBuffer").Call("bind", v),
fnDeleteFramebuffer: v.Get("deleteFramebuffer").Call("bind", v),
fnDeleteProgram: v.Get("deleteProgram").Call("bind", v),
fnDeleteRenderbuffer: v.Get("deleteRenderbuffer").Call("bind", v),
fnDeleteShader: v.Get("deleteShader").Call("bind", v),
fnDeleteTexture: v.Get("deleteTexture").Call("bind", v),
fnDeleteVertexArray: v.Get("deleteVertexArray").Call("bind", v),
fnDisable: v.Get("disable").Call("bind", v),
fnDisableVertexAttribArray: v.Get("disableVertexAttribArray").Call("bind", v),
fnDrawElements: v.Get("drawElements").Call("bind", v),
fnEnable: v.Get("enable").Call("bind", v),
fnEnableVertexAttribArray: v.Get("enableVertexAttribArray").Call("bind", v),
fnFramebufferRenderbuffer: v.Get("framebufferRenderbuffer").Call("bind", v),
fnFramebufferTexture2D: v.Get("framebufferTexture2D").Call("bind", v),
fnFlush: v.Get("flush").Call("bind", v),
fnGetError: v.Get("getError").Call("bind", v),
fnGetParameter: v.Get("getParameter").Call("bind", v),
fnGetProgramInfoLog: v.Get("getProgramInfoLog").Call("bind", v),
fnGetProgramParameter: v.Get("getProgramParameter").Call("bind", v),
fnGetShaderInfoLog: v.Get("getShaderInfoLog").Call("bind", v),
fnGetShaderParameter: v.Get("getShaderParameter").Call("bind", v),
fnGetUniformLocation: v.Get("getUniformLocation").Call("bind", v),
fnIsFramebuffer: v.Get("isFramebuffer").Call("bind", v),
fnIsProgram: v.Get("isProgram").Call("bind", v),
fnIsRenderbuffer: v.Get("isRenderbuffer").Call("bind", v),
fnLinkProgram: v.Get("linkProgram").Call("bind", v),
fnPixelStorei: v.Get("pixelStorei").Call("bind", v),
fnReadPixels: v.Get("readPixels").Call("bind", v),
fnRenderbufferStorage: v.Get("renderbufferStorage").Call("bind", v),
fnScissor: v.Get("scissor").Call("bind", v),
fnShaderSource: v.Get("shaderSource").Call("bind", v),
fnStencilFunc: v.Get("stencilFunc").Call("bind", v),
fnStencilMask: v.Get("stencilMask").Call("bind", v),
fnStencilOpSeparate: v.Get("stencilOpSeparate").Call("bind", v),
fnTexImage2D: v.Get("texImage2D").Call("bind", v),
fnTexSubImage2D: v.Get("texSubImage2D").Call("bind", v),
fnTexParameteri: v.Get("texParameteri").Call("bind", v),
fnUniform1fv: v.Get("uniform1fv").Call("bind", v),
fnUniform1i: v.Get("uniform1i").Call("bind", v),
fnUniform1iv: v.Get("uniform1iv").Call("bind", v),
fnUniform2fv: v.Get("uniform2fv").Call("bind", v),
fnUniform2iv: v.Get("uniform2iv").Call("bind", v),
fnUniform3fv: v.Get("uniform3fv").Call("bind", v),
fnUniform3iv: v.Get("uniform3iv").Call("bind", v),
fnUniform4fv: v.Get("uniform4fv").Call("bind", v),
fnUniform4iv: v.Get("uniform4iv").Call("bind", v),
fnUniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v),
fnUniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v),
fnUniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v),
fnUseProgram: v.Get("useProgram").Call("bind", v),
fnVertexAttribPointer: v.Get("vertexAttribPointer").Call("bind", v),
fnViewport: v.Get("viewport").Call("bind", v),
}
return g, nil
}
func (c *defaultContext) getUniformLocation(location int32) js.Value {
program := uint32(location) >> 5
return c.uniformLocations[program].get(uint32(location) & ((1 << 5) - 1))
}
func (c *defaultContext) LoadFunctions() error {
return nil
}
func (c *defaultContext) IsES() bool {
// WebGL is compatible with GLES.
return true
}
func (c *defaultContext) ActiveTexture(texture uint32) {
c.fnActiveTexture.Invoke(texture)
}
func (c *defaultContext) AttachShader(program uint32, shader uint32) {
c.fnAttachShader.Invoke(c.programs.get(program), c.shaders.get(shader))
}
func (c *defaultContext) BindAttribLocation(program uint32, index uint32, name string) {
c.fnBindAttribLocation.Invoke(c.programs.get(program), index, name)
}
func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
c.fnBindBuffer.Invoke(target, c.buffers.get(buffer))
}
func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) {
c.fnBindFramebuffer.Invoke(target, c.framebuffers.get(framebuffer))
}
func (c *defaultContext) BindRenderbuffer(target uint32, renderbuffer uint32) {
c.fnBindRenderbuffer.Invoke(target, c.renderbuffers.get(renderbuffer))
}
func (c *defaultContext) BindTexture(target uint32, texture uint32) {
c.fnBindTexture.Invoke(target, c.textures.get(texture))
}
func (c *defaultContext) BindVertexArray(array uint32) {
c.fnBindVertexArray.Invoke(c.vertexArrays.get(array))
}
func (c *defaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
c.fnBlendEquationSeparate.Invoke(modeRGB, modeAlpha)
}
func (c *defaultContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
c.fnBlendFuncSeparate.Invoke(srcRGB, dstRGB, srcAlpha, dstAlpha)
}
func (c *defaultContext) BufferInit(target uint32, size int, usage uint32) {
c.fnBufferData.Invoke(target, size, usage)
}
func (c *defaultContext) BufferSubData(target uint32, offset int, data []byte) {
l := len(data)
arr := jsutil.TemporaryUint8ArrayFromUint8Slice(l, data)
c.fnBufferSubData.Invoke(target, offset, arr, 0, l)
}
func (c *defaultContext) CheckFramebufferStatus(target uint32) uint32 {
return uint32(c.fnCheckFramebufferStatus.Invoke(target).Int())
}
func (c *defaultContext) Clear(mask uint32) {
c.fnClear.Invoke(mask)
}
func (c *defaultContext) ColorMask(red, green, blue, alpha bool) {
c.fnColorMask.Invoke(red, green, blue, alpha)
}
func (c *defaultContext) CompileShader(shader uint32) {
c.fnCompileShader.Invoke(c.shaders.get(shader))
}
func (c *defaultContext) CreateBuffer() uint32 {
return c.buffers.create(c.fnCreateBuffer.Invoke())
}
func (c *defaultContext) CreateFramebuffer() uint32 {
return c.framebuffers.create(c.fnCreateFramebuffer.Invoke())
}
func (c *defaultContext) CreateProgram() uint32 {
return c.programs.create(c.fnCreateProgram.Invoke())
}
func (c *defaultContext) CreateRenderbuffer() uint32 {
return c.renderbuffers.create(c.fnCreateRenderbuffer.Invoke())
}
func (c *defaultContext) CreateShader(xtype uint32) uint32 {
return c.shaders.create(c.fnCreateShader.Invoke(xtype))
}
func (c *defaultContext) CreateTexture() uint32 {
return c.textures.create(c.fnCreateTexture.Invoke())
}
func (c *defaultContext) CreateVertexArray() uint32 {
return c.vertexArrays.create(c.fnCreateVertexArray.Invoke())
}
func (c *defaultContext) DeleteBuffer(buffer uint32) {
c.fnDeleteBuffer.Invoke(c.buffers.get(buffer))
c.buffers.delete(buffer)
}
func (c *defaultContext) DeleteFramebuffer(framebuffer uint32) {
c.fnDeleteFramebuffer.Invoke(c.framebuffers.get(framebuffer))
c.framebuffers.delete(framebuffer)
}
func (c *defaultContext) DeleteProgram(program uint32) {
c.fnDeleteProgram.Invoke(c.programs.get(program))
c.programs.delete(program)
delete(c.uniformLocations, program)
}
func (c *defaultContext) DeleteRenderbuffer(renderbuffer uint32) {
c.fnDeleteRenderbuffer.Invoke(c.renderbuffers.get(renderbuffer))
c.renderbuffers.delete(renderbuffer)
}
func (c *defaultContext) DeleteShader(shader uint32) {
c.fnDeleteShader.Invoke(c.shaders.get(shader))
c.shaders.delete(shader)
}
func (c *defaultContext) DeleteTexture(texture uint32) {
c.fnDeleteTexture.Invoke(c.textures.get(texture))
c.textures.delete(texture)
}
func (c *defaultContext) DeleteVertexArray(array uint32) {
c.fnDeleteVertexArray.Invoke(c.vertexArrays.get(array))
c.textures.delete(array)
}
func (c *defaultContext) Disable(cap uint32) {
c.fnDisable.Invoke(cap)
}
func (c *defaultContext) DisableVertexAttribArray(index uint32) {
c.fnDisableVertexAttribArray.Invoke(index)
}
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
c.fnDrawElements.Invoke(mode, count, xtype, offset)
}
func (c *defaultContext) Enable(cap uint32) {
c.fnEnable.Invoke(cap)
}
func (c *defaultContext) EnableVertexAttribArray(index uint32) {
c.fnEnableVertexAttribArray.Invoke(index)
}
func (c *defaultContext) Flush() {
c.fnFlush.Invoke()
}
func (c *defaultContext) FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32) {
c.fnFramebufferRenderbuffer.Invoke(target, attachment, renderbuffertarget, c.renderbuffers.get(renderbuffer))
}
func (c *defaultContext) FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32) {
c.fnFramebufferTexture2D.Invoke(target, attachment, textarget, c.textures.get(texture), level)
}
func (c *defaultContext) GetError() uint32 {
return uint32(c.fnGetError.Invoke().Int())
}
func (c *defaultContext) GetInteger(pname uint32) int {
ret := c.fnGetParameter.Invoke(pname)
switch pname {
case FRAMEBUFFER_BINDING:
id, ok := c.framebuffers.getID(ret)
if !ok {
return 0
}
return int(id)
case MAX_TEXTURE_SIZE:
return ret.Int()
default:
panic(fmt.Sprintf("gl: unexpected pname at GetInteger: %d", pname))
}
}
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
return c.fnGetProgramInfoLog.Invoke(c.programs.get(program)).String()
}
func (c *defaultContext) GetProgrami(program uint32, pname uint32) int {
v := c.fnGetProgramParameter.Invoke(c.programs.get(program), pname)
switch v.Type() {
case js.TypeNumber:
return v.Int()
case js.TypeBoolean:
if v.Bool() {
return TRUE
}
return FALSE
default:
panic(fmt.Sprintf("gl: unexpected return type at GetProgrami: %v", v))
}
}
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
return c.fnGetShaderInfoLog.Invoke(c.shaders.get(shader)).String()
}
func (c *defaultContext) GetShaderi(shader uint32, pname uint32) int {
v := c.fnGetShaderParameter.Invoke(c.shaders.get(shader), pname)
switch v.Type() {
case js.TypeNumber:
return v.Int()
case js.TypeBoolean:
if v.Bool() {
return TRUE
}
return FALSE
default:
panic(fmt.Sprintf("gl: unexpected return type at GetShaderi: %v", v))
}
}
func (c *defaultContext) GetUniformLocation(program uint32, name string) int32 {
location := c.fnGetUniformLocation.Invoke(c.programs.get(program), name)
if c.uniformLocations == nil {
c.uniformLocations = map[uint32]*values{}
}
vs, ok := c.uniformLocations[program]
if !ok {
vs = &values{}
c.uniformLocations[program] = vs
}
idx := vs.getOrCreate(location)
return int32((program << 5) | idx)
}
func (c *defaultContext) IsFramebuffer(framebuffer uint32) bool {
return c.fnIsFramebuffer.Invoke(c.framebuffers.get(framebuffer)).Bool()
}
func (c *defaultContext) IsProgram(program uint32) bool {
return c.fnIsProgram.Invoke(c.programs.get(program)).Bool()
}
func (c *defaultContext) IsRenderbuffer(renderbuffer uint32) bool {
return c.fnIsRenderbuffer.Invoke(c.renderbuffers.get(renderbuffer)).Bool()
}
func (c *defaultContext) LinkProgram(program uint32) {
c.fnLinkProgram.Invoke(c.programs.get(program))
}
func (c *defaultContext) PixelStorei(pname uint32, param int32) {
c.fnPixelStorei.Invoke(pname, param)
}
func (c *defaultContext) ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32) {
if dst == nil {
c.fnReadPixels.Invoke(x, y, width, height, format, xtype, 0)
return
}
p := jsutil.TemporaryUint8ArrayFromUint8Slice(len(dst), nil)
c.fnReadPixels.Invoke(x, y, width, height, format, xtype, p)
js.CopyBytesToGo(dst, p)
}
func (c *defaultContext) RenderbufferStorage(target uint32, internalFormat uint32, width int32, height int32) {
c.fnRenderbufferStorage.Invoke(target, internalFormat, width, height)
}
func (c *defaultContext) Scissor(x, y, width, height int32) {
c.fnScissor.Invoke(x, y, width, height)
}
func (c *defaultContext) ShaderSource(shader uint32, xstring string) {
c.fnShaderSource.Invoke(c.shaders.get(shader), xstring)
}
func (c *defaultContext) StencilFunc(func_ uint32, ref int32, mask uint32) {
c.fnStencilFunc.Invoke(func_, ref, mask)
}
func (c *defaultContext) StencilOpSeparate(face, sfail, dpfail, dppass uint32) {
c.fnStencilOpSeparate.Invoke(face, sfail, dpfail, dppass)
}
func (c *defaultContext) TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
if pixels != nil {
panic("gl: TexImage2D with non-nil pixels is not implemented")
}
c.fnTexImage2D.Invoke(target, level, internalformat, width, height, 0, format, xtype, nil)
}
func (c *defaultContext) TexParameteri(target uint32, pname uint32, param int32) {
c.fnTexParameteri.Invoke(target, pname, param)
}
func (c *defaultContext) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
arr := jsutil.TemporaryUint8ArrayFromUint8Slice(len(pixels), pixels)
// void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
// GLsizei width, GLsizei height,
// GLenum format, GLenum type, ArrayBufferView pixels, srcOffset);
c.fnTexSubImage2D.Invoke(target, level, xoffset, yoffset, width, height, format, xtype, arr, 0)
}
func (c *defaultContext) Uniform1fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniform1fv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform1i(location int32, v0 int32) {
l := c.getUniformLocation(location)
c.fnUniform1i.Invoke(l, v0)
}
func (c *defaultContext) Uniform1iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
c.fnUniform1iv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform2fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniform2fv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
c.fnUniform2iv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniform3fv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
c.fnUniform3iv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniform4fv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
c.fnUniform4iv.Invoke(l, arr, 0, len(value))
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniformMatrix2fv.Invoke(l, false, arr, 0, len(value))
}
func (c *defaultContext) UniformMatrix3fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniformMatrix3fv.Invoke(l, false, arr, 0, len(value))
}
func (c *defaultContext) UniformMatrix4fv(location int32, value []float32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value)
c.fnUniformMatrix4fv.Invoke(l, false, arr, 0, len(value))
}
func (c *defaultContext) UseProgram(program uint32) {
c.fnUseProgram.Invoke(c.programs.get(program))
}
func (c *defaultContext) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset int) {
c.fnVertexAttribPointer.Invoke(index, size, xtype, normalized, stride, offset)
}
func (c *defaultContext) Viewport(x int32, y int32, width int32, height int32) {
c.fnViewport.Invoke(x, y, width, height)
}
@@ -0,0 +1,569 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build darwin || windows
package gl
import (
"runtime"
"unsafe"
"github.com/ebitengine/purego"
)
type defaultContext struct {
gpActiveTexture uintptr
gpAttachShader uintptr
gpBindAttribLocation uintptr
gpBindBuffer uintptr
gpBindFramebuffer uintptr
gpBindRenderbuffer uintptr
gpBindTexture uintptr
gpBindVertexArray uintptr
gpBlendEquationSeparate uintptr
gpBlendFuncSeparate uintptr
gpBufferData uintptr
gpBufferSubData uintptr
gpCheckFramebufferStatus uintptr
gpClear uintptr
gpColorMask uintptr
gpCompileShader uintptr
gpCreateProgram uintptr
gpCreateShader uintptr
gpDeleteBuffers uintptr
gpDeleteFramebuffers uintptr
gpDeleteProgram uintptr
gpDeleteRenderbuffers uintptr
gpDeleteShader uintptr
gpDeleteTextures uintptr
gpDeleteVertexArrays uintptr
gpDisable uintptr
gpDisableVertexAttribArray uintptr
gpDrawElements uintptr
gpEnable uintptr
gpEnableVertexAttribArray uintptr
gpFlush uintptr
gpFramebufferRenderbuffer uintptr
gpFramebufferTexture2D uintptr
gpGenBuffers uintptr
gpGenFramebuffers uintptr
gpGenRenderbuffers uintptr
gpGenTextures uintptr
gpGenVertexArrays uintptr
gpGetError uintptr
gpGetIntegerv uintptr
gpGetProgramInfoLog uintptr
gpGetProgramiv uintptr
gpGetShaderInfoLog uintptr
gpGetShaderiv uintptr
gpGetUniformLocation uintptr
gpIsFramebuffer uintptr
gpIsProgram uintptr
gpIsRenderbuffer uintptr
gpLinkProgram uintptr
gpPixelStorei uintptr
gpReadPixels uintptr
gpRenderbufferStorage uintptr
gpScissor uintptr
gpShaderSource uintptr
gpStencilFunc uintptr
gpStencilOpSeparate uintptr
gpTexImage2D uintptr
gpTexParameteri uintptr
gpTexSubImage2D uintptr
gpUniform1fv uintptr
gpUniform1i uintptr
gpUniform1iv uintptr
gpUniform2fv uintptr
gpUniform2iv uintptr
gpUniform3fv uintptr
gpUniform3iv uintptr
gpUniform4fv uintptr
gpUniform4iv uintptr
gpUniformMatrix2fv uintptr
gpUniformMatrix3fv uintptr
gpUniformMatrix4fv uintptr
gpUseProgram uintptr
gpVertexAttribPointer uintptr
gpViewport uintptr
isES bool
}
func NewDefaultContext() (Context, error) {
ctx := &defaultContext{}
if err := ctx.init(); err != nil {
return nil, err
}
return ctx, nil
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}
func (c *defaultContext) IsES() bool {
return c.isES
}
func (c *defaultContext) ActiveTexture(texture uint32) {
purego.SyscallN(c.gpActiveTexture, uintptr(texture))
}
func (c *defaultContext) AttachShader(program uint32, shader uint32) {
purego.SyscallN(c.gpAttachShader, uintptr(program), uintptr(shader))
}
func (c *defaultContext) BindAttribLocation(program uint32, index uint32, name string) {
cname, free := cStr(name)
defer free()
purego.SyscallN(c.gpBindAttribLocation, uintptr(program), uintptr(index), uintptr(unsafe.Pointer(cname)))
}
func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
purego.SyscallN(c.gpBindBuffer, uintptr(target), uintptr(buffer))
}
func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) {
purego.SyscallN(c.gpBindFramebuffer, uintptr(target), uintptr(framebuffer))
}
func (c *defaultContext) BindRenderbuffer(target uint32, renderbuffer uint32) {
purego.SyscallN(c.gpBindRenderbuffer, uintptr(target), uintptr(renderbuffer))
}
func (c *defaultContext) BindTexture(target uint32, texture uint32) {
purego.SyscallN(c.gpBindTexture, uintptr(target), uintptr(texture))
}
func (c *defaultContext) BindVertexArray(array uint32) {
purego.SyscallN(c.gpBindVertexArray, uintptr(array))
}
func (c *defaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
purego.SyscallN(c.gpBlendEquationSeparate, uintptr(modeRGB), uintptr(modeAlpha))
}
func (c *defaultContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
purego.SyscallN(c.gpBlendFuncSeparate, uintptr(srcRGB), uintptr(dstRGB), uintptr(srcAlpha), uintptr(dstAlpha))
}
func (c *defaultContext) BufferInit(target uint32, size int, usage uint32) {
purego.SyscallN(c.gpBufferData, uintptr(target), uintptr(size), 0, uintptr(usage))
}
func (c *defaultContext) BufferSubData(target uint32, offset int, data []byte) {
purego.SyscallN(c.gpBufferSubData, uintptr(target), uintptr(offset), uintptr(len(data)), uintptr(unsafe.Pointer(&data[0])))
runtime.KeepAlive(data)
}
func (c *defaultContext) CheckFramebufferStatus(target uint32) uint32 {
ret, _, _ := purego.SyscallN(c.gpCheckFramebufferStatus, uintptr(target))
return uint32(ret)
}
func (c *defaultContext) Clear(mask uint32) {
purego.SyscallN(c.gpClear, uintptr(mask))
}
func (c *defaultContext) ColorMask(red bool, green bool, blue bool, alpha bool) {
purego.SyscallN(c.gpColorMask, uintptr(boolToInt(red)), uintptr(boolToInt(green)), uintptr(boolToInt(blue)), uintptr(boolToInt(alpha)))
}
func (c *defaultContext) CompileShader(shader uint32) {
purego.SyscallN(c.gpCompileShader, uintptr(shader))
}
func (c *defaultContext) CreateBuffer() uint32 {
var buffer uint32
purego.SyscallN(c.gpGenBuffers, 1, uintptr(unsafe.Pointer(&buffer)))
return buffer
}
func (c *defaultContext) CreateFramebuffer() uint32 {
var framebuffer uint32
purego.SyscallN(c.gpGenFramebuffers, 1, uintptr(unsafe.Pointer(&framebuffer)))
return framebuffer
}
func (c *defaultContext) CreateProgram() uint32 {
ret, _, _ := purego.SyscallN(c.gpCreateProgram)
return uint32(ret)
}
func (c *defaultContext) CreateRenderbuffer() uint32 {
var renderbuffer uint32
purego.SyscallN(c.gpGenRenderbuffers, 1, uintptr(unsafe.Pointer(&renderbuffer)))
return renderbuffer
}
func (c *defaultContext) CreateShader(xtype uint32) uint32 {
ret, _, _ := purego.SyscallN(c.gpCreateShader, uintptr(xtype))
return uint32(ret)
}
func (c *defaultContext) CreateTexture() uint32 {
var texture uint32
purego.SyscallN(c.gpGenTextures, 1, uintptr(unsafe.Pointer(&texture)))
return texture
}
func (c *defaultContext) CreateVertexArray() uint32 {
var array uint32
purego.SyscallN(c.gpGenVertexArrays, 1, uintptr(unsafe.Pointer(&array)))
return array
}
func (c *defaultContext) DeleteBuffer(buffer uint32) {
purego.SyscallN(c.gpDeleteBuffers, 1, uintptr(unsafe.Pointer(&buffer)))
}
func (c *defaultContext) DeleteFramebuffer(framebuffer uint32) {
purego.SyscallN(c.gpDeleteFramebuffers, 1, uintptr(unsafe.Pointer(&framebuffer)))
}
func (c *defaultContext) DeleteProgram(program uint32) {
purego.SyscallN(c.gpDeleteProgram, uintptr(program))
}
func (c *defaultContext) DeleteRenderbuffer(renderbuffer uint32) {
purego.SyscallN(c.gpDeleteRenderbuffers, 1, uintptr(unsafe.Pointer(&renderbuffer)))
}
func (c *defaultContext) DeleteShader(shader uint32) {
purego.SyscallN(c.gpDeleteShader, uintptr(shader))
}
func (c *defaultContext) DeleteTexture(texture uint32) {
purego.SyscallN(c.gpDeleteTextures, 1, uintptr(unsafe.Pointer(&texture)))
}
func (c *defaultContext) DeleteVertexArray(array uint32) {
purego.SyscallN(c.gpDeleteVertexArrays, 1, uintptr(unsafe.Pointer(&array)))
}
func (c *defaultContext) Disable(cap uint32) {
purego.SyscallN(c.gpDisable, uintptr(cap))
}
func (c *defaultContext) DisableVertexAttribArray(index uint32) {
purego.SyscallN(c.gpDisableVertexAttribArray, uintptr(index))
}
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
purego.SyscallN(c.gpDrawElements, uintptr(mode), uintptr(count), uintptr(xtype), uintptr(offset))
}
func (c *defaultContext) Enable(cap uint32) {
purego.SyscallN(c.gpEnable, uintptr(cap))
}
func (c *defaultContext) EnableVertexAttribArray(index uint32) {
purego.SyscallN(c.gpEnableVertexAttribArray, uintptr(index))
}
func (c *defaultContext) Flush() {
purego.SyscallN(c.gpFlush)
}
func (c *defaultContext) FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32) {
purego.SyscallN(c.gpFramebufferRenderbuffer, uintptr(target), uintptr(attachment), uintptr(renderbuffertarget), uintptr(renderbuffer))
}
func (c *defaultContext) FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32) {
purego.SyscallN(c.gpFramebufferTexture2D, uintptr(target), uintptr(attachment), uintptr(textarget), uintptr(texture), uintptr(level))
}
func (c *defaultContext) GetError() uint32 {
ret, _, _ := purego.SyscallN(c.gpGetError)
return uint32(ret)
}
func (c *defaultContext) GetInteger(pname uint32) int {
var dst int32
purego.SyscallN(c.gpGetIntegerv, uintptr(pname), uintptr(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
bufSize := c.GetProgrami(program, INFO_LOG_LENGTH)
infoLog := make([]byte, bufSize)
purego.SyscallN(c.gpGetProgramInfoLog, uintptr(program), uintptr(bufSize), 0, uintptr(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
}
func (c *defaultContext) GetProgrami(program uint32, pname uint32) int {
var dst int32
purego.SyscallN(c.gpGetProgramiv, uintptr(program), uintptr(pname), uintptr(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
bufSize := c.GetShaderi(shader, INFO_LOG_LENGTH)
infoLog := make([]byte, bufSize)
purego.SyscallN(c.gpGetShaderInfoLog, uintptr(shader), uintptr(bufSize), 0, uintptr(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
}
func (c *defaultContext) GetShaderi(shader uint32, pname uint32) int {
var dst int32
purego.SyscallN(c.gpGetShaderiv, uintptr(shader), uintptr(pname), uintptr(unsafe.Pointer(&dst)))
return int(dst)
}
func (c *defaultContext) GetUniformLocation(program uint32, name string) int32 {
cname, free := cStr(name)
defer free()
ret, _, _ := purego.SyscallN(c.gpGetUniformLocation, uintptr(program), uintptr(unsafe.Pointer(cname)))
return int32(ret)
}
func (c *defaultContext) IsFramebuffer(framebuffer uint32) bool {
ret, _, _ := purego.SyscallN(c.gpIsFramebuffer, uintptr(framebuffer))
return byte(ret) != 0
}
func (c *defaultContext) IsProgram(program uint32) bool {
ret, _, _ := purego.SyscallN(c.gpIsProgram, uintptr(program))
return byte(ret) != 0
}
func (c *defaultContext) IsRenderbuffer(renderbuffer uint32) bool {
ret, _, _ := purego.SyscallN(c.gpIsRenderbuffer, uintptr(renderbuffer))
return byte(ret) != 0
}
func (c *defaultContext) LinkProgram(program uint32) {
purego.SyscallN(c.gpLinkProgram, uintptr(program))
}
func (c *defaultContext) PixelStorei(pname uint32, param int32) {
purego.SyscallN(c.gpPixelStorei, uintptr(pname), uintptr(param))
}
func (c *defaultContext) ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32) {
purego.SyscallN(c.gpReadPixels, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(&dst[0])))
}
func (c *defaultContext) RenderbufferStorage(target uint32, internalformat uint32, width int32, height int32) {
purego.SyscallN(c.gpRenderbufferStorage, uintptr(target), uintptr(internalformat), uintptr(width), uintptr(height))
}
func (c *defaultContext) Scissor(x int32, y int32, width int32, height int32) {
purego.SyscallN(c.gpScissor, uintptr(x), uintptr(y), uintptr(width), uintptr(height))
}
func (c *defaultContext) ShaderSource(shader uint32, xstring string) {
cstring, free := cStr(xstring)
defer free()
purego.SyscallN(c.gpShaderSource, uintptr(shader), 1, uintptr(unsafe.Pointer(&cstring)), 0)
}
func (c *defaultContext) StencilFunc(xfunc uint32, ref int32, mask uint32) {
purego.SyscallN(c.gpStencilFunc, uintptr(xfunc), uintptr(ref), uintptr(mask))
}
func (c *defaultContext) StencilOpSeparate(face uint32, fail uint32, zfail uint32, zpass uint32) {
purego.SyscallN(c.gpStencilOpSeparate, uintptr(face), uintptr(fail), uintptr(zfail), uintptr(zpass))
}
func (c *defaultContext) TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
var ptr *byte
if len(pixels) > 0 {
ptr = &pixels[0]
}
purego.SyscallN(c.gpTexImage2D, uintptr(target), uintptr(level), uintptr(internalformat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(ptr)))
runtime.KeepAlive(pixels)
}
func (c *defaultContext) TexParameteri(target uint32, pname uint32, param int32) {
purego.SyscallN(c.gpTexParameteri, uintptr(target), uintptr(pname), uintptr(param))
}
func (c *defaultContext) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
purego.SyscallN(c.gpTexSubImage2D, uintptr(target), uintptr(level), uintptr(xoffset), uintptr(yoffset), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(&pixels[0])))
runtime.KeepAlive(pixels)
}
func (c *defaultContext) Uniform1fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform1fv, uintptr(location), uintptr(len(value)), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform1i(location int32, v0 int32) {
purego.SyscallN(c.gpUniform1i, uintptr(location), uintptr(v0))
}
func (c *defaultContext) Uniform1iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform1iv, uintptr(location), uintptr(len(value)), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform2fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform2fv, uintptr(location), uintptr(len(value)/2), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform2iv, uintptr(location), uintptr(len(value)/2), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform3fv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform3iv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform4fv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform4iv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
purego.SyscallN(c.gpUniformMatrix2fv, uintptr(location), uintptr(len(value)/4), 0, uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix3fv(location int32, value []float32) {
purego.SyscallN(c.gpUniformMatrix3fv, uintptr(location), uintptr(len(value)/9), 0, uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix4fv(location int32, value []float32) {
purego.SyscallN(c.gpUniformMatrix4fv, uintptr(location), uintptr(len(value)/16), 0, uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UseProgram(program uint32) {
purego.SyscallN(c.gpUseProgram, uintptr(program))
}
func (c *defaultContext) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset int) {
purego.SyscallN(c.gpVertexAttribPointer, uintptr(index), uintptr(size), uintptr(xtype), uintptr(boolToInt(normalized)), uintptr(stride), uintptr(offset))
}
func (c *defaultContext) Viewport(x int32, y int32, width int32, height int32) {
purego.SyscallN(c.gpViewport, uintptr(x), uintptr(y), uintptr(width), uintptr(height))
}
func (c *defaultContext) LoadFunctions() error {
g := procAddressGetter{ctx: c}
c.gpActiveTexture = g.get("glActiveTexture")
c.gpAttachShader = g.get("glAttachShader")
c.gpBindAttribLocation = g.get("glBindAttribLocation")
c.gpBindBuffer = g.get("glBindBuffer")
c.gpBindFramebuffer = g.get("glBindFramebuffer")
c.gpBindRenderbuffer = g.get("glBindRenderbuffer")
c.gpBindTexture = g.get("glBindTexture")
c.gpBindVertexArray = g.get("glBindVertexArray")
c.gpBlendEquationSeparate = g.get("glBlendEquationSeparate")
c.gpBlendFuncSeparate = g.get("glBlendFuncSeparate")
c.gpBufferData = g.get("glBufferData")
c.gpBufferSubData = g.get("glBufferSubData")
c.gpCheckFramebufferStatus = g.get("glCheckFramebufferStatus")
c.gpClear = g.get("glClear")
c.gpColorMask = g.get("glColorMask")
c.gpCompileShader = g.get("glCompileShader")
c.gpCreateProgram = g.get("glCreateProgram")
c.gpCreateShader = g.get("glCreateShader")
c.gpDeleteBuffers = g.get("glDeleteBuffers")
c.gpDeleteFramebuffers = g.get("glDeleteFramebuffers")
c.gpDeleteProgram = g.get("glDeleteProgram")
c.gpDeleteRenderbuffers = g.get("glDeleteRenderbuffers")
c.gpDeleteShader = g.get("glDeleteShader")
c.gpDeleteTextures = g.get("glDeleteTextures")
c.gpDeleteVertexArrays = g.get("glDeleteVertexArrays")
c.gpDisable = g.get("glDisable")
c.gpDisableVertexAttribArray = g.get("glDisableVertexAttribArray")
c.gpDrawElements = g.get("glDrawElements")
c.gpEnable = g.get("glEnable")
c.gpEnableVertexAttribArray = g.get("glEnableVertexAttribArray")
c.gpFlush = g.get("glFlush")
c.gpFramebufferRenderbuffer = g.get("glFramebufferRenderbuffer")
c.gpFramebufferTexture2D = g.get("glFramebufferTexture2D")
c.gpGenBuffers = g.get("glGenBuffers")
c.gpGenFramebuffers = g.get("glGenFramebuffers")
c.gpGenRenderbuffers = g.get("glGenRenderbuffers")
c.gpGenTextures = g.get("glGenTextures")
c.gpGenVertexArrays = g.get("glGenVertexArrays")
c.gpGetError = g.get("glGetError")
c.gpGetIntegerv = g.get("glGetIntegerv")
c.gpGetProgramInfoLog = g.get("glGetProgramInfoLog")
c.gpGetProgramiv = g.get("glGetProgramiv")
c.gpGetShaderInfoLog = g.get("glGetShaderInfoLog")
c.gpGetShaderiv = g.get("glGetShaderiv")
c.gpGetUniformLocation = g.get("glGetUniformLocation")
c.gpIsFramebuffer = g.get("glIsFramebuffer")
c.gpIsProgram = g.get("glIsProgram")
c.gpIsRenderbuffer = g.get("glIsRenderbuffer")
c.gpLinkProgram = g.get("glLinkProgram")
c.gpPixelStorei = g.get("glPixelStorei")
c.gpReadPixels = g.get("glReadPixels")
c.gpRenderbufferStorage = g.get("glRenderbufferStorage")
c.gpScissor = g.get("glScissor")
c.gpShaderSource = g.get("glShaderSource")
c.gpStencilFunc = g.get("glStencilFunc")
c.gpStencilOpSeparate = g.get("glStencilOpSeparate")
c.gpTexImage2D = g.get("glTexImage2D")
c.gpTexParameteri = g.get("glTexParameteri")
c.gpTexSubImage2D = g.get("glTexSubImage2D")
c.gpUniform1fv = g.get("glUniform1fv")
c.gpUniform1i = g.get("glUniform1i")
c.gpUniform1iv = g.get("glUniform1iv")
c.gpUniform2fv = g.get("glUniform2fv")
c.gpUniform2iv = g.get("glUniform2iv")
c.gpUniform3fv = g.get("glUniform3fv")
c.gpUniform3iv = g.get("glUniform3iv")
c.gpUniform4fv = g.get("glUniform4fv")
c.gpUniform4iv = g.get("glUniform4iv")
c.gpUniformMatrix2fv = g.get("glUniformMatrix2fv")
c.gpUniformMatrix3fv = g.get("glUniformMatrix3fv")
c.gpUniformMatrix4fv = g.get("glUniformMatrix4fv")
c.gpUseProgram = g.get("glUseProgram")
c.gpVertexAttribPointer = g.get("glVertexAttribPointer")
c.gpViewport = g.get("glViewport")
return g.error()
}
// cStr takes a Go string (with or without null-termination)
// and returns the C counterpart.
//
// The returned free function must be called once you are done using the string
// in order to free the memory.
func cStr(str string) (cstr *byte, free func()) {
bs := []byte(str)
if len(bs) == 0 || bs[len(bs)-1] != 0 {
bs = append(bs, 0)
}
return &bs[0], func() {
runtime.KeepAlive(bs)
bs = nil
}
}
@@ -0,0 +1,104 @@
// Copyright 2020 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package gl
//go:generate go run gen.go
//go:generate gofmt -s -w .
// Context is a context for OpenGL (ES) functions.
//
// Context is basically the same as gomobile's gl.Context.
// See https://pkg.go.dev/github.com/ebitengine/gomobile/gl#Context
type Context interface {
LoadFunctions() error
IsES() bool
ActiveTexture(texture uint32)
AttachShader(program uint32, shader uint32)
BindAttribLocation(program uint32, index uint32, name string)
BindBuffer(target uint32, buffer uint32)
BindFramebuffer(target uint32, framebuffer uint32)
BindRenderbuffer(target uint32, renderbuffer uint32)
BindTexture(target uint32, texture uint32)
BindVertexArray(array uint32)
BlendEquationSeparate(modeRGB uint32, modeAlpha uint32)
BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32)
BufferInit(target uint32, size int, usage uint32)
BufferSubData(target uint32, offset int, data []byte)
CheckFramebufferStatus(target uint32) uint32
Clear(mask uint32)
ColorMask(red, green, blue, alpha bool)
CompileShader(shader uint32)
CreateBuffer() uint32
CreateFramebuffer() uint32
CreateProgram() uint32
CreateRenderbuffer() uint32
CreateShader(xtype uint32) uint32
CreateTexture() uint32
CreateVertexArray() uint32
DeleteBuffer(buffer uint32)
DeleteFramebuffer(framebuffer uint32)
DeleteProgram(program uint32)
DeleteRenderbuffer(renderbuffer uint32)
DeleteShader(shader uint32)
DeleteTexture(texture uint32)
DeleteVertexArray(array uint32)
Disable(cap uint32)
DisableVertexAttribArray(index uint32)
DrawElements(mode uint32, count int32, xtype uint32, offset int)
Enable(cap uint32)
EnableVertexAttribArray(index uint32)
Flush()
FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32)
FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32)
GetError() uint32
GetInteger(pname uint32) int
GetProgramInfoLog(program uint32) string
GetProgrami(program uint32, pname uint32) int
GetShaderInfoLog(shader uint32) string
GetShaderi(shader uint32, pname uint32) int
GetUniformLocation(program uint32, name string) int32
IsFramebuffer(framebuffer uint32) bool
IsProgram(program uint32) bool
IsRenderbuffer(renderbuffer uint32) bool
LinkProgram(program uint32)
PixelStorei(pname uint32, param int32)
ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32)
RenderbufferStorage(target uint32, internalFormat uint32, width int32, height int32)
Scissor(x, y, width, height int32)
ShaderSource(shader uint32, xstring string)
StencilFunc(func_ uint32, ref int32, mask uint32)
StencilOpSeparate(face, sfail, dpfail, dppass uint32)
TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
TexParameteri(target uint32, pname uint32, param int32)
TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
Uniform1fv(location int32, value []float32)
Uniform1i(location int32, v0 int32)
Uniform1iv(location int32, value []int32)
Uniform2fv(location int32, value []float32)
Uniform2iv(location int32, value []int32)
Uniform3fv(location int32, value []float32)
Uniform3iv(location int32, value []int32)
Uniform4fv(location int32, value []float32)
Uniform4iv(location int32, value []int32)
UniformMatrix2fv(location int32, value []float32)
UniformMatrix3fv(location int32, value []float32)
UniformMatrix4fv(location int32, value []float32)
UseProgram(program uint32)
VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset int)
Viewport(x int32, y int32, width int32, height int32)
}
@@ -0,0 +1,43 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !js && !playstation5
package gl
import (
"fmt"
)
type procAddressGetter struct {
ctx *defaultContext
err error
}
func (p *procAddressGetter) get(name string) uintptr {
proc, err := p.ctx.getProcAddress(name)
if err != nil {
p.err = fmt.Errorf("gl: %s is missing: %w", name, err)
return 0
}
if proc == 0 {
p.err = fmt.Errorf("gl: %s is missing", name)
return 0
}
return proc
}
func (p *procAddressGetter) error() error {
return p.err
}
@@ -0,0 +1,51 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gl
import (
"fmt"
"github.com/ebitengine/purego"
)
var (
opengl uintptr
)
func (c *defaultContext) init() error {
lib, errGLES := purego.Dlopen("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", purego.RTLD_LAZY|purego.RTLD_GLOBAL)
if errGLES == nil {
c.isES = true
opengl = lib
return nil
}
lib, errGL := purego.Dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", purego.RTLD_LAZY|purego.RTLD_GLOBAL)
if errGL == nil {
opengl = lib
return nil
}
// TODO: Use multiple %w-s as of Go 1.20
return fmt.Errorf("gl: failed to load: OpenGL.framework: %v, OpenGLES.framework: %v", errGL, errGLES)
}
func (c *defaultContext) getProcAddress(name string) (uintptr, error) {
proc, err := purego.Dlsym(opengl, name)
if err != nil {
return 0, err
}
return proc, nil
}
@@ -0,0 +1,114 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build (freebsd || linux || netbsd || openbsd) && !nintendosdk && !playstation5
package gl
// #cgo LDFLAGS: -ldl
//
// #include <dlfcn.h>
// #include <stdlib.h>
//
// static void* getProcAddressGL(void* libGL, const char* name) {
// static void*(*glXGetProcAddress)(const char*);
// if (!glXGetProcAddress) {
// glXGetProcAddress = dlsym(libGL, "glXGetProcAddress");
// if (!glXGetProcAddress) {
// glXGetProcAddress = dlsym(libGL, "glXGetProcAddressARB");
// }
// }
// return glXGetProcAddress(name);
// }
//
// static void* getProcAddressGLES(void* libGLES, const char* name) {
// return dlsym(libGLES, name);
// }
import "C"
import (
"fmt"
"os"
"runtime"
"strings"
"unsafe"
)
var (
libGL unsafe.Pointer
libGLES unsafe.Pointer
)
func (c *defaultContext) init() error {
var preferES bool
if runtime.GOOS == "android" {
preferES = true
}
if !preferES {
for _, t := range strings.Split(os.Getenv("EBITENGINE_OPENGL"), ",") {
switch strings.TrimSpace(t) {
case "es":
preferES = true
break
}
}
}
// Try OpenGL first. OpenGL is preferable as this doesn't cause context losses.
if !preferES {
// Usually libGL.so or libGL.so.1 is used. libGL.so.2 might exist only on NetBSD.
for _, name := range []string{"libGL.so", "libGL.so.2", "libGL.so.1", "libGL.so.0"} {
cname := C.CString(name)
lib := C.dlopen(cname, C.RTLD_LAZY|C.RTLD_GLOBAL)
C.free(unsafe.Pointer(cname))
if lib != nil {
libGL = lib
return nil
}
}
}
// Try OpenGL ES.
for _, name := range []string{"libGLESv2.so", "libGLESv2.so.2", "libGLESv2.so.1", "libGLESv2.so.0"} {
cname := C.CString(name)
lib := C.dlopen(cname, C.RTLD_LAZY|C.RTLD_GLOBAL)
C.free(unsafe.Pointer(cname))
if lib != nil {
libGLES = lib
c.isES = true
return nil
}
}
return fmt.Errorf("gl: failed to load libGL.so and libGLESv2.so")
}
func (c *defaultContext) getProcAddress(name string) (uintptr, error) {
if c.isES {
return getProcAddressGLES(name), nil
}
return getProcAddressGL(name), nil
}
func getProcAddressGL(name string) uintptr {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return uintptr(C.getProcAddressGL(libGL, cname))
}
func getProcAddressGLES(name string) uintptr {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return uintptr(C.getProcAddressGLES(libGLES, cname))
}
@@ -0,0 +1,39 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build nintendosdk
package gl
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
//
// #include <stdlib.h>
// #include <EGL/egl.h>
//
// static void* getProcAddress(const char* name) {
// return eglGetProcAddress(name);
// }
import "C"
import "unsafe"
func (c *defaultContext) init() error {
return nil
}
func (c *defaultContext) getProcAddress(name string) (uintptr, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return uintptr(C.getProcAddress(cname)), nil
}
@@ -0,0 +1,52 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gl
import (
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
var (
opengl32 = windows.NewLazySystemDLL("opengl32")
procWglGetProcAddress = opengl32.NewProc("wglGetProcAddress")
)
func (c *defaultContext) init() error {
return nil
}
func (c *defaultContext) getProcAddress(namea string) (uintptr, error) {
cname, err := windows.BytePtrFromString(namea)
if err != nil {
return 0, err
}
r, _, err := procWglGetProcAddress.Call(uintptr(unsafe.Pointer(cname)))
if r != 0 {
return r, nil
}
if err != nil && err != windows.ERROR_SUCCESS && err != windows.ERROR_PROC_NOT_FOUND {
return 0, fmt.Errorf("gl: wglGetProcAddress failed for %s: %w", namea, err)
}
p := opengl32.NewProc(namea)
if err := p.Find(); err != nil {
return 0, err
}
return p.Addr(), nil
}
@@ -0,0 +1,341 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
import (
"fmt"
"unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
)
type activatedTexture struct {
textureNative textureNative
index int
}
type Graphics struct {
state openGLState
context context
vsync bool
nextImageID graphicsdriver.ImageID
images map[graphicsdriver.ImageID]*Image
nextShaderID graphicsdriver.ShaderID
shaders map[graphicsdriver.ShaderID]*Shader
// drawCalled is true just after Draw is called. This holds true until WritePixels is called.
drawCalled bool
uniformVariableNameCache map[int]string
textureVariableNameCache map[int]string
uniformVars []uniformVariable
// activatedTextures is a set of activated textures.
// textureNative cannot be a map key unfortunately.
activatedTextures []activatedTexture
graphicsPlatform
}
func newGraphics(ctx gl.Context) *Graphics {
g := &Graphics{
vsync: true,
}
if isDebug {
g.context.ctx = &gl.DebugContext{Context: ctx}
} else {
g.context.ctx = ctx
}
return g
}
func (g *Graphics) Begin() error {
// Do nothing.
return nil
}
func (g *Graphics) End(present bool) error {
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
// TODO: examples/sprites worked without this. Is this really needed?
g.context.ctx.Flush()
// The last uniforms must be reset before swapping the buffer (#2517).
if present {
g.state.resetLastUniforms()
if err := g.swapBuffers(); err != nil {
return err
}
}
return nil
}
func (g *Graphics) SetTransparent(transparent bool) {
// Do nothing.
}
func (g *Graphics) checkSize(width, height int) {
if width < 1 {
panic(fmt.Sprintf("opengl: width (%d) must be equal or more than %d", width, 1))
}
if height < 1 {
panic(fmt.Sprintf("opengl: height (%d) must be equal or more than %d", height, 1))
}
m := g.context.getMaxTextureSize()
if width > m {
panic(fmt.Sprintf("opengl: width (%d) must be less than or equal to %d", width, m))
}
if height > m {
panic(fmt.Sprintf("opengl: height (%d) must be less than or equal to %d", height, m))
}
}
func (g *Graphics) genNextImageID() graphicsdriver.ImageID {
g.nextImageID++
return g.nextImageID
}
func (g *Graphics) genNextShaderID() graphicsdriver.ShaderID {
g.nextShaderID++
return g.nextShaderID
}
func (g *Graphics) NewImage(width, height int) (graphicsdriver.Image, error) {
i := &Image{
id: g.genNextImageID(),
graphics: g,
width: width,
height: height,
}
w := graphics.InternalImageSize(width)
h := graphics.InternalImageSize(height)
g.checkSize(w, h)
t, err := g.context.newTexture(w, h)
if err != nil {
return nil, err
}
i.texture = t
g.addImage(i)
return i, nil
}
func (g *Graphics) NewScreenFramebufferImage(width, height int) (graphicsdriver.Image, error) {
g.checkSize(width, height)
i := &Image{
id: g.genNextImageID(),
graphics: g,
width: width,
height: height,
screen: true,
}
g.addImage(i)
return i, nil
}
func (g *Graphics) addImage(img *Image) {
if g.images == nil {
g.images = map[graphicsdriver.ImageID]*Image{}
}
if _, ok := g.images[img.id]; ok {
panic(fmt.Sprintf("opengl: image ID %d was already registered", img.id))
}
g.images[img.id] = img
}
func (g *Graphics) removeImage(img *Image) {
delete(g.images, img.id)
}
func (g *Graphics) Initialize() error {
if err := g.makeContextCurrent(); err != nil {
return err
}
if err := g.state.reset(&g.context); err != nil {
return err
}
return nil
}
// Reset resets or initializes the current OpenGL state.
func (g *Graphics) Reset() error {
return g.state.reset(&g.context)
}
func (g *Graphics) SetVertices(vertices []float32, indices []uint32) error {
g.state.setVertices(&g.context, vertices, indices)
return nil
}
func (g *Graphics) uniformVariableName(idx int) string {
if v, ok := g.uniformVariableNameCache[idx]; ok {
return v
}
if g.uniformVariableNameCache == nil {
g.uniformVariableNameCache = map[int]string{}
}
name := fmt.Sprintf("U%d", idx)
g.uniformVariableNameCache[idx] = name
return name
}
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, shaderID graphicsdriver.ShaderID, dstRegions []graphicsdriver.DstRegion, indexOffset int, blend graphicsdriver.Blend, uniforms []uint32, fillRule graphicsdriver.FillRule) error {
if shaderID == graphicsdriver.InvalidShaderID {
return fmt.Errorf("opengl: shader ID is invalid")
}
destination := g.images[dstID]
g.drawCalled = true
if err := destination.setViewport(); err != nil {
return err
}
g.context.blend(blend)
shader := g.shaders[shaderID]
program := shader.p
ulen := len(shader.ir.Uniforms)
if cap(g.uniformVars) < ulen {
g.uniformVars = make([]uniformVariable, ulen)
} else {
g.uniformVars = g.uniformVars[:ulen]
}
var idx int
for i, typ := range shader.ir.Uniforms {
n := typ.Uint32Count()
g.uniformVars[i].name = g.uniformVariableName(i)
g.uniformVars[i].value = uniforms[idx : idx+n]
g.uniformVars[i].typ = typ
idx += n
}
// In OpenGL, the NDC's Y direction is upward, so flip the Y direction for the final framebuffer.
if destination.screen {
const idx = graphics.ProjectionMatrixUniformVariableIndex
// Invert the sign bits as float32 values.
g.uniformVars[idx].value[1] ^= 1 << 31
g.uniformVars[idx].value[5] ^= 1 << 31
g.uniformVars[idx].value[9] ^= 1 << 31
g.uniformVars[idx].value[13] ^= 1 << 31
}
var imgs [graphics.ShaderImageCount]textureVariable
for i, srcID := range srcIDs {
if srcID == graphicsdriver.InvalidImageID {
continue
}
imgs[i].valid = true
imgs[i].native = g.images[srcID].texture
}
if err := g.useProgram(program, g.uniformVars, imgs); err != nil {
return err
}
for i := range g.uniformVars {
g.uniformVars[i] = uniformVariable{}
}
g.uniformVars = g.uniformVars[:0]
if fillRule != graphicsdriver.FillAll {
if err := destination.ensureStencilBuffer(); err != nil {
return err
}
g.context.ctx.Enable(gl.STENCIL_TEST)
}
for _, dstRegion := range dstRegions {
g.context.ctx.Scissor(
int32(dstRegion.Region.Min.X),
int32(dstRegion.Region.Min.Y),
int32(dstRegion.Region.Dx()),
int32(dstRegion.Region.Dy()),
)
switch fillRule {
case graphicsdriver.NonZero:
g.context.ctx.Clear(gl.STENCIL_BUFFER_BIT)
g.context.ctx.StencilFunc(gl.ALWAYS, 0x00, 0xff)
g.context.ctx.StencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.INCR_WRAP)
g.context.ctx.StencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.DECR_WRAP)
g.context.ctx.ColorMask(false, false, false, false)
g.context.ctx.DrawElements(gl.TRIANGLES, int32(dstRegion.IndexCount), gl.UNSIGNED_INT, indexOffset*int(unsafe.Sizeof(uint32(0))))
case graphicsdriver.EvenOdd:
g.context.ctx.Clear(gl.STENCIL_BUFFER_BIT)
g.context.ctx.StencilFunc(gl.ALWAYS, 0x00, 0xff)
g.context.ctx.StencilOpSeparate(gl.FRONT_AND_BACK, gl.KEEP, gl.KEEP, gl.INVERT)
g.context.ctx.ColorMask(false, false, false, false)
g.context.ctx.DrawElements(gl.TRIANGLES, int32(dstRegion.IndexCount), gl.UNSIGNED_INT, indexOffset*int(unsafe.Sizeof(uint32(0))))
}
if fillRule != graphicsdriver.FillAll {
g.context.ctx.StencilFunc(gl.NOTEQUAL, 0x00, 0xff)
g.context.ctx.StencilOpSeparate(gl.FRONT_AND_BACK, gl.KEEP, gl.KEEP, gl.KEEP)
g.context.ctx.ColorMask(true, true, true, true)
}
g.context.ctx.DrawElements(gl.TRIANGLES, int32(dstRegion.IndexCount), gl.UNSIGNED_INT, indexOffset*int(unsafe.Sizeof(uint32(0))))
indexOffset += dstRegion.IndexCount
}
if fillRule != graphicsdriver.FillAll {
g.context.ctx.Disable(gl.STENCIL_TEST)
}
return nil
}
func (g *Graphics) SetVsyncEnabled(enabled bool) {
g.vsync = enabled
}
func (g *Graphics) NeedsClearingScreen() bool {
return true
}
func (g *Graphics) MaxImageSize() int {
return g.context.getMaxTextureSize()
}
func (g *Graphics) NewShader(program *shaderir.Program) (graphicsdriver.Shader, error) {
s, err := newShader(g.genNextShaderID(), g, program)
if err != nil {
return nil, err
}
g.addShader(s)
return s, nil
}
func (g *Graphics) addShader(shader *Shader) {
if g.shaders == nil {
g.shaders = map[graphicsdriver.ShaderID]*Shader{}
}
if _, ok := g.shaders[shader.id]; ok {
panic(fmt.Sprintf("opengl: shader ID %d was already registered", shader.id))
}
g.shaders[shader.id] = shader
}
func (g *Graphics) removeShader(shader *Shader) {
delete(g.shaders, shader.id)
}
@@ -0,0 +1,19 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build ebitenginegldebug
package opengl
const isDebug = true
@@ -0,0 +1,119 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !android && !ios && !js && !nintendosdk && !playstation5
package opengl
import (
"fmt"
"runtime"
"github.com/hajimehoshi/ebiten/v2/internal/glfw"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
)
type graphicsPlatform struct {
window *glfw.Window
}
// NewGraphics creates an implementation of graphicsdriver.Graphics for OpenGL.
// The returned graphics value is nil iff the error is not nil.
func NewGraphics() (graphicsdriver.Graphics, error) {
if microsoftgdk.IsXbox() {
return nil, fmt.Errorf("opengl: OpenGL is not supported on Xbox")
}
ctx, err := gl.NewDefaultContext()
if err != nil {
return nil, err
}
if err := setGLFWClientAPI(ctx.IsES()); err != nil {
return nil, err
}
return newGraphics(ctx), nil
}
func setGLFWClientAPI(isES bool) error {
if isES {
if err := glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLESAPI); err != nil {
return err
}
if err := glfw.WindowHint(glfw.ContextVersionMajor, 3); err != nil {
return err
}
if err := glfw.WindowHint(glfw.ContextVersionMinor, 0); err != nil {
return err
}
if err := glfw.WindowHint(glfw.ContextCreationAPI, glfw.EGLContextAPI); err != nil {
return err
}
return nil
}
if err := glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLAPI); err != nil {
return err
}
if err := glfw.WindowHint(glfw.ContextVersionMajor, 3); err != nil {
return err
}
if err := glfw.WindowHint(glfw.ContextVersionMinor, 2); err != nil {
return err
}
// macOS requires forward-compatible and a core profile.
if runtime.GOOS == "darwin" {
if err := glfw.WindowHint(glfw.OpenGLForwardCompat, glfw.True); err != nil {
return err
}
if err := glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile); err != nil {
return err
}
}
return nil
}
func (g *Graphics) SetGLFWWindow(window *glfw.Window) {
g.window = window
}
func (g *Graphics) makeContextCurrent() error {
return g.window.MakeContextCurrent()
}
func (g *Graphics) swapBuffers() error {
// Call SwapIntervals even though vsync is not changed.
// When toggling to fullscreen, vsync state might be reset unexpectedly (#1787).
// SwapInterval is affected by the current monitor of the window.
// This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
if g.vsync {
if err := glfw.SwapInterval(1); err != nil {
return err
}
} else {
if err := glfw.SwapInterval(0); err != nil {
return err
}
}
if err := g.window.SwapBuffers(); err != nil {
return err
}
return nil
}
@@ -0,0 +1,58 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package opengl
import (
"fmt"
"syscall/js"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
)
type graphicsPlatform struct {
}
// NewGraphics creates an implementation of graphicsdriver.Graphics for OpenGL.
// The returned graphics value is nil iff the error is not nil.
func NewGraphics(canvas js.Value) (graphicsdriver.Graphics, error) {
var glContext js.Value
attr := js.Global().Get("Object").New()
attr.Set("alpha", true)
attr.Set("premultipliedAlpha", true)
attr.Set("stencil", true)
glContext = canvas.Call("getContext", "webgl2", attr)
if !glContext.Truthy() {
return nil, fmt.Errorf("opengl: getContext for webgl2 failed")
}
ctx, err := gl.NewDefaultContext(glContext)
if err != nil {
return nil, err
}
return newGraphics(ctx), nil
}
func (g *Graphics) makeContextCurrent() error {
return nil
}
func (g *Graphics) swapBuffers() error {
return nil
}
@@ -0,0 +1,43 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build android || ios
package opengl
import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
)
type graphicsPlatform struct {
}
// NewGraphics creates an implementation of graphicsdriver.Graphics for OpenGL.
// The returned graphics value is nil iff the error is not nil.
func NewGraphics() (graphicsdriver.Graphics, error) {
ctx, err := gl.NewDefaultContext()
if err != nil {
return nil, err
}
return newGraphics(ctx), nil
}
func (g *Graphics) makeContextCurrent() error {
return nil
}
func (g *Graphics) swapBuffers() error {
return nil
}
@@ -0,0 +1,49 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build nintendosdk
package opengl
import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
)
type graphicsPlatform struct {
egl *egl
}
func NewGraphics(nativeWindowType uintptr) (graphicsdriver.Graphics, error) {
ctx, err := gl.NewDefaultContext()
if err != nil {
return nil, err
}
g := newGraphics(ctx)
e, err := newEGL(nativeWindowType)
if err != nil {
return nil, err
}
g.egl = e
return g, nil
}
func (g *Graphics) makeContextCurrent() error {
return g.egl.makeContextCurrent()
}
func (g *Graphics) swapBuffers() error {
g.egl.swapBuffers()
return nil
}
@@ -0,0 +1,19 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !ebitenginegldebug
package opengl
const isDebug = false
@@ -0,0 +1,158 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
import (
"errors"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
)
type Image struct {
id graphicsdriver.ImageID
graphics *Graphics
texture textureNative
stencil renderbufferNative
framebuffer *framebuffer
width int
height int
screen bool
}
// framebuffer is a wrapper of OpenGL's framebuffer.
type framebuffer struct {
graphics *Graphics
native framebufferNative
width int
height int
}
func (i *Image) ID() graphicsdriver.ImageID {
return i.id
}
func (i *Image) Dispose() {
if i.framebuffer != nil {
i.graphics.context.deleteFramebuffer(i.framebuffer.native)
}
if i.texture != 0 {
i.graphics.context.deleteTexture(i.texture)
}
if i.stencil != 0 {
i.graphics.context.deleteRenderbuffer(i.stencil)
}
i.graphics.removeImage(i)
}
func (i *Image) setViewport() error {
if err := i.ensureFramebuffer(); err != nil {
return err
}
i.graphics.context.setViewport(i.framebuffer)
return nil
}
func (i *Image) ReadPixels(args []graphicsdriver.PixelsArgs) error {
if err := i.ensureFramebuffer(); err != nil {
return err
}
for _, arg := range args {
if err := i.graphics.context.framebufferPixels(arg.Pixels, i.framebuffer, arg.Region); err != nil {
return err
}
}
return nil
}
func (i *Image) framebufferSize() (int, int) {
if i.screen {
// The (default) framebuffer size can't be converted to a power of 2.
// On browsers, i.width and i.height are used as viewport size and
// Edge can't treat a bigger viewport than the drawing area (#71).
return i.width, i.height
}
return graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
}
func (i *Image) ensureFramebuffer() error {
if i.framebuffer != nil {
return nil
}
w, h := i.framebufferSize()
if i.screen {
i.framebuffer = i.graphics.context.newScreenFramebuffer(w, h)
return nil
}
f, err := i.graphics.context.newFramebuffer(i.texture, w, h)
if err != nil {
return err
}
i.framebuffer = f
return nil
}
func (i *Image) ensureStencilBuffer() error {
if i.stencil != 0 {
return nil
}
if err := i.ensureFramebuffer(); err != nil {
return err
}
r, err := i.graphics.context.newRenderbuffer(i.framebufferSize())
if err != nil {
return err
}
i.stencil = r
if err := i.graphics.context.bindStencilBuffer(i.framebuffer.native, i.stencil); err != nil {
return err
}
return nil
}
func (i *Image) WritePixels(args []graphicsdriver.PixelsArgs) error {
if i.screen {
return errors.New("opengl: WritePixels cannot be called on the screen")
}
if len(args) == 0 {
return nil
}
// glFlush is necessary on Android.
// glTexSubImage2D didn't work without this hack at least on Nexus 5x and NuAns NEO [Reloaded] (#211).
if i.graphics.drawCalled {
i.graphics.context.ctx.Flush()
}
i.graphics.drawCalled = false
i.graphics.context.bindTexture(i.texture)
for _, a := range args {
x := int32(a.Region.Min.X)
y := int32(a.Region.Min.Y)
width := int32(a.Region.Dx())
height := int32(a.Region.Dy())
i.graphics.context.ctx.TexSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, a.Pixels)
}
return nil
}
@@ -0,0 +1,43 @@
// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
type locationCache struct {
uniformLocationCache map[program]map[string]uniformLocation
}
func newLocationCache() *locationCache {
return &locationCache{
uniformLocationCache: map[program]map[string]uniformLocation{},
}
}
func (c *locationCache) GetUniformLocation(context *context, p program, location string) uniformLocation {
if _, ok := c.uniformLocationCache[p]; !ok {
c.uniformLocationCache[p] = map[string]uniformLocation{}
}
l, ok := c.uniformLocationCache[p][location]
if !ok {
l = uniformLocation(context.ctx.GetUniformLocation(uint32(p), location))
c.uniformLocationCache[p][location] = l
}
return l
}
func (c *locationCache) deleteProgram(p program) {
delete(c.uniformLocationCache, p)
}
@@ -0,0 +1,344 @@
// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
import (
"fmt"
"math"
"runtime"
"unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
)
const floatSizeInBytes = 4
// arrayBufferLayoutPart is a part of an array buffer layout.
type arrayBufferLayoutPart struct {
// TODO: This struct should belong to a program and know it.
name string
num int
}
// arrayBufferLayout is an array buffer layout.
//
// An array buffer in OpenGL is a buffer representing vertices and
// is passed to a vertex shader.
type arrayBufferLayout struct {
parts []arrayBufferLayoutPart
total int
}
func (a *arrayBufferLayout) names() []string {
ns := make([]string, len(a.parts))
for i, p := range a.parts {
ns[i] = p.name
}
return ns
}
// totalBytes returns the size in bytes for one element of the array buffer.
func (a *arrayBufferLayout) totalBytes() int {
if a.total != 0 {
return a.total
}
t := 0
for _, p := range a.parts {
t += floatSizeInBytes * p.num
}
a.total = t
return a.total
}
// enable starts using the array buffer.
func (a *arrayBufferLayout) enable(context *context) {
for i := range a.parts {
context.ctx.EnableVertexAttribArray(uint32(i))
}
total := a.totalBytes()
offset := 0
for i, p := range a.parts {
context.ctx.VertexAttribPointer(uint32(i), int32(p.num), gl.FLOAT, false, int32(total), offset)
offset += floatSizeInBytes * p.num
}
}
// disable stops using the array buffer.
func (a *arrayBufferLayout) disable(context *context) {
// TODO: Disabling should be done in reversed order?
for i := range a.parts {
context.ctx.DisableVertexAttribArray(uint32(i))
}
}
// theArrayBufferLayout is the array buffer layout for Ebitengine.
var theArrayBufferLayout = arrayBufferLayout{
// Note that GL_MAX_VERTEX_ATTRIBS is at least 16.
parts: []arrayBufferLayoutPart{
{
name: "A0",
num: 2,
},
{
name: "A1",
num: 2,
},
{
name: "A2",
num: 4,
},
},
}
func init() {
vertexFloatCount := theArrayBufferLayout.totalBytes() / floatSizeInBytes
if graphics.VertexFloatCount != vertexFloatCount {
panic(fmt.Sprintf("vertex float num must be %d but %d", graphics.VertexFloatCount, vertexFloatCount))
}
}
type openGLState struct {
vertexArray uint32
// arrayBuffer is OpenGL's array buffer (vertices data).
arrayBuffer buffer
arrayBufferSizeInBytes int
// elementArrayBuffer is OpenGL's element array buffer (indices data).
elementArrayBuffer buffer
elementArrayBufferSizeInBytes int
lastProgram program
lastUniforms map[string][]uint32
lastActiveTexture int
}
// reset resets or initializes the OpenGL state.
func (s *openGLState) reset(context *context) error {
if err := context.reset(); err != nil {
return err
}
s.lastProgram = 0
context.ctx.UseProgram(0)
for key := range s.lastUniforms {
delete(s.lastUniforms, key)
}
// On browsers (at least Chrome), buffers are already detached from the context
// and must not be deleted by DeleteBuffer.
if runtime.GOOS != "js" {
if s.arrayBuffer != 0 {
context.ctx.DeleteBuffer(uint32(s.arrayBuffer))
}
if s.elementArrayBuffer != 0 {
context.ctx.DeleteBuffer(uint32(s.elementArrayBuffer))
}
if s.vertexArray != 0 {
context.ctx.DeleteVertexArray(s.vertexArray)
}
}
s.arrayBuffer = 0
s.arrayBufferSizeInBytes = 0
s.elementArrayBuffer = 0
s.elementArrayBufferSizeInBytes = 0
s.vertexArray = 0
return nil
}
func pow2(x int) int {
if x > (math.MaxInt+1)/2 {
return math.MaxInt
}
p2 := 1
for p2 < x {
p2 *= 2
}
return p2
}
func (s *openGLState) setVertices(context *context, vertices []float32, indices []uint32) {
if s.vertexArray == 0 {
s.vertexArray = context.ctx.CreateVertexArray()
}
context.ctx.BindVertexArray(s.vertexArray)
if size := len(vertices) * int(unsafe.Sizeof(vertices[0])); s.arrayBufferSizeInBytes < size {
if s.arrayBuffer != 0 {
context.ctx.DeleteBuffer(uint32(s.arrayBuffer))
}
newSize := pow2(size)
// newArrayBuffer calls BindBuffer.
s.arrayBuffer = context.newArrayBuffer(newSize)
s.arrayBufferSizeInBytes = newSize
// Reenable the array buffer layout explicitly after resetting the array buffer.
theArrayBufferLayout.enable(context)
}
if size := len(indices) * int(unsafe.Sizeof(indices[0])); s.elementArrayBufferSizeInBytes < size {
if s.elementArrayBuffer != 0 {
context.ctx.DeleteBuffer(uint32(s.elementArrayBuffer))
}
newSize := pow2(size)
// newElementArrayBuffer calls BindBuffer.
s.elementArrayBuffer = context.newElementArrayBuffer(newSize)
s.elementArrayBufferSizeInBytes = newSize
}
// Note that the vertices and the indices passed to BufferSubData is not under GC management in the gl package.
vs := unsafe.Slice((*byte)(unsafe.Pointer(&vertices[0])), len(vertices)*int(unsafe.Sizeof(vertices[0])))
context.ctx.BufferSubData(gl.ARRAY_BUFFER, 0, vs)
is := unsafe.Slice((*byte)(unsafe.Pointer(&indices[0])), len(indices)*int(unsafe.Sizeof(indices[0])))
context.ctx.BufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, is)
}
func (s *openGLState) resetLastUniforms() {
for k := range s.lastUniforms {
delete(s.lastUniforms, k)
}
}
// areSameUint32Array returns a boolean indicating if a and b are deeply equal.
func areSameUint32Array(a, b []uint32) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
type uniformVariable struct {
name string
value []uint32
typ shaderir.Type
}
type textureVariable struct {
valid bool
native textureNative
}
func (g *Graphics) textureVariableName(idx int) string {
if v, ok := g.textureVariableNameCache[idx]; ok {
return v
}
if g.textureVariableNameCache == nil {
g.textureVariableNameCache = map[int]string{}
}
name := fmt.Sprintf("T%d", idx)
g.textureVariableNameCache[idx] = name
return name
}
// useProgram uses the program (programTexture).
func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures [graphics.ShaderImageCount]textureVariable) error {
if g.state.lastProgram != program {
g.context.ctx.UseProgram(uint32(program))
g.state.lastProgram = program
for k := range g.state.lastUniforms {
delete(g.state.lastUniforms, k)
}
g.state.lastActiveTexture = 0
g.context.ctx.ActiveTexture(gl.TEXTURE0)
g.context.lastTexture = 0 // Make sure next bindTexture call actually does something.
}
for _, u := range uniforms {
if u.value == nil {
continue
}
if got, expected := len(u.value), u.typ.Uint32Count(); got != expected {
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
// the value u would be allocated on heap.
typ := u.typ
return fmt.Errorf("opengl: length of a uniform variables %s (%s) doesn't match: expected %d but %d", u.name, typ.String(), expected, got)
}
cached, ok := g.state.lastUniforms[u.name]
if ok && areSameUint32Array(cached, u.value) {
continue
}
g.context.uniforms(program, u.name, u.value, u.typ)
if g.state.lastUniforms == nil {
g.state.lastUniforms = map[string][]uint32{}
}
g.state.lastUniforms[u.name] = u.value
}
var idx int
loop:
for i, t := range textures {
if !t.valid {
continue
}
// If the texture is already bound, set the texture variable to point to the texture.
// Rebinding the same texture seems problematic (#1193).
for _, at := range g.activatedTextures {
if t.native == at.textureNative {
g.context.uniformInt(program, g.textureVariableName(i), at.index)
continue loop
}
}
g.activatedTextures = append(g.activatedTextures, activatedTexture{
textureNative: t.native,
index: idx,
})
g.context.uniformInt(program, g.textureVariableName(i), idx)
if g.state.lastActiveTexture != idx {
g.context.ctx.ActiveTexture(uint32(gl.TEXTURE0 + idx))
g.state.lastActiveTexture = idx
g.context.lastTexture = 0 // Make sure next bindTexture call actually does something.
}
// Apparently, a texture must be bound every time. The cache is not used here.
g.context.bindTexture(t.native)
idx++
}
for i := range g.activatedTextures {
g.activatedTextures[i] = activatedTexture{}
}
g.activatedTextures = g.activatedTextures[:0]
return nil
}
func uint32sToFloat32s(s []uint32) []float32 {
return unsafe.Slice((*float32)(unsafe.Pointer(&s[0])), len(s))
}
func uint32sToInt32s(s []uint32) []int32 {
return unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
}
@@ -0,0 +1,79 @@
// Copyright 2020 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !playstation5
package opengl
import (
"fmt"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/glsl"
)
type Shader struct {
id graphicsdriver.ShaderID
graphics *Graphics
ir *shaderir.Program
p program
}
func newShader(id graphicsdriver.ShaderID, graphics *Graphics, program *shaderir.Program) (*Shader, error) {
s := &Shader{
id: id,
graphics: graphics,
ir: program,
}
if err := s.compile(); err != nil {
return nil, err
}
return s, nil
}
func (s *Shader) ID() graphicsdriver.ShaderID {
return s.id
}
func (s *Shader) Dispose() {
s.graphics.context.deleteProgram(s.p)
s.graphics.removeShader(s)
}
func (s *Shader) compile() error {
vssrc, fssrc := glsl.Compile(s.ir, s.graphics.context.glslVersion())
vs, err := s.graphics.context.newShader(gl.VERTEX_SHADER, vssrc)
if err != nil {
return fmt.Errorf("opengl: vertex shader compile error: %v, source:\n%s", err, vssrc)
}
defer s.graphics.context.ctx.DeleteShader(uint32(vs))
fs, err := s.graphics.context.newShader(gl.FRAGMENT_SHADER, fssrc)
if err != nil {
return fmt.Errorf("opengl: fragment shader compile error: %v, source:\n%s", err, fssrc)
}
defer s.graphics.context.ctx.DeleteShader(uint32(fs))
p, err := s.graphics.context.newProgram([]shader{vs, fs}, theArrayBufferLayout.names())
if err != nil {
return err
}
s.p = p
return nil
}