From f6f7ed3e3d926b76ba087475bc6e60bedda265b5 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Mon, 14 Nov 2022 03:42:37 +0900 Subject: [PATCH] internal/graphicsdriver/opengl/gl: automatically choose OpenGL and OpenGL ES Updates #292 --- .github/workflows/test.yml | 2 +- doc.go | 3 +- .../graphicsdriver/opengl/context_notjs.go | 4 +- .../opengl/gl/default_android.go | 6 +- .../opengl/gl/default_notpurego.go | 152 +++++++++--------- .../opengl/gl/default_purego.go | 152 +++++++++--------- internal/graphicsdriver/opengl/gl/gomobile.go | 2 +- .../graphicsdriver/opengl/gl/interface.go | 2 +- .../opengl/gl/procaddr_darwin.go | 15 +- .../graphicsdriver/opengl/gl/procaddr_gl.go | 48 ------ .../graphicsdriver/opengl/gl/procaddr_gles.go | 48 ------ .../opengl/gl/procaddr_nintendosdk.go | 8 +- .../opengl/gl/procaddr_others.go | 110 +++++++++++++ .../opengl/gl/procaddr_windows.go | 7 +- .../graphicsdriver/opengl/graphics_default.go | 7 +- .../graphicsdriver/opengl/graphics_mobile.go | 6 +- 16 files changed, 308 insertions(+), 264 deletions(-) delete mode 100644 internal/graphicsdriver/opengl/gl/procaddr_gl.go delete mode 100644 internal/graphicsdriver/opengl/gl/procaddr_gles.go create mode 100644 internal/graphicsdriver/opengl/gl/procaddr_others.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf2c59ede..32ee9c3c4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -134,7 +134,7 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get install libgles2-mesa-dev - env EBITENGINE_GRAPHICS_LIBRARY=opengl go test -tags=opengles -shuffle=on -v ./... + env EBITENGINE_GRAPHICS_LIBRARY=opengl EBITENGINE_OPENGL=es go test -shuffle=on -v ./... - name: go test (Windows 386) if: runner.os == 'Windows' diff --git a/doc.go b/doc.go index f9acfab66..a2b5eec57 100644 --- a/doc.go +++ b/doc.go @@ -84,6 +84,7 @@ // `EBITENGINE_OPENGL` environment variable specifies various parameters for OpenGL. // You can specify multiple values separated by a comma. The default value is empty (i.e. no parameters). // +// "es": Use OpenGL ES. Without this, OpenGL and OpenGL ES are automatically chosen. // "webgl1": Use WebGL 1. This is valid only on browsers. // // # Build tags @@ -99,6 +100,4 @@ // `microsoftgdk` is for Microsoft GDK (e.g. Xbox). // // `nintendosdk` is for NintendoSDK (e.g. Nintendo Switch). -// -// `opengles` uses OpenGL ES (2) instead of OpenGL. package ebiten diff --git a/internal/graphicsdriver/opengl/context_notjs.go b/internal/graphicsdriver/opengl/context_notjs.go index 1edd2daf2..fa5f91184 100644 --- a/internal/graphicsdriver/opengl/context_notjs.go +++ b/internal/graphicsdriver/opengl/context_notjs.go @@ -89,8 +89,8 @@ type contextImpl struct { func (c *context) reset() error { if !c.init { - // Initialize OpenGL after WGL is initialized especially for Windows (#2452). - if err := c.ctx.Init(); err != nil { + // Load OpenGL functions after WGL is initialized especially for Windows (#2452). + if err := c.ctx.LoadFunctions(); err != nil { return err } c.init = true diff --git a/internal/graphicsdriver/opengl/gl/default_android.go b/internal/graphicsdriver/opengl/gl/default_android.go index 067a01ccb..fd3b8879f 100644 --- a/internal/graphicsdriver/opengl/gl/default_android.go +++ b/internal/graphicsdriver/opengl/gl/default_android.go @@ -33,11 +33,11 @@ func glBool(x bool) C.GLboolean { type defaultContext struct{} -func NewDefaultContext() Context { - return defaultContext{} +func NewDefaultContext() (Context, error) { + return defaultContext{}, nil } -func (defaultContext) Init() error { +func (defaultContext) LoadFunctions() error { return nil } diff --git a/internal/graphicsdriver/opengl/gl/default_notpurego.go b/internal/graphicsdriver/opengl/gl/default_notpurego.go index 563e1f923..4a40ed239 100644 --- a/internal/graphicsdriver/opengl/gl/default_notpurego.go +++ b/internal/graphicsdriver/opengl/gl/default_notpurego.go @@ -393,10 +393,16 @@ type defaultContext struct { gpUseProgram C.GPUSEPROGRAM gpVertexAttribPointer C.GPVERTEXATTRIBPOINTER gpViewport C.GPVIEWPORT + + isES bool } -func NewDefaultContext() Context { - return &defaultContext{} +func NewDefaultContext() (Context, error) { + ctx := &defaultContext{} + if err := ctx.init(); err != nil { + return nil, err + } + return ctx, nil } func boolToInt(b bool) int { @@ -407,7 +413,7 @@ func boolToInt(b bool) int { } func (c *defaultContext) IsES() bool { - return isES + return c.isES } func (c *defaultContext) ActiveTexture(texture uint32) { @@ -741,244 +747,244 @@ 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) Init() error { - c.gpActiveTexture = (C.GPACTIVETEXTURE)(getProcAddress("glActiveTexture")) +func (c *defaultContext) LoadFunctions() error { + c.gpActiveTexture = (C.GPACTIVETEXTURE)(c.getProcAddress("glActiveTexture")) if c.gpActiveTexture == nil { return errors.New("gl: glActiveTexture is missing") } - c.gpAttachShader = (C.GPATTACHSHADER)(getProcAddress("glAttachShader")) + c.gpAttachShader = (C.GPATTACHSHADER)(c.getProcAddress("glAttachShader")) if c.gpAttachShader == nil { return errors.New("gl: glAttachShader is missing") } - c.gpBindAttribLocation = (C.GPBINDATTRIBLOCATION)(getProcAddress("glBindAttribLocation")) + c.gpBindAttribLocation = (C.GPBINDATTRIBLOCATION)(c.getProcAddress("glBindAttribLocation")) if c.gpBindAttribLocation == nil { return errors.New("gl: glBindAttribLocation is missing") } - c.gpBindBuffer = (C.GPBINDBUFFER)(getProcAddress("glBindBuffer")) + c.gpBindBuffer = (C.GPBINDBUFFER)(c.getProcAddress("glBindBuffer")) if c.gpBindBuffer == nil { return errors.New("gl: glBindBuffer is missing") } - c.gpBindFramebufferEXT = (C.GPBINDFRAMEBUFFEREXT)(getProcAddress("glBindFramebufferEXT")) - c.gpBindRenderbufferEXT = (C.GPBINDRENDERBUFFEREXT)(getProcAddress("glBindRenderbufferEXT")) - c.gpBindTexture = (C.GPBINDTEXTURE)(getProcAddress("glBindTexture")) + c.gpBindFramebufferEXT = (C.GPBINDFRAMEBUFFEREXT)(c.getProcAddress("glBindFramebufferEXT")) + c.gpBindRenderbufferEXT = (C.GPBINDRENDERBUFFEREXT)(c.getProcAddress("glBindRenderbufferEXT")) + c.gpBindTexture = (C.GPBINDTEXTURE)(c.getProcAddress("glBindTexture")) if c.gpBindTexture == nil { return errors.New("gl: glBindTexture is missing") } - c.gpBlendEquationSeparate = (C.GPBLENDEQUATIONSEPARATE)(getProcAddress("glBlendEquationSeparate")) + c.gpBlendEquationSeparate = (C.GPBLENDEQUATIONSEPARATE)(c.getProcAddress("glBlendEquationSeparate")) if c.gpBlendEquationSeparate == nil { return errors.New("gl: glBlendEquationSeparate is missing") } - c.gpBlendFuncSeparate = (C.GPBLENDFUNCSEPARATE)(getProcAddress("glBlendFuncSeparate")) + c.gpBlendFuncSeparate = (C.GPBLENDFUNCSEPARATE)(c.getProcAddress("glBlendFuncSeparate")) if c.gpBlendFuncSeparate == nil { return errors.New("gl: glBlendFuncSeparate is missing") } - c.gpBufferData = (C.GPBUFFERDATA)(getProcAddress("glBufferData")) + c.gpBufferData = (C.GPBUFFERDATA)(c.getProcAddress("glBufferData")) if c.gpBufferData == nil { return errors.New("gl: glBufferData is missing") } - c.gpBufferSubData = (C.GPBUFFERSUBDATA)(getProcAddress("glBufferSubData")) + c.gpBufferSubData = (C.GPBUFFERSUBDATA)(c.getProcAddress("glBufferSubData")) if c.gpBufferSubData == nil { return errors.New("gl: glBufferSubData is missing") } - c.gpCheckFramebufferStatusEXT = (C.GPCHECKFRAMEBUFFERSTATUSEXT)(getProcAddress("glCheckFramebufferStatusEXT")) - c.gpClear = (C.GPCLEAR)(getProcAddress("glClear")) + c.gpCheckFramebufferStatusEXT = (C.GPCHECKFRAMEBUFFERSTATUSEXT)(c.getProcAddress("glCheckFramebufferStatusEXT")) + c.gpClear = (C.GPCLEAR)(c.getProcAddress("glClear")) if c.gpClear == nil { return errors.New("gl: glClear is missing") } - c.gpColorMask = (C.GPCOLORMASK)(getProcAddress("glColorMask")) + c.gpColorMask = (C.GPCOLORMASK)(c.getProcAddress("glColorMask")) if c.gpColorMask == nil { return errors.New("gl: glColorMask is missing") } - c.gpCompileShader = (C.GPCOMPILESHADER)(getProcAddress("glCompileShader")) + c.gpCompileShader = (C.GPCOMPILESHADER)(c.getProcAddress("glCompileShader")) if c.gpCompileShader == nil { return errors.New("gl: glCompileShader is missing") } - c.gpCreateProgram = (C.GPCREATEPROGRAM)(getProcAddress("glCreateProgram")) + c.gpCreateProgram = (C.GPCREATEPROGRAM)(c.getProcAddress("glCreateProgram")) if c.gpCreateProgram == nil { return errors.New("gl: glCreateProgram is missing") } - c.gpCreateShader = (C.GPCREATESHADER)(getProcAddress("glCreateShader")) + c.gpCreateShader = (C.GPCREATESHADER)(c.getProcAddress("glCreateShader")) if c.gpCreateShader == nil { return errors.New("gl: glCreateShader is missing") } - c.gpDeleteBuffers = (C.GPDELETEBUFFERS)(getProcAddress("glDeleteBuffers")) + c.gpDeleteBuffers = (C.GPDELETEBUFFERS)(c.getProcAddress("glDeleteBuffers")) if c.gpDeleteBuffers == nil { return errors.New("gl: glDeleteBuffers is missing") } - c.gpDeleteFramebuffersEXT = (C.GPDELETEFRAMEBUFFERSEXT)(getProcAddress("glDeleteFramebuffersEXT")) - c.gpDeleteProgram = (C.GPDELETEPROGRAM)(getProcAddress("glDeleteProgram")) + c.gpDeleteFramebuffersEXT = (C.GPDELETEFRAMEBUFFERSEXT)(c.getProcAddress("glDeleteFramebuffersEXT")) + c.gpDeleteProgram = (C.GPDELETEPROGRAM)(c.getProcAddress("glDeleteProgram")) if c.gpDeleteProgram == nil { return errors.New("gl: glDeleteProgram is missing") } - c.gpDeleteRenderbuffersEXT = (C.GPDELETERENDERBUFFERSEXT)(getProcAddress("glDeleteRenderbuffersEXT")) - c.gpDeleteShader = (C.GPDELETESHADER)(getProcAddress("glDeleteShader")) + c.gpDeleteRenderbuffersEXT = (C.GPDELETERENDERBUFFERSEXT)(c.getProcAddress("glDeleteRenderbuffersEXT")) + c.gpDeleteShader = (C.GPDELETESHADER)(c.getProcAddress("glDeleteShader")) if c.gpDeleteShader == nil { return errors.New("gl: glDeleteShader is missing") } - c.gpDeleteTextures = (C.GPDELETETEXTURES)(getProcAddress("glDeleteTextures")) + c.gpDeleteTextures = (C.GPDELETETEXTURES)(c.getProcAddress("glDeleteTextures")) if c.gpDeleteTextures == nil { return errors.New("gl: glDeleteTextures is missing") } - c.gpDisable = (C.GPDISABLE)(getProcAddress("glDisable")) + c.gpDisable = (C.GPDISABLE)(c.getProcAddress("glDisable")) if c.gpDisable == nil { return errors.New("gl: glDisable is missing") } - c.gpDisableVertexAttribArray = (C.GPDISABLEVERTEXATTRIBARRAY)(getProcAddress("glDisableVertexAttribArray")) + c.gpDisableVertexAttribArray = (C.GPDISABLEVERTEXATTRIBARRAY)(c.getProcAddress("glDisableVertexAttribArray")) if c.gpDisableVertexAttribArray == nil { return errors.New("gl: glDisableVertexAttribArray is missing") } - c.gpDrawElements = (C.GPDRAWELEMENTS)(getProcAddress("glDrawElements")) + c.gpDrawElements = (C.GPDRAWELEMENTS)(c.getProcAddress("glDrawElements")) if c.gpDrawElements == nil { return errors.New("gl: glDrawElements is missing") } - c.gpEnable = (C.GPENABLE)(getProcAddress("glEnable")) + c.gpEnable = (C.GPENABLE)(c.getProcAddress("glEnable")) if c.gpEnable == nil { return errors.New("gl: glEnable is missing") } - c.gpEnableVertexAttribArray = (C.GPENABLEVERTEXATTRIBARRAY)(getProcAddress("glEnableVertexAttribArray")) + c.gpEnableVertexAttribArray = (C.GPENABLEVERTEXATTRIBARRAY)(c.getProcAddress("glEnableVertexAttribArray")) if c.gpEnableVertexAttribArray == nil { return errors.New("gl: glEnableVertexAttribArray is missing") } - c.gpFlush = (C.GPFLUSH)(getProcAddress("glFlush")) + c.gpFlush = (C.GPFLUSH)(c.getProcAddress("glFlush")) if c.gpFlush == nil { return errors.New("gl: glFlush is missing") } - c.gpFramebufferRenderbufferEXT = (C.GPFRAMEBUFFERRENDERBUFFEREXT)(getProcAddress("glFramebufferRenderbufferEXT")) - c.gpFramebufferTexture2DEXT = (C.GPFRAMEBUFFERTEXTURE2DEXT)(getProcAddress("glFramebufferTexture2DEXT")) - c.gpGenBuffers = (C.GPGENBUFFERS)(getProcAddress("glGenBuffers")) + c.gpFramebufferRenderbufferEXT = (C.GPFRAMEBUFFERRENDERBUFFEREXT)(c.getProcAddress("glFramebufferRenderbufferEXT")) + c.gpFramebufferTexture2DEXT = (C.GPFRAMEBUFFERTEXTURE2DEXT)(c.getProcAddress("glFramebufferTexture2DEXT")) + c.gpGenBuffers = (C.GPGENBUFFERS)(c.getProcAddress("glGenBuffers")) if c.gpGenBuffers == nil { return errors.New("gl: glGenBuffers is missing") } - c.gpGenFramebuffersEXT = (C.GPGENFRAMEBUFFERSEXT)(getProcAddress("glGenFramebuffersEXT")) - c.gpGenRenderbuffersEXT = (C.GPGENRENDERBUFFERSEXT)(getProcAddress("glGenRenderbuffersEXT")) - c.gpGenTextures = (C.GPGENTEXTURES)(getProcAddress("glGenTextures")) + c.gpGenFramebuffersEXT = (C.GPGENFRAMEBUFFERSEXT)(c.getProcAddress("glGenFramebuffersEXT")) + c.gpGenRenderbuffersEXT = (C.GPGENRENDERBUFFERSEXT)(c.getProcAddress("glGenRenderbuffersEXT")) + c.gpGenTextures = (C.GPGENTEXTURES)(c.getProcAddress("glGenTextures")) if c.gpGenTextures == nil { return errors.New("gl: glGenTextures is missing") } - c.gpGetError = (C.GPGETERROR)(getProcAddress("glGetError")) + c.gpGetError = (C.GPGETERROR)(c.getProcAddress("glGetError")) if c.gpGetError == nil { return errors.New("gl: glGetError is missing") } - c.gpGetIntegerv = (C.GPGETINTEGERV)(getProcAddress("glGetIntegerv")) + c.gpGetIntegerv = (C.GPGETINTEGERV)(c.getProcAddress("glGetIntegerv")) if c.gpGetIntegerv == nil { return errors.New("gl: glGetIntegerv is missing") } - c.gpGetProgramInfoLog = (C.GPGETPROGRAMINFOLOG)(getProcAddress("glGetProgramInfoLog")) + c.gpGetProgramInfoLog = (C.GPGETPROGRAMINFOLOG)(c.getProcAddress("glGetProgramInfoLog")) if c.gpGetProgramInfoLog == nil { return errors.New("gl: glGetProgramInfoLog is missing") } - c.gpGetProgramiv = (C.GPGETPROGRAMIV)(getProcAddress("glGetProgramiv")) + c.gpGetProgramiv = (C.GPGETPROGRAMIV)(c.getProcAddress("glGetProgramiv")) if c.gpGetProgramiv == nil { return errors.New("gl: glGetProgramiv is missing") } - c.gpGetShaderInfoLog = (C.GPGETSHADERINFOLOG)(getProcAddress("glGetShaderInfoLog")) + c.gpGetShaderInfoLog = (C.GPGETSHADERINFOLOG)(c.getProcAddress("glGetShaderInfoLog")) if c.gpGetShaderInfoLog == nil { return errors.New("gl: glGetShaderInfoLog is missing") } - c.gpGetShaderiv = (C.GPGETSHADERIV)(getProcAddress("glGetShaderiv")) + c.gpGetShaderiv = (C.GPGETSHADERIV)(c.getProcAddress("glGetShaderiv")) if c.gpGetShaderiv == nil { return errors.New("gl: glGetShaderiv is missing") } - c.gpGetUniformLocation = (C.GPGETUNIFORMLOCATION)(getProcAddress("glGetUniformLocation")) + c.gpGetUniformLocation = (C.GPGETUNIFORMLOCATION)(c.getProcAddress("glGetUniformLocation")) if c.gpGetUniformLocation == nil { return errors.New("gl: glGetUniformLocation is missing") } - c.gpIsFramebufferEXT = (C.GPISFRAMEBUFFEREXT)(getProcAddress("glIsFramebufferEXT")) - c.gpIsProgram = (C.GPISPROGRAM)(getProcAddress("glIsProgram")) + c.gpIsFramebufferEXT = (C.GPISFRAMEBUFFEREXT)(c.getProcAddress("glIsFramebufferEXT")) + c.gpIsProgram = (C.GPISPROGRAM)(c.getProcAddress("glIsProgram")) if c.gpIsProgram == nil { return errors.New("gl: glIsProgram is missing") } - c.gpIsRenderbufferEXT = (C.GPISRENDERBUFFEREXT)(getProcAddress("glIsRenderbufferEXT")) - c.gpIsTexture = (C.GPISTEXTURE)(getProcAddress("glIsTexture")) + c.gpIsRenderbufferEXT = (C.GPISRENDERBUFFEREXT)(c.getProcAddress("glIsRenderbufferEXT")) + c.gpIsTexture = (C.GPISTEXTURE)(c.getProcAddress("glIsTexture")) if c.gpIsTexture == nil { return errors.New("gl: glIsTexture is missing") } - c.gpLinkProgram = (C.GPLINKPROGRAM)(getProcAddress("glLinkProgram")) + c.gpLinkProgram = (C.GPLINKPROGRAM)(c.getProcAddress("glLinkProgram")) if c.gpLinkProgram == nil { return errors.New("gl: glLinkProgram is missing") } - c.gpPixelStorei = (C.GPPIXELSTOREI)(getProcAddress("glPixelStorei")) + c.gpPixelStorei = (C.GPPIXELSTOREI)(c.getProcAddress("glPixelStorei")) if c.gpPixelStorei == nil { return errors.New("gl: glPixelStorei is missing") } - c.gpReadPixels = (C.GPREADPIXELS)(getProcAddress("glReadPixels")) + c.gpReadPixels = (C.GPREADPIXELS)(c.getProcAddress("glReadPixels")) if c.gpReadPixels == nil { return errors.New("gl: glReadPixels is missing") } - c.gpRenderbufferStorageEXT = (C.GPRENDERBUFFERSTORAGEEXT)(getProcAddress("glRenderbufferStorageEXT")) - c.gpScissor = (C.GPSCISSOR)(getProcAddress("glScissor")) + c.gpRenderbufferStorageEXT = (C.GPRENDERBUFFERSTORAGEEXT)(c.getProcAddress("glRenderbufferStorageEXT")) + c.gpScissor = (C.GPSCISSOR)(c.getProcAddress("glScissor")) if c.gpScissor == nil { return errors.New("gl: glScissor is missing") } - c.gpShaderSource = (C.GPSHADERSOURCE)(getProcAddress("glShaderSource")) + c.gpShaderSource = (C.GPSHADERSOURCE)(c.getProcAddress("glShaderSource")) if c.gpShaderSource == nil { return errors.New("gl: glShaderSource is missing") } - c.gpStencilFunc = (C.GPSTENCILFUNC)(getProcAddress("glStencilFunc")) + c.gpStencilFunc = (C.GPSTENCILFUNC)(c.getProcAddress("glStencilFunc")) if c.gpStencilFunc == nil { return errors.New("gl: glStencilFunc is missing") } - c.gpStencilOp = (C.GPSTENCILOP)(getProcAddress("glStencilOp")) + c.gpStencilOp = (C.GPSTENCILOP)(c.getProcAddress("glStencilOp")) if c.gpStencilOp == nil { return errors.New("gl: glStencilOp is missing") } - c.gpTexImage2D = (C.GPTEXIMAGE2D)(getProcAddress("glTexImage2D")) + c.gpTexImage2D = (C.GPTEXIMAGE2D)(c.getProcAddress("glTexImage2D")) if c.gpTexImage2D == nil { return errors.New("gl: glTexImage2D is missing") } - c.gpTexParameteri = (C.GPTEXPARAMETERI)(getProcAddress("glTexParameteri")) + c.gpTexParameteri = (C.GPTEXPARAMETERI)(c.getProcAddress("glTexParameteri")) if c.gpTexParameteri == nil { return errors.New("gl: glTexParameteri is missing") } - c.gpTexSubImage2D = (C.GPTEXSUBIMAGE2D)(getProcAddress("glTexSubImage2D")) + c.gpTexSubImage2D = (C.GPTEXSUBIMAGE2D)(c.getProcAddress("glTexSubImage2D")) if c.gpTexSubImage2D == nil { return errors.New("gl: glTexSubImage2D is missing") } - c.gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddress("glUniform1fv")) + c.gpUniform1fv = (C.GPUNIFORM1FV)(c.getProcAddress("glUniform1fv")) if c.gpUniform1fv == nil { return errors.New("gl: glUniform1fv is missing") } - c.gpUniform1i = (C.GPUNIFORM1I)(getProcAddress("glUniform1i")) + c.gpUniform1i = (C.GPUNIFORM1I)(c.getProcAddress("glUniform1i")) if c.gpUniform1i == nil { return errors.New("gl: glUniform1i is missing") } - c.gpUniform1iv = (C.GPUNIFORM1IV)(getProcAddress("glUniform1iv")) + c.gpUniform1iv = (C.GPUNIFORM1IV)(c.getProcAddress("glUniform1iv")) if c.gpUniform1iv == nil { return errors.New("gl: glUniform1iv is missing") } - c.gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddress("glUniform2fv")) + c.gpUniform2fv = (C.GPUNIFORM2FV)(c.getProcAddress("glUniform2fv")) if c.gpUniform2fv == nil { return errors.New("gl: glUniform2fv is missing") } - c.gpUniform3fv = (C.GPUNIFORM3FV)(getProcAddress("glUniform3fv")) + c.gpUniform3fv = (C.GPUNIFORM3FV)(c.getProcAddress("glUniform3fv")) if c.gpUniform3fv == nil { return errors.New("gl: glUniform3fv is missing") } - c.gpUniform4fv = (C.GPUNIFORM4FV)(getProcAddress("glUniform4fv")) + c.gpUniform4fv = (C.GPUNIFORM4FV)(c.getProcAddress("glUniform4fv")) if c.gpUniform4fv == nil { return errors.New("gl: glUniform4fv is missing") } - c.gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(getProcAddress("glUniformMatrix2fv")) + c.gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(c.getProcAddress("glUniformMatrix2fv")) if c.gpUniformMatrix2fv == nil { return errors.New("gl: glUniformMatrix2fv is missing") } - c.gpUniformMatrix3fv = (C.GPUNIFORMMATRIX3FV)(getProcAddress("glUniformMatrix3fv")) + c.gpUniformMatrix3fv = (C.GPUNIFORMMATRIX3FV)(c.getProcAddress("glUniformMatrix3fv")) if c.gpUniformMatrix3fv == nil { return errors.New("gl: glUniformMatrix3fv is missing") } - c.gpUniformMatrix4fv = (C.GPUNIFORMMATRIX4FV)(getProcAddress("glUniformMatrix4fv")) + c.gpUniformMatrix4fv = (C.GPUNIFORMMATRIX4FV)(c.getProcAddress("glUniformMatrix4fv")) if c.gpUniformMatrix4fv == nil { return errors.New("gl: glUniformMatrix4fv is missing") } - c.gpUseProgram = (C.GPUSEPROGRAM)(getProcAddress("glUseProgram")) + c.gpUseProgram = (C.GPUSEPROGRAM)(c.getProcAddress("glUseProgram")) if c.gpUseProgram == nil { return errors.New("gl: glUseProgram is missing") } - c.gpVertexAttribPointer = (C.GPVERTEXATTRIBPOINTER)(getProcAddress("glVertexAttribPointer")) + c.gpVertexAttribPointer = (C.GPVERTEXATTRIBPOINTER)(c.getProcAddress("glVertexAttribPointer")) if c.gpVertexAttribPointer == nil { return errors.New("gl: glVertexAttribPointer is missing") } - c.gpViewport = (C.GPVIEWPORT)(getProcAddress("glViewport")) + c.gpViewport = (C.GPVIEWPORT)(c.getProcAddress("glViewport")) if c.gpViewport == nil { return errors.New("gl: glViewport is missing") } diff --git a/internal/graphicsdriver/opengl/gl/default_purego.go b/internal/graphicsdriver/opengl/gl/default_purego.go index f6b02befc..08bf6e42e 100644 --- a/internal/graphicsdriver/opengl/gl/default_purego.go +++ b/internal/graphicsdriver/opengl/gl/default_purego.go @@ -94,10 +94,16 @@ type defaultContext struct { gpUseProgram uintptr gpVertexAttribPointer uintptr gpViewport uintptr + + isES bool } -func NewDefaultContext() Context { - return &defaultContext{} +func NewDefaultContext() (Context, error) { + ctx := &defaultContext{} + if err := ctx.init(); err != nil { + return nil, err + } + return ctx, nil } func boolToInt(b bool) int { @@ -108,7 +114,7 @@ func boolToInt(b bool) int { } func (c *defaultContext) IsES() bool { - return isES + return c.isES } func (c *defaultContext) ActiveTexture(texture uint32) { @@ -440,244 +446,244 @@ 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) Init() error { - c.gpActiveTexture = getProcAddress("glActiveTexture") +func (c *defaultContext) LoadFunctions() error { + c.gpActiveTexture = c.getProcAddress("glActiveTexture") if c.gpActiveTexture == 0 { return errors.New("gl: glActiveTexture is missing") } - c.gpAttachShader = getProcAddress("glAttachShader") + c.gpAttachShader = c.getProcAddress("glAttachShader") if c.gpAttachShader == 0 { return errors.New("gl: glAttachShader is missing") } - c.gpBindAttribLocation = getProcAddress("glBindAttribLocation") + c.gpBindAttribLocation = c.getProcAddress("glBindAttribLocation") if c.gpBindAttribLocation == 0 { return errors.New("gl: glBindAttribLocation is missing") } - c.gpBindBuffer = getProcAddress("glBindBuffer") + c.gpBindBuffer = c.getProcAddress("glBindBuffer") if c.gpBindBuffer == 0 { return errors.New("gl: glBindBuffer is missing") } - c.gpBindFramebufferEXT = getProcAddress("glBindFramebufferEXT") - c.gpBindRenderbufferEXT = getProcAddress("glBindRenderbufferEXT") - c.gpBindTexture = getProcAddress("glBindTexture") + c.gpBindFramebufferEXT = c.getProcAddress("glBindFramebufferEXT") + c.gpBindRenderbufferEXT = c.getProcAddress("glBindRenderbufferEXT") + c.gpBindTexture = c.getProcAddress("glBindTexture") if c.gpBindTexture == 0 { return errors.New("gl: glBindTexture is missing") } - c.gpBlendEquationSeparate = getProcAddress("glBlendEquationSeparate") + c.gpBlendEquationSeparate = c.getProcAddress("glBlendEquationSeparate") if c.gpBlendEquationSeparate == 0 { return errors.New("gl: glBlendEquationSeparate is missing") } - c.gpBlendFuncSeparate = getProcAddress("glBlendFuncSeparate") + c.gpBlendFuncSeparate = c.getProcAddress("glBlendFuncSeparate") if c.gpBlendFuncSeparate == 0 { return errors.New("gl: glBlendFuncSeparate is missing") } - c.gpBufferData = getProcAddress("glBufferData") + c.gpBufferData = c.getProcAddress("glBufferData") if c.gpBufferData == 0 { return errors.New("gl: glBufferData is missing") } - c.gpBufferSubData = getProcAddress("glBufferSubData") + c.gpBufferSubData = c.getProcAddress("glBufferSubData") if c.gpBufferSubData == 0 { return errors.New("gl: glBufferSubData is missing") } - c.gpCheckFramebufferStatusEXT = getProcAddress("glCheckFramebufferStatusEXT") - c.gpClear = getProcAddress("glClear") + c.gpCheckFramebufferStatusEXT = c.getProcAddress("glCheckFramebufferStatusEXT") + c.gpClear = c.getProcAddress("glClear") if c.gpClear == 0 { return errors.New("gl: glClear is missing") } - c.gpColorMask = getProcAddress("glColorMask") + c.gpColorMask = c.getProcAddress("glColorMask") if c.gpColorMask == 0 { return errors.New("gl: glColorMask is missing") } - c.gpCompileShader = getProcAddress("glCompileShader") + c.gpCompileShader = c.getProcAddress("glCompileShader") if c.gpCompileShader == 0 { return errors.New("gl: glCompileShader is missing") } - c.gpCreateProgram = getProcAddress("glCreateProgram") + c.gpCreateProgram = c.getProcAddress("glCreateProgram") if c.gpCreateProgram == 0 { return errors.New("gl: glCreateProgram is missing") } - c.gpCreateShader = getProcAddress("glCreateShader") + c.gpCreateShader = c.getProcAddress("glCreateShader") if c.gpCreateShader == 0 { return errors.New("gl: glCreateShader is missing") } - c.gpDeleteBuffers = getProcAddress("glDeleteBuffers") + c.gpDeleteBuffers = c.getProcAddress("glDeleteBuffers") if c.gpDeleteBuffers == 0 { return errors.New("gl: glDeleteBuffers is missing") } - c.gpDeleteFramebuffersEXT = getProcAddress("glDeleteFramebuffersEXT") - c.gpDeleteProgram = getProcAddress("glDeleteProgram") + c.gpDeleteFramebuffersEXT = c.getProcAddress("glDeleteFramebuffersEXT") + c.gpDeleteProgram = c.getProcAddress("glDeleteProgram") if c.gpDeleteProgram == 0 { return errors.New("gl: glDeleteProgram is missing") } - c.gpDeleteRenderbuffersEXT = getProcAddress("glDeleteRenderbuffersEXT") - c.gpDeleteShader = getProcAddress("glDeleteShader") + c.gpDeleteRenderbuffersEXT = c.getProcAddress("glDeleteRenderbuffersEXT") + c.gpDeleteShader = c.getProcAddress("glDeleteShader") if c.gpDeleteShader == 0 { return errors.New("gl: glDeleteShader is missing") } - c.gpDeleteTextures = getProcAddress("glDeleteTextures") + c.gpDeleteTextures = c.getProcAddress("glDeleteTextures") if c.gpDeleteTextures == 0 { return errors.New("gl: glDeleteTextures is missing") } - c.gpDisable = getProcAddress("glDisable") + c.gpDisable = c.getProcAddress("glDisable") if c.gpDisable == 0 { return errors.New("gl: glDisable is missing") } - c.gpDisableVertexAttribArray = getProcAddress("glDisableVertexAttribArray") + c.gpDisableVertexAttribArray = c.getProcAddress("glDisableVertexAttribArray") if c.gpDisableVertexAttribArray == 0 { return errors.New("gl: glDisableVertexAttribArray is missing") } - c.gpDrawElements = getProcAddress("glDrawElements") + c.gpDrawElements = c.getProcAddress("glDrawElements") if c.gpDrawElements == 0 { return errors.New("gl: glDrawElements is missing") } - c.gpEnable = getProcAddress("glEnable") + c.gpEnable = c.getProcAddress("glEnable") if c.gpEnable == 0 { return errors.New("gl: glEnable is missing") } - c.gpEnableVertexAttribArray = getProcAddress("glEnableVertexAttribArray") + c.gpEnableVertexAttribArray = c.getProcAddress("glEnableVertexAttribArray") if c.gpEnableVertexAttribArray == 0 { return errors.New("gl: glEnableVertexAttribArray is missing") } - c.gpFlush = getProcAddress("glFlush") + c.gpFlush = c.getProcAddress("glFlush") if c.gpFlush == 0 { return errors.New("gl: glFlush is missing") } - c.gpFramebufferRenderbufferEXT = getProcAddress("glFramebufferRenderbufferEXT") - c.gpFramebufferTexture2DEXT = getProcAddress("glFramebufferTexture2DEXT") - c.gpGenBuffers = getProcAddress("glGenBuffers") + c.gpFramebufferRenderbufferEXT = c.getProcAddress("glFramebufferRenderbufferEXT") + c.gpFramebufferTexture2DEXT = c.getProcAddress("glFramebufferTexture2DEXT") + c.gpGenBuffers = c.getProcAddress("glGenBuffers") if c.gpGenBuffers == 0 { return errors.New("gl: glGenBuffers is missing") } - c.gpGenFramebuffersEXT = getProcAddress("glGenFramebuffersEXT") - c.gpGenRenderbuffersEXT = getProcAddress("glGenRenderbuffersEXT") - c.gpGenTextures = getProcAddress("glGenTextures") + c.gpGenFramebuffersEXT = c.getProcAddress("glGenFramebuffersEXT") + c.gpGenRenderbuffersEXT = c.getProcAddress("glGenRenderbuffersEXT") + c.gpGenTextures = c.getProcAddress("glGenTextures") if c.gpGenTextures == 0 { return errors.New("gl: glGenTextures is missing") } - c.gpGetError = getProcAddress("glGetError") + c.gpGetError = c.getProcAddress("glGetError") if c.gpGetError == 0 { return errors.New("gl: glGetError is missing") } - c.gpGetIntegerv = getProcAddress("glGetIntegerv") + c.gpGetIntegerv = c.getProcAddress("glGetIntegerv") if c.gpGetIntegerv == 0 { return errors.New("gl: glGetIntegerv is missing") } - c.gpGetProgramInfoLog = getProcAddress("glGetProgramInfoLog") + c.gpGetProgramInfoLog = c.getProcAddress("glGetProgramInfoLog") if c.gpGetProgramInfoLog == 0 { return errors.New("gl: glGetProgramInfoLog is missing") } - c.gpGetProgramiv = getProcAddress("glGetProgramiv") + c.gpGetProgramiv = c.getProcAddress("glGetProgramiv") if c.gpGetProgramiv == 0 { return errors.New("gl: glGetProgramiv is missing") } - c.gpGetShaderInfoLog = getProcAddress("glGetShaderInfoLog") + c.gpGetShaderInfoLog = c.getProcAddress("glGetShaderInfoLog") if c.gpGetShaderInfoLog == 0 { return errors.New("gl: glGetShaderInfoLog is missing") } - c.gpGetShaderiv = getProcAddress("glGetShaderiv") + c.gpGetShaderiv = c.getProcAddress("glGetShaderiv") if c.gpGetShaderiv == 0 { return errors.New("gl: glGetShaderiv is missing") } - c.gpGetUniformLocation = getProcAddress("glGetUniformLocation") + c.gpGetUniformLocation = c.getProcAddress("glGetUniformLocation") if c.gpGetUniformLocation == 0 { return errors.New("gl: glGetUniformLocation is missing") } - c.gpIsFramebufferEXT = getProcAddress("glIsFramebufferEXT") - c.gpIsProgram = getProcAddress("glIsProgram") + c.gpIsFramebufferEXT = c.getProcAddress("glIsFramebufferEXT") + c.gpIsProgram = c.getProcAddress("glIsProgram") if c.gpIsProgram == 0 { return errors.New("gl: glIsProgram is missing") } - c.gpIsRenderbufferEXT = getProcAddress("glIsRenderbufferEXT") - c.gpIsTexture = getProcAddress("glIsTexture") + c.gpIsRenderbufferEXT = c.getProcAddress("glIsRenderbufferEXT") + c.gpIsTexture = c.getProcAddress("glIsTexture") if c.gpIsTexture == 0 { return errors.New("gl: glIsTexture is missing") } - c.gpLinkProgram = getProcAddress("glLinkProgram") + c.gpLinkProgram = c.getProcAddress("glLinkProgram") if c.gpLinkProgram == 0 { return errors.New("gl: glLinkProgram is missing") } - c.gpPixelStorei = getProcAddress("glPixelStorei") + c.gpPixelStorei = c.getProcAddress("glPixelStorei") if c.gpPixelStorei == 0 { return errors.New("gl: glPixelStorei is missing") } - c.gpReadPixels = getProcAddress("glReadPixels") + c.gpReadPixels = c.getProcAddress("glReadPixels") if c.gpReadPixels == 0 { return errors.New("gl: glReadPixels is missing") } - c.gpRenderbufferStorageEXT = getProcAddress("glRenderbufferStorageEXT") - c.gpScissor = getProcAddress("glScissor") + c.gpRenderbufferStorageEXT = c.getProcAddress("glRenderbufferStorageEXT") + c.gpScissor = c.getProcAddress("glScissor") if c.gpScissor == 0 { return errors.New("gl: glScissor is missing") } - c.gpShaderSource = getProcAddress("glShaderSource") + c.gpShaderSource = c.getProcAddress("glShaderSource") if c.gpShaderSource == 0 { return errors.New("gl: glShaderSource is missing") } - c.gpStencilFunc = getProcAddress("glStencilFunc") + c.gpStencilFunc = c.getProcAddress("glStencilFunc") if c.gpStencilFunc == 0 { return errors.New("gl: glStencilFunc is missing") } - c.gpStencilOp = getProcAddress("glStencilOp") + c.gpStencilOp = c.getProcAddress("glStencilOp") if c.gpStencilOp == 0 { return errors.New("gl: glStencilOp is missing") } - c.gpTexImage2D = getProcAddress("glTexImage2D") + c.gpTexImage2D = c.getProcAddress("glTexImage2D") if c.gpTexImage2D == 0 { return errors.New("gl: glTexImage2D is missing") } - c.gpTexParameteri = getProcAddress("glTexParameteri") + c.gpTexParameteri = c.getProcAddress("glTexParameteri") if c.gpTexParameteri == 0 { return errors.New("gl: glTexParameteri is missing") } - c.gpTexSubImage2D = getProcAddress("glTexSubImage2D") + c.gpTexSubImage2D = c.getProcAddress("glTexSubImage2D") if c.gpTexSubImage2D == 0 { return errors.New("gl: glTexSubImage2D is missing") } - c.gpUniform1fv = getProcAddress("glUniform1fv") + c.gpUniform1fv = c.getProcAddress("glUniform1fv") if c.gpUniform1fv == 0 { return errors.New("gl: glUniform1fv is missing") } - c.gpUniform1i = getProcAddress("glUniform1i") + c.gpUniform1i = c.getProcAddress("glUniform1i") if c.gpUniform1i == 0 { return errors.New("gl: glUniform1i is missing") } - c.gpUniform1iv = getProcAddress("glUniform1iv") + c.gpUniform1iv = c.getProcAddress("glUniform1iv") if c.gpUniform1iv == 0 { return errors.New("gl: glUniform1iv is missing") } - c.gpUniform2fv = getProcAddress("glUniform2fv") + c.gpUniform2fv = c.getProcAddress("glUniform2fv") if c.gpUniform2fv == 0 { return errors.New("gl: glUniform2fv is missing") } - c.gpUniform3fv = getProcAddress("glUniform3fv") + c.gpUniform3fv = c.getProcAddress("glUniform3fv") if c.gpUniform3fv == 0 { return errors.New("gl: glUniform3fv is missing") } - c.gpUniform4fv = getProcAddress("glUniform4fv") + c.gpUniform4fv = c.getProcAddress("glUniform4fv") if c.gpUniform4fv == 0 { return errors.New("gl: glUniform4fv is missing") } - c.gpUniformMatrix2fv = getProcAddress("glUniformMatrix2fv") + c.gpUniformMatrix2fv = c.getProcAddress("glUniformMatrix2fv") if c.gpUniformMatrix2fv == 0 { return errors.New("gl: glUniformMatrix2fv is missing") } - c.gpUniformMatrix3fv = getProcAddress("glUniformMatrix3fv") + c.gpUniformMatrix3fv = c.getProcAddress("glUniformMatrix3fv") if c.gpUniformMatrix3fv == 0 { return errors.New("gl: glUniformMatrix3fv is missing") } - c.gpUniformMatrix4fv = getProcAddress("glUniformMatrix4fv") + c.gpUniformMatrix4fv = c.getProcAddress("glUniformMatrix4fv") if c.gpUniformMatrix4fv == 0 { return errors.New("gl: glUniformMatrix4fv is missing") } - c.gpUseProgram = getProcAddress("glUseProgram") + c.gpUseProgram = c.getProcAddress("glUseProgram") if c.gpUseProgram == 0 { return errors.New("gl: glUseProgram is missing") } - c.gpVertexAttribPointer = getProcAddress("glVertexAttribPointer") + c.gpVertexAttribPointer = c.getProcAddress("glVertexAttribPointer") if c.gpVertexAttribPointer == 0 { return errors.New("gl: glVertexAttribPointer is missing") } - c.gpViewport = getProcAddress("glViewport") + c.gpViewport = c.getProcAddress("glViewport") if c.gpViewport == 0 { return errors.New("gl: glViewport is missing") } diff --git a/internal/graphicsdriver/opengl/gl/gomobile.go b/internal/graphicsdriver/opengl/gl/gomobile.go index 45a597a2d..00b4d1e7b 100644 --- a/internal/graphicsdriver/opengl/gl/gomobile.go +++ b/internal/graphicsdriver/opengl/gl/gomobile.go @@ -35,7 +35,7 @@ func NewGomobileContext(ctx gl.Context) Context { return &gomobileContext{ctx} } -func (g *gomobileContext) Init() error { +func (g *gomobileContext) LoadFunctions() error { return nil } diff --git a/internal/graphicsdriver/opengl/gl/interface.go b/internal/graphicsdriver/opengl/gl/interface.go index e5a011f07..f06a81186 100644 --- a/internal/graphicsdriver/opengl/gl/interface.go +++ b/internal/graphicsdriver/opengl/gl/interface.go @@ -19,7 +19,7 @@ package gl // Context is basically the same as gomobile's gl.Context. // See https://pkg.go.dev/golang.org/x/mobile/gl#Context type Context interface { - Init() error + LoadFunctions() error IsES() bool ActiveTexture(texture uint32) diff --git a/internal/graphicsdriver/opengl/gl/procaddr_darwin.go b/internal/graphicsdriver/opengl/gl/procaddr_darwin.go index c901b24a7..2b2cf21ef 100644 --- a/internal/graphicsdriver/opengl/gl/procaddr_darwin.go +++ b/internal/graphicsdriver/opengl/gl/procaddr_darwin.go @@ -15,23 +15,28 @@ package gl import ( + "fmt" + "github.com/ebitengine/purego" ) var ( opengl uintptr - isES bool ) -func init() { +func (c *defaultContext) init() error { opengl = purego.Dlopen("/System/Library/Frameworks/OpenGLES.framework/Versions/Current/OpenGLES", purego.RTLD_LAZY|purego.RTLD_GLOBAL) if opengl != 0 { - isES = true - return + c.isES = true + return nil } opengl = purego.Dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", purego.RTLD_LAZY|purego.RTLD_GLOBAL) + if opengl != 0 { + return nil + } + return fmt.Errorf("gl: failed to load OpenGL.framework and OpenGLES.framework") } -func getProcAddress(name string) uintptr { +func (c *defaultContext) getProcAddress(name string) uintptr { return purego.Dlsym(opengl, name) } diff --git a/internal/graphicsdriver/opengl/gl/procaddr_gl.go b/internal/graphicsdriver/opengl/gl/procaddr_gl.go deleted file mode 100644 index f16d502e7..000000000 --- a/internal/graphicsdriver/opengl/gl/procaddr_gl.go +++ /dev/null @@ -1,48 +0,0 @@ -// 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 && !darwin && !js && !nintendosdk && !windows && !opengles - -package gl - -// #cgo LDFLAGS: -ldl -// -// #include -// #include -// -// static void* getProcAddress(const char* name) { -// static void* libGL; -// if (!libGL) { -// libGL = dlopen("libGL.so", RTLD_LAZY | RTLD_GLOBAL); -// } -// static void*(*glXGetProcAddress)(const char*); -// if (!glXGetProcAddress) { -// glXGetProcAddress = dlsym(libGL, "glXGetProcAddress"); -// if (!glXGetProcAddress) { -// glXGetProcAddress = dlsym(libGL, "glXGetProcAddressARB"); -// } -// } -// return glXGetProcAddress(name); -// } -import "C" - -import "unsafe" - -var isES = false - -func getProcAddress(namea string) unsafe.Pointer { - cname := C.CString(namea) - defer C.free(unsafe.Pointer(cname)) - return C.getProcAddress(cname) -} diff --git a/internal/graphicsdriver/opengl/gl/procaddr_gles.go b/internal/graphicsdriver/opengl/gl/procaddr_gles.go deleted file mode 100644 index 9831887ad..000000000 --- a/internal/graphicsdriver/opengl/gl/procaddr_gles.go +++ /dev/null @@ -1,48 +0,0 @@ -// 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 && !darwin && !js && !nintendosdk && !windows && opengles - -package gl - -// #cgo LDFLAGS: -ldl -// -// #include -// #include -// -// static void* getProcAddress(const char* name) { -// static void* libGLES; -// if (!libGLES) { -// libGLES = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_GLOBAL); -// } -// return dlsym(libGLES, name); -// } -import "C" - -import ( - "strings" - "unsafe" -) - -var isES = true - -func getProcAddress(namea string) unsafe.Pointer { - const ext = "EXT" - if strings.HasSuffix(namea, ext) { - namea = namea[:len(namea)-len(ext)] - } - cname := C.CString(namea) - defer C.free(unsafe.Pointer(cname)) - return C.getProcAddress(cname) -} diff --git a/internal/graphicsdriver/opengl/gl/procaddr_nintendosdk.go b/internal/graphicsdriver/opengl/gl/procaddr_nintendosdk.go index cb2c26786..6ff409a02 100644 --- a/internal/graphicsdriver/opengl/gl/procaddr_nintendosdk.go +++ b/internal/graphicsdriver/opengl/gl/procaddr_nintendosdk.go @@ -28,10 +28,12 @@ import "C" import "unsafe" -var isES = false +func (c *defaultContext) init() error { + return nil +} -func getProcAddress(namea string) unsafe.Pointer { - cname := C.CString(namea) +func (c *defaultContext) getProcAddress(name string) unsafe.Pointer { + cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) return C.getProcAddress(cname) } diff --git a/internal/graphicsdriver/opengl/gl/procaddr_others.go b/internal/graphicsdriver/opengl/gl/procaddr_others.go new file mode 100644 index 000000000..041c144b1 --- /dev/null +++ b/internal/graphicsdriver/opengl/gl/procaddr_others.go @@ -0,0 +1,110 @@ +// 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 && !darwin && !js && !nintendosdk && !windows + +package gl + +// #cgo LDFLAGS: -ldl +// +// #include +// #include +// +// static void* libGL() { +// static void* so; +// if (!so) { +// so = dlopen("libGL.so", RTLD_LAZY | RTLD_GLOBAL); +// } +// return so; +// } +// +// static void* libGLES() { +// static void* so; +// if (!so) { +// so = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_GLOBAL); +// } +// return so; +// } +// +// static void* getProcAddressGL(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(const char* name) { +// return dlsym(libGLES(), name); +// } +import "C" + +import ( + "fmt" + "os" + "strings" + "unsafe" +) + +func (c *defaultContext) init() error { + var preferES bool + for _, t := range strings.Split(os.Getenv("EBITENGINE_OPENGL"), ",") { + switch strings.TrimSpace(t) { + case "es": + preferES = true + break + } + } + + // Try OpenGL first. OpenGL is preferrable as this doesn't cause context losts. + if !preferES { + if C.libGL() != nil { + return nil + } + } + + // Try OpenGL ES. + if C.libGLES() != nil { + c.isES = true + return nil + } + + return fmt.Errorf("gl: failed to load libGL.so and libGLES.so") +} + +func (c *defaultContext) getProcAddress(name string) unsafe.Pointer { + if c.isES { + return getProcAddressGLES(name) + } + return getProcAddressGL(name) +} + +func getProcAddressGL(name string) unsafe.Pointer { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return C.getProcAddressGL(cname) +} + +func getProcAddressGLES(name string) unsafe.Pointer { + const ext = "EXT" + if strings.HasSuffix(name, ext) { + name = name[:len(name)-len(ext)] + } + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return C.getProcAddressGLES(cname) +} diff --git a/internal/graphicsdriver/opengl/gl/procaddr_windows.go b/internal/graphicsdriver/opengl/gl/procaddr_windows.go index 68bc9b9d9..245fef550 100644 --- a/internal/graphicsdriver/opengl/gl/procaddr_windows.go +++ b/internal/graphicsdriver/opengl/gl/procaddr_windows.go @@ -24,10 +24,13 @@ import ( var ( opengl32 = windows.NewLazySystemDLL("opengl32") procWglGetProcAddress = opengl32.NewProc("wglGetProcAddress") - isES = false ) -func getProcAddress(namea string) uintptr { +func (c *defaultContext) init() error { + return nil +} + +func (c *defaultContext) getProcAddress(namea string) uintptr { cname, err := windows.BytePtrFromString(namea) if err != nil { panic(err) diff --git a/internal/graphicsdriver/opengl/graphics_default.go b/internal/graphicsdriver/opengl/graphics_default.go index 8965a97bb..6f132b858 100644 --- a/internal/graphicsdriver/opengl/graphics_default.go +++ b/internal/graphicsdriver/opengl/graphics_default.go @@ -31,7 +31,12 @@ func NewGraphics() (graphicsdriver.Graphics, error) { return nil, fmt.Errorf("opengl: OpenGL is not supported on Xbox") } + ctx, err := gl.NewDefaultContext() + if err != nil { + return nil, err + } + g := &Graphics{} - g.context.ctx = gl.NewDefaultContext() + g.context.ctx = ctx return g, nil } diff --git a/internal/graphicsdriver/opengl/graphics_mobile.go b/internal/graphicsdriver/opengl/graphics_mobile.go index d23e6560f..5ab8e15f6 100644 --- a/internal/graphicsdriver/opengl/graphics_mobile.go +++ b/internal/graphicsdriver/opengl/graphics_mobile.go @@ -30,7 +30,11 @@ func NewGraphics(context mgl.Context) (graphicsdriver.Graphics, error) { if context != nil { ctx = gl.NewGomobileContext(context.(mgl.Context)) } else { - ctx = gl.NewDefaultContext() + var err error + ctx, err = gl.NewDefaultContext() + if err != nil { + return nil, err + } } g := &Graphics{}