From 4f69ca4ea9450815d154f5f63001e80dde39e163 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 21 Apr 2023 22:52:49 +0900 Subject: [PATCH] internal/graphicsdriver/opengl: add a debug mode with a build tag `ebitenginegldebug` In the debug mode, GetError is inserted in each GL function call. Closes #2650 --- doc.go | 3 + internal/graphicsdriver/opengl/gl/debug.go | 627 ++++++++++++++++++ internal/graphicsdriver/opengl/gl/gen.go | 143 ++++ .../graphicsdriver/opengl/gl/interface.go | 3 + internal/graphicsdriver/opengl/graphics.go | 10 + .../graphicsdriver/opengl/graphics_debug.go | 19 + .../graphicsdriver/opengl/graphics_default.go | 4 +- internal/graphicsdriver/opengl/graphics_js.go | 3 +- .../graphicsdriver/opengl/graphics_mobile.go | 5 +- .../opengl/graphics_notdebug.go | 19 + 10 files changed, 827 insertions(+), 9 deletions(-) create mode 100644 internal/graphicsdriver/opengl/gl/debug.go create mode 100644 internal/graphicsdriver/opengl/gl/gen.go create mode 100644 internal/graphicsdriver/opengl/graphics_debug.go create mode 100644 internal/graphicsdriver/opengl/graphics_notdebug.go diff --git a/doc.go b/doc.go index 34967a09a..f3824557a 100644 --- a/doc.go +++ b/doc.go @@ -102,6 +102,9 @@ // `ebitenginedebug` outputs a log of graphics commands. This is useful to know what happens in Ebitengine. In general, the // number of graphics commands affects the performance of your game. // +// `ebitenginegldebug` enables a debug mode for OpenGL. This is valid only when the graphics library is OpenGL. +// This affects performance very much. +// // `ebitenginesinglethread` disables Ebitengine's thread safety to unlock maximum performance. If you use this you will have // to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag. // They must be called from the main thread or the same goroutine as the given game's callback functions like Update diff --git a/internal/graphicsdriver/opengl/gl/debug.go b/internal/graphicsdriver/opengl/gl/debug.go new file mode 100644 index 000000000..87bdff4b7 --- /dev/null +++ b/internal/graphicsdriver/opengl/gl/debug.go @@ -0,0 +1,627 @@ +// 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. + +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) 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) 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) 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) IsTexture(arg0 uint32) bool { + out0 := d.Context.IsTexture(arg0) + fmt.Fprintln(os.Stderr, "IsTexture") + if e := d.Context.GetError(); e != NO_ERROR { + panic(fmt.Sprintf("gl: GetError() returned %d at IsTexture", 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) StencilOp(arg0 uint32, arg1 uint32, arg2 uint32) { + d.Context.StencilOp(arg0, arg1, arg2) + fmt.Fprintln(os.Stderr, "StencilOp") + if e := d.Context.GetError(); e != NO_ERROR { + panic(fmt.Sprintf("gl: GetError() returned %d at StencilOp", 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)) + } +} diff --git a/internal/graphicsdriver/opengl/gl/gen.go b/internal/graphicsdriver/opengl/gl/gen.go new file mode 100644 index 000000000..d953b5c44 --- /dev/null +++ b/internal/graphicsdriver/opengl/gl/gen.go @@ -0,0 +1,143 @@ +// 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 ignore + +package main + +import ( + "fmt" + "os" + "reflect" + "strings" + + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl" +) + +func main() { + if err := run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func run() error { + f, err := os.Create("debug.go") + if err != nil { + return err + } + defer f.Close() + + if _, err := f.WriteString(`// 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. + +package gl + +import ( + "fmt" + "os" +) + +type DebugContext struct { + Context Context +} + +var _ Context = (*DebugContext)(nil) +`); err != nil { + return err + } + + t := reflect.TypeOf((*gl.Context)(nil)).Elem() + for i := 0; i < t.NumMethod(); i++ { + m := t.Method(i) + name := m.Name + + var argNames []string + var argNamesAndTypes []string + for j := 0; j < m.Type.NumIn(); j++ { + n := fmt.Sprintf("arg%d", j) + argNames = append(argNames, n) + argNamesAndTypes = append(argNamesAndTypes, n+" "+typeName(m.Type.In(j))) + } + + var outTypes []string + var outNames []string + for j := 0; j < m.Type.NumOut(); j++ { + outTypes = append(outTypes, typeName(m.Type.Out(j))) + outNames = append(outNames, fmt.Sprintf("out%d", j)) + } + + if _, err := fmt.Fprintf(f, "\nfunc (d *DebugContext) %s(%s) (%s) {\n", name, strings.Join(argNamesAndTypes, ", "), strings.Join(outTypes, ",")); err != nil { + return err + } + if len(outTypes) > 0 { + if _, err := fmt.Fprintf(f, "\t%s := ", strings.Join(outNames, ", ")); err != nil { + return err + } + } else { + if _, err := fmt.Fprintf(f, "\t"); err != nil { + return err + } + } + if _, err := fmt.Fprintf(f, "d.Context.%s(%s)\n", name, strings.Join(argNames, ", ")); err != nil { + return err + } + + // Print logs. + if name != "LoadFunctions" && name != "IsES" { + if _, err := fmt.Fprintf(f, "\tfmt.Fprintln(os.Stderr, %q)\n", name); err != nil { + return err + } + } + + // Check errors. + if name != "LoadFunctions" && name != "IsES" && name != "GetError" { + if _, err := fmt.Fprintf(f, ` if e := d.Context.GetError(); e != NO_ERROR { + panic(fmt.Sprintf("gl: GetError() returned %%d at %s", e)) + } +`, name); err != nil { + return err + } + } + + if len(outTypes) > 0 { + if _, err := fmt.Fprintf(f, "\treturn %s\n", strings.Join(outNames, ", ")); err != nil { + return err + } + } + if _, err := fmt.Fprintf(f, "}\n"); err != nil { + return err + } + } + + return nil +} + +func typeName(t reflect.Type) string { + if t.Kind() == reflect.Slice { + return "[]" + typeName(t.Elem()) + } + return t.Name() +} diff --git a/internal/graphicsdriver/opengl/gl/interface.go b/internal/graphicsdriver/opengl/gl/interface.go index 095f4e56c..e5df5ae39 100644 --- a/internal/graphicsdriver/opengl/gl/interface.go +++ b/internal/graphicsdriver/opengl/gl/interface.go @@ -14,6 +14,9 @@ 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. diff --git a/internal/graphicsdriver/opengl/graphics.go b/internal/graphicsdriver/opengl/graphics.go index 15d1774ff..87304c47e 100644 --- a/internal/graphicsdriver/opengl/graphics.go +++ b/internal/graphicsdriver/opengl/graphics.go @@ -52,6 +52,16 @@ type Graphics struct { activatedTextures []activatedTexture } +func newGraphics(ctx gl.Context) *Graphics { + g := &Graphics{} + 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 diff --git a/internal/graphicsdriver/opengl/graphics_debug.go b/internal/graphicsdriver/opengl/graphics_debug.go new file mode 100644 index 000000000..ecbfe0b6d --- /dev/null +++ b/internal/graphicsdriver/opengl/graphics_debug.go @@ -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 diff --git a/internal/graphicsdriver/opengl/graphics_default.go b/internal/graphicsdriver/opengl/graphics_default.go index 6f132b858..3810f0647 100644 --- a/internal/graphicsdriver/opengl/graphics_default.go +++ b/internal/graphicsdriver/opengl/graphics_default.go @@ -36,7 +36,5 @@ func NewGraphics() (graphicsdriver.Graphics, error) { return nil, err } - g := &Graphics{} - g.context.ctx = ctx - return g, nil + return newGraphics(ctx), nil } diff --git a/internal/graphicsdriver/opengl/graphics_js.go b/internal/graphicsdriver/opengl/graphics_js.go index e1de1fd07..1fd3f1c1e 100644 --- a/internal/graphicsdriver/opengl/graphics_js.go +++ b/internal/graphicsdriver/opengl/graphics_js.go @@ -43,9 +43,8 @@ func NewGraphics(canvas js.Value) (graphicsdriver.Graphics, error) { return nil, err } - g := &Graphics{} + g := newGraphics(ctx) g.context.canvas = canvas - g.context.ctx = ctx return g, nil } diff --git a/internal/graphicsdriver/opengl/graphics_mobile.go b/internal/graphicsdriver/opengl/graphics_mobile.go index 5ab8e15f6..d8be6a5f2 100644 --- a/internal/graphicsdriver/opengl/graphics_mobile.go +++ b/internal/graphicsdriver/opengl/graphics_mobile.go @@ -37,8 +37,5 @@ func NewGraphics(context mgl.Context) (graphicsdriver.Graphics, error) { } } - g := &Graphics{} - g.context.ctx = ctx - - return g, nil + return newGraphics(ctx), nil } diff --git a/internal/graphicsdriver/opengl/graphics_notdebug.go b/internal/graphicsdriver/opengl/graphics_notdebug.go new file mode 100644 index 000000000..45ddc6524 --- /dev/null +++ b/internal/graphicsdriver/opengl/graphics_notdebug.go @@ -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