internal/graphicsdriver/opengl: refactoring: move some functions from internal/ui

Updates #2714
This commit is contained in:
Hajime Hoshi 2023-12-23 19:17:50 +09:00
parent ee2ca6d20c
commit 4895ae7f93
17 changed files with 73 additions and 76 deletions

View File

@ -752,7 +752,7 @@ func EndFrame() error {
return nil
}
func SwapBuffers(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
func SwapBuffers(graphicsDriver graphicsdriver.Graphics) error {
func() {
backendsM.Lock()
defer backendsM.Unlock()
@ -762,7 +762,7 @@ func SwapBuffers(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()
}
}()
if err := restorable.SwapBuffers(graphicsDriver, swapBuffersForGL); err != nil {
if err := restorable.SwapBuffers(graphicsDriver); err != nil {
return err
}
return nil

View File

@ -59,8 +59,8 @@ func SetVsyncEnabled(enabled bool, graphicsDriver graphicsdriver.Graphics) {
// FlushCommands flushes the command queue and present the screen if needed.
// If endFrame is true, the current screen might be used to present.
func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
if err := theCommandQueueManager.flush(graphicsDriver, endFrame, swapBuffersForGL); err != nil {
func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
if err := theCommandQueueManager.flush(graphicsDriver, endFrame); err != nil {
return err
}
return nil
@ -178,7 +178,7 @@ func (q *commandQueue) Enqueue(command command) {
}
// Flush flushes the command queue.
func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
if err := q.err.Load(); err != nil {
return err.(error)
}
@ -212,10 +212,6 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
return
}
if endFrame && swapBuffersForGL != nil {
swapBuffersForGL()
}
theCommandQueueManager.putCommandQueue(q)
}, sync)
@ -504,7 +500,7 @@ func (c *commandQueueManager) enqueueDrawTrianglesCommand(dst *Image, srcs [grap
c.current.EnqueueDrawTrianglesCommand(dst, srcs, vertices, indices, blend, dstRegion, srcRegions, shader, uniforms, fillRule)
}
func (c *commandQueueManager) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
func (c *commandQueueManager) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
// Switch the command queue.
prev := c.current
q, err := c.pool.get()
@ -516,7 +512,7 @@ func (c *commandQueueManager) flush(graphicsDriver graphicsdriver.Graphics, endF
if prev == nil {
return nil
}
if err := prev.Flush(graphicsDriver, endFrame, swapBuffersForGL); err != nil {
if err := prev.Flush(graphicsDriver, endFrame); err != nil {
return err
}
return nil

View File

@ -154,7 +154,7 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, args []graphi
args: args,
}
theCommandQueueManager.enqueueCommand(c)
if err := theCommandQueueManager.flush(graphicsDriver, false, nil); err != nil {
if err := theCommandQueueManager.flush(graphicsDriver, false); err != nil {
return err
}
return nil
@ -183,7 +183,7 @@ func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, err
image: i,
}
theCommandQueueManager.enqueueCommand(c)
if err := theCommandQueueManager.flush(graphicsDriver, false, nil); err != nil {
if err := theCommandQueueManager.flush(graphicsDriver, false); err != nil {
return false, err
}
return c.result, nil

View File

@ -33,15 +33,16 @@ type egl struct {
context C.EGLContext
}
func (e *egl) init(nativeWindowHandle uintptr) error {
// Initialize EGL
func newEGL(nativeWindowHandle uintptr) (*egl, error) {
e := &egl{}
e.display = C.eglGetDisplay(C.NativeDisplayType(C.EGL_DEFAULT_DISPLAY))
if e.display == 0 {
return fmt.Errorf("opengl: eglGetDisplay failed")
return nil, fmt.Errorf("opengl: eglGetDisplay failed")
}
if r := C.eglInitialize(e.display, nil, nil); r == 0 {
return fmt.Errorf("opengl: eglInitialize failed")
return nil, fmt.Errorf("opengl: eglInitialize failed")
}
configAttribs := []C.EGLint{
@ -55,20 +56,20 @@ func (e *egl) init(nativeWindowHandle uintptr) error {
var numConfigs C.EGLint
var config C.EGLConfig
if r := C.eglChooseConfig(e.display, &configAttribs[0], &config, 1, &numConfigs); r == 0 {
return fmt.Errorf("opengl: eglChooseConfig failed")
return nil, fmt.Errorf("opengl: eglChooseConfig failed")
}
if numConfigs != 1 {
return fmt.Errorf("opengl: eglChooseConfig failed: numConfigs must be 1 but %d", numConfigs)
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 fmt.Errorf("opengl: eglCreateWindowSurface failed")
return nil, fmt.Errorf("opengl: eglCreateWindowSurface failed")
}
// Set the current rendering API.
if r := C.eglBindAPI(C.EGL_OPENGL_API); r == 0 {
return fmt.Errorf("opengl: eglBindAPI failed")
return nil, fmt.Errorf("opengl: eglBindAPI failed")
}
// Create new context and set it as current.
@ -81,10 +82,10 @@ func (e *egl) init(nativeWindowHandle uintptr) error {
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 fmt.Errorf("opengl: eglCreateContext failed: error: %d", C.eglGetError())
return nil, fmt.Errorf("opengl: eglCreateContext failed: error: %d", C.eglGetError())
}
return nil
return e, nil
}
func (e *egl) makeContextCurrent() error {

View File

@ -54,6 +54,8 @@ type Graphics struct {
// activatedTextures is a set of activated textures.
// textureNative cannot be a map key unfortunately.
activatedTextures []activatedTexture
graphicsPlatform
}
func newGraphics(ctx gl.Context) *Graphics {

View File

@ -26,6 +26,10 @@ import (
"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) {
@ -83,9 +87,12 @@ func setGLFWClientAPI(isES bool) error {
return nil
}
func (g *Graphics) SetGLFWWindow(window *glfw.Window) {
g.window = window
}
func (g *Graphics) makeContextCurrent() error {
// TODO: Implement this (#2714).
return nil
return g.window.MakeContextCurrent()
}
func (g *Graphics) swapBuffers() error {
@ -105,6 +112,8 @@ func (g *Graphics) swapBuffers() error {
}
}
// TODO: Implement this (#2714).
if err := g.window.SwapBuffers(); err != nil {
return err
}
return nil
}

View File

@ -22,6 +22,9 @@ import (
"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) {

View File

@ -23,6 +23,9 @@ import (
"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(context mgl.Context) (graphicsdriver.Graphics, error) {

View File

@ -21,25 +21,29 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl"
)
var (
theEGL egl
)
type graphicsPlatform struct {
egl *egl
}
func NewGraphics(nativeWindowType uintptr) (graphicsdriver.Graphics, error) {
theEGL.init(nativeWindowType)
ctx, err := gl.NewDefaultContext()
if err != nil {
return nil, err
}
return newGraphics(ctx), nil
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 theEGL.makeContextCurrent()
return g.egl.makeContextCurrent()
}
func (g *Graphics) swapBuffers() error {
theEGL.swapBuffers()
g.egl.swapBuffers()
return nil
}

View File

@ -21,7 +21,7 @@ import (
)
func ResolveStaleImages(graphicsDriver graphicsdriver.Graphics) error {
return resolveStaleImages(graphicsDriver, false, nil)
return resolveStaleImages(graphicsDriver, false)
}
func AppendRegionRemovingDuplicates(regions *[]image.Rectangle, region image.Rectangle) {

View File

@ -56,7 +56,7 @@ var theImages = &images{
shaders: map[*Shader]struct{}{},
}
func SwapBuffers(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) error {
func SwapBuffers(graphicsDriver graphicsdriver.Graphics) error {
if debug.IsDebug {
debug.Logf("Internal image sizes:\n")
imgs := make([]*graphicscommand.Image, 0, len(theImages.images))
@ -65,13 +65,13 @@ func SwapBuffers(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()
}
graphicscommand.LogImagesInfo(imgs)
}
return resolveStaleImages(graphicsDriver, true, swapBuffersForGL)
return resolveStaleImages(graphicsDriver, true)
}
// resolveStaleImages flushes the queued draw commands and resolves all stale images.
// If endFrame is true, the current screen might be used to present when flushing the commands.
func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool, swapBuffersForGL func()) error {
if err := graphicscommand.FlushCommands(graphicsDriver, endFrame, swapBuffersForGL); err != nil {
func resolveStaleImages(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
if err := graphicscommand.FlushCommands(graphicsDriver, endFrame); err != nil {
return err
}
if !needsRestoring() {

View File

@ -63,12 +63,12 @@ func newContext(game Game) *context {
}
}
func (c *context) updateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface, swapBuffersForGL func()) error {
func (c *context) updateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface) error {
// TODO: If updateCount is 0 and vsync is disabled, swapping buffers can be skipped.
return c.updateFrameImpl(graphicsDriver, clock.UpdateFrame(), outsideWidth, outsideHeight, deviceScaleFactor, ui, false, swapBuffersForGL)
return c.updateFrameImpl(graphicsDriver, clock.UpdateFrame(), outsideWidth, outsideHeight, deviceScaleFactor, ui, false)
}
func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface, swapBuffersForGL func()) error {
func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface) error {
n := 1
if ui.GraphicsLibrary() == GraphicsLibraryDirectX {
// On DirectX, both framebuffers in the swap chain should be updated.
@ -76,14 +76,14 @@ func (c *context) forceUpdateFrame(graphicsDriver graphicsdriver.Graphics, outsi
n = 2
}
for i := 0; i < n; i++ {
if err := c.updateFrameImpl(graphicsDriver, 1, outsideWidth, outsideHeight, deviceScaleFactor, ui, true, swapBuffersForGL); err != nil {
if err := c.updateFrameImpl(graphicsDriver, 1, outsideWidth, outsideHeight, deviceScaleFactor, ui, true); err != nil {
return err
}
}
return nil
}
func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, updateCount int, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface, forceDraw bool, swapBuffersForGL func()) (err error) {
func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, updateCount int, outsideWidth, outsideHeight float64, deviceScaleFactor float64, ui *UserInterface, forceDraw bool) (err error) {
// The given outside size can be 0 e.g. just after restoring from the fullscreen mode on Windows (#1589)
// Just ignore such cases. Otherwise, creating a zero-sized framebuffer causes a panic.
if outsideWidth == 0 || outsideHeight == 0 {
@ -102,7 +102,7 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
return
}
if err1 := atlas.SwapBuffers(graphicsDriver, swapBuffersForGL); err1 != nil && err == nil {
if err1 := atlas.SwapBuffers(graphicsDriver); err1 != nil && err == nil {
err = err1
return
}

View File

@ -1177,7 +1177,10 @@ func (u *UserInterface) initOnMainThread(options *RunOptions) error {
}
}
if g, ok := u.graphicsDriver.(interface{ SetWindow(uintptr) }); ok {
switch g := u.graphicsDriver.(type) {
case interface{ SetGLFWWindow(window *glfw.Window) }:
g.SetGLFWWindow(u.window)
case interface{ SetWindow(uintptr) }:
w, err := u.nativeWindow()
if err != nil {
return err
@ -1405,15 +1408,6 @@ func (u *UserInterface) loopGame() (ferr error) {
})
}()
u.renderThread.Call(func() {
if u.GraphicsLibrary() == GraphicsLibraryOpenGL {
if err := u.window.MakeContextCurrent(); err != nil {
u.setError(err)
return
}
}
})
for {
if err := u.updateGame(); err != nil {
return err
@ -1458,13 +1452,7 @@ func (u *UserInterface) updateGame() error {
return err
}
if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor, u, func() {
// This works only for OpenGL.
if err := u.swapBuffersOnRenderThread(); err != nil {
u.setError(err)
return
}
}); err != nil {
if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor, u); err != nil {
return err
}
@ -1543,15 +1531,6 @@ func (u *UserInterface) updateIconIfNeeded() error {
return nil
}
func (u *UserInterface) swapBuffersOnRenderThread() error {
if u.GraphicsLibrary() == GraphicsLibraryOpenGL {
if err := u.window.SwapBuffers(); err != nil {
return err
}
}
return nil
}
// updateWindowSizeLimits must be called from the main thread.
func (u *UserInterface) updateWindowSizeLimits() error {
m, err := u.currentMonitor()

View File

@ -365,11 +365,11 @@ func (u *UserInterface) updateImpl(force bool) error {
w, h := u.outsideSize()
if force {
if err := u.context.forceUpdateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u, nil); err != nil {
if err := u.context.forceUpdateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u); err != nil {
return err
}
} else {
if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u, nil); err != nil {
if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u); err != nil {
return err
}
}

View File

@ -330,7 +330,7 @@ func (u *UserInterface) update() error {
}()
w, h := u.outsideSize()
if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u, nil); err != nil {
if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor(), u); err != nil {
return err
}
return nil

View File

@ -95,7 +95,7 @@ func (u *UserInterface) loopGame() error {
for {
recordProfilerHeartbeat()
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u, nil); err != nil {
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u); err != nil {
return err
}
}

View File

@ -82,7 +82,7 @@ func (u *UserInterface) initOnMainThread(options *RunOptions) error {
func (u *UserInterface) loopGame() error {
for {
if err := u.context.updateFrame(u.graphicsDriver, screenWidth, screenHeight, deviceScaleFactor, u, nil); err != nil {
if err := u.context.updateFrame(u.graphicsDriver, screenWidth, screenHeight, deviceScaleFactor, u); err != nil {
return err
}
}