graphicsdriver/opengl: Rename Driver -> Graphics

This commit is contained in:
Hajime Hoshi 2020-04-04 17:20:08 +09:00
parent 01d1afa25c
commit eabe4152a7
6 changed files with 105 additions and 105 deletions

View File

@ -16,10 +16,10 @@ package opengl
// framebuffer is a wrapper of OpenGL's framebuffer. // framebuffer is a wrapper of OpenGL's framebuffer.
type framebuffer struct { type framebuffer struct {
driver *Driver graphics *Graphics
native framebufferNative native framebufferNative
width int width int
height int height int
} }
// newFramebufferFromTexture creates a framebuffer from the given texture. // newFramebufferFromTexture creates a framebuffer from the given texture.

View File

@ -23,13 +23,13 @@ import (
"github.com/hajimehoshi/ebiten/internal/thread" "github.com/hajimehoshi/ebiten/internal/thread"
) )
var theDriver Driver var theGraphics Graphics
func Get() *Driver { func Get() *Graphics {
return &theDriver return &theGraphics
} }
type Driver struct { type Graphics struct {
state openGLState state openGLState
context context context context
@ -37,32 +37,32 @@ type Driver struct {
drawCalled bool drawCalled bool
} }
func (d *Driver) SetThread(thread *thread.Thread) { func (g *Graphics) SetThread(thread *thread.Thread) {
d.context.t = thread g.context.t = thread
} }
func (d *Driver) Begin() { func (g *Graphics) Begin() {
// Do nothing. // Do nothing.
} }
func (d *Driver) End() { func (g *Graphics) End() {
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS). // Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
// TODO: examples/sprites worked without this. Is this really needed? // TODO: examples/sprites worked without this. Is this really needed?
d.context.flush() g.context.flush()
} }
func (d *Driver) SetTransparent(transparent bool) { func (g *Graphics) SetTransparent(transparent bool) {
// Do nothings. // Do nothings.
} }
func (d *Driver) checkSize(width, height int) { func (g *Graphics) checkSize(width, height int) {
if width < 1 { if width < 1 {
panic(fmt.Sprintf("opengl: width (%d) must be equal or more than %d", width, 1)) panic(fmt.Sprintf("opengl: width (%d) must be equal or more than %d", width, 1))
} }
if height < 1 { if height < 1 {
panic(fmt.Sprintf("opengl: height (%d) must be equal or more than %d", height, 1)) panic(fmt.Sprintf("opengl: height (%d) must be equal or more than %d", height, 1))
} }
m := d.context.getMaxTextureSize() m := g.context.getMaxTextureSize()
if width > m { if width > m {
panic(fmt.Sprintf("opengl: width (%d) must be less than or equal to %d", width, m)) panic(fmt.Sprintf("opengl: width (%d) must be less than or equal to %d", width, m))
} }
@ -71,16 +71,16 @@ func (d *Driver) checkSize(width, height int) {
} }
} }
func (d *Driver) NewImage(width, height int) (driver.Image, error) { func (g *Graphics) NewImage(width, height int) (driver.Image, error) {
i := &Image{ i := &Image{
driver: d, graphics: g,
width: width, width: width,
height: height, height: height,
} }
w := graphics.InternalImageSize(width) w := graphics.InternalImageSize(width)
h := graphics.InternalImageSize(height) h := graphics.InternalImageSize(height)
d.checkSize(w, h) g.checkSize(w, h)
t, err := d.context.newTexture(w, h) t, err := g.context.newTexture(w, h)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -88,63 +88,63 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) {
return i, nil return i, nil
} }
func (d *Driver) NewScreenFramebufferImage(width, height int) (driver.Image, error) { func (g *Graphics) NewScreenFramebufferImage(width, height int) (driver.Image, error) {
d.checkSize(width, height) g.checkSize(width, height)
i := &Image{ i := &Image{
driver: d, graphics: g,
width: width, width: width,
height: height, height: height,
screen: true, screen: true,
} }
return i, nil return i, nil
} }
// Reset resets or initializes the current OpenGL state. // Reset resets or initializes the current OpenGL state.
func (d *Driver) Reset() error { func (g *Graphics) Reset() error {
return d.state.reset(&d.context) return g.state.reset(&g.context)
} }
func (d *Driver) SetVertices(vertices []float32, indices []uint16) { func (g *Graphics) SetVertices(vertices []float32, indices []uint16) {
// Note that the vertices passed to BufferSubData is not under GC management // Note that the vertices passed to BufferSubData is not under GC management
// in opengl package due to unsafe-way. // in opengl package due to unsafe-way.
// See BufferSubData in context_mobile.go. // See BufferSubData in context_mobile.go.
d.context.arrayBufferSubData(vertices) g.context.arrayBufferSubData(vertices)
d.context.elementArrayBufferSubData(indices) g.context.elementArrayBufferSubData(indices)
} }
func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error { func (g *Graphics) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error {
d.drawCalled = true g.drawCalled = true
if err := d.useProgram(mode, colorM, filter, address); err != nil { if err := g.useProgram(mode, colorM, filter, address); err != nil {
return err return err
} }
d.context.drawElements(indexLen, indexOffset*2) // 2 is uint16 size in bytes g.context.drawElements(indexLen, indexOffset*2) // 2 is uint16 size in bytes
// glFlush() might be necessary at least on MacBook Pro (a smilar problem at #419), // glFlush() might be necessary at least on MacBook Pro (a smilar problem at #419),
// but basically this pass the tests (esp. TestImageTooManyFill). // but basically this pass the tests (esp. TestImageTooManyFill).
// As glFlush() causes performance problems, this should be avoided as much as possible. // As glFlush() causes performance problems, this should be avoided as much as possible.
// Let's wait and see, and file a new issue when this problem is newly found. // Let's wait and see, and file a new issue when this problem is newly foung.
return nil return nil
} }
func (d *Driver) SetVsyncEnabled(enabled bool) { func (g *Graphics) SetVsyncEnabled(enabled bool) {
// Do nothing // Do nothing
} }
func (d *Driver) VDirection() driver.VDirection { func (g *Graphics) VDirection() driver.VDirection {
return driver.VDownward return driver.VDownward
} }
func (d *Driver) NeedsRestoring() bool { func (g *Graphics) NeedsRestoring() bool {
return d.context.needsRestoring() return g.context.needsRestoring()
} }
func (d *Driver) IsGL() bool { func (g *Graphics) IsGL() bool {
return true return true
} }
func (d *Driver) HasHighPrecisionFloat() bool { func (g *Graphics) HasHighPrecisionFloat() bool {
return d.context.hasHighPrecisionFloat() return g.context.hasHighPrecisionFloat()
} }
func (d *Driver) MaxImageSize() int { func (g *Graphics) MaxImageSize() int {
return d.context.getMaxTextureSize() return g.context.getMaxTextureSize()
} }

View File

@ -20,6 +20,6 @@ import (
"golang.org/x/mobile/gl" "golang.org/x/mobile/gl"
) )
func (d *Driver) SetMobileGLContext(context gl.Context) { func (g *Graphics) SetMobileGLContext(context gl.Context) {
d.context.gl = context g.context.gl = context
} }

View File

@ -20,7 +20,7 @@ import (
) )
type Image struct { type Image struct {
driver *Driver graphics *Graphics
textureNative textureNative textureNative textureNative
framebuffer *framebuffer framebuffer *framebuffer
pbo buffer pbo buffer
@ -30,30 +30,30 @@ type Image struct {
} }
func (i *Image) IsInvalidated() bool { func (i *Image) IsInvalidated() bool {
return !i.driver.context.isTexture(i.textureNative) return !i.graphics.context.isTexture(i.textureNative)
} }
func (i *Image) Dispose() { func (i *Image) Dispose() {
if !i.pbo.equal(*new(buffer)) { if !i.pbo.equal(*new(buffer)) {
i.driver.context.deleteBuffer(i.pbo) i.graphics.context.deleteBuffer(i.pbo)
} }
if i.framebuffer != nil { if i.framebuffer != nil {
i.framebuffer.delete(&i.driver.context) i.framebuffer.delete(&i.graphics.context)
} }
if !i.textureNative.equal(*new(textureNative)) { if !i.textureNative.equal(*new(textureNative)) {
i.driver.context.deleteTexture(i.textureNative) i.graphics.context.deleteTexture(i.textureNative)
} }
} }
func (i *Image) SetAsDestination() { func (i *Image) SetAsDestination() {
i.driver.state.destination = i i.graphics.state.destination = i
} }
func (i *Image) setViewport() error { func (i *Image) setViewport() error {
if err := i.ensureFramebuffer(); err != nil { if err := i.ensureFramebuffer(); err != nil {
return err return err
} }
i.driver.context.setViewport(i.framebuffer) i.graphics.context.setViewport(i.framebuffer)
return nil return nil
} }
@ -61,7 +61,7 @@ func (i *Image) Pixels() ([]byte, error) {
if err := i.ensureFramebuffer(); err != nil { if err := i.ensureFramebuffer(); err != nil {
return nil, err return nil, err
} }
p, err := i.driver.context.framebufferPixels(i.framebuffer, i.width, i.height) p, err := i.graphics.context.framebufferPixels(i.framebuffer, i.width, i.height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -77,12 +77,12 @@ func (i *Image) ensureFramebuffer() error {
// The (default) framebuffer size can't be converted to a power of 2. // The (default) framebuffer size can't be converted to a power of 2.
// On browsers, c.width and c.height are used as viewport size and // On browsers, c.width and c.height are used as viewport size and
// Edge can't treat a bigger viewport than the drawing area (#71). // Edge can't treat a bigger viewport than the drawing area (#71).
i.framebuffer = newScreenFramebuffer(&i.driver.context, i.width, i.height) i.framebuffer = newScreenFramebuffer(&i.graphics.context, i.width, i.height)
return nil return nil
} }
w, h := graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height) w, h := graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
f, err := newFramebufferFromTexture(&i.driver.context, i.textureNative, w, h) f, err := newFramebufferFromTexture(&i.graphics.context, i.textureNative, w, h)
if err != nil { if err != nil {
return err return err
} }
@ -100,26 +100,26 @@ func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
// glFlush is necessary on Android. // glFlush is necessary on Android.
// glTexSubImage2D didn't work without this hack at least on Nexus 5x and NuAns NEO [Reloaded] (#211). // glTexSubImage2D didn't work without this hack at least on Nexus 5x and NuAns NEO [Reloaded] (#211).
if i.driver.drawCalled { if i.graphics.drawCalled {
i.driver.context.flush() i.graphics.context.flush()
} }
i.driver.drawCalled = false i.graphics.drawCalled = false
w, h := i.width, i.height w, h := i.width, i.height
if !i.driver.context.canUsePBO() { if !i.graphics.context.canUsePBO() {
i.driver.context.texSubImage2D(i.textureNative, w, h, args) i.graphics.context.texSubImage2D(i.textureNative, w, h, args)
return return
} }
if i.pbo.equal(*new(buffer)) { if i.pbo.equal(*new(buffer)) {
i.pbo = i.driver.context.newPixelBufferObject(w, h) i.pbo = i.graphics.context.newPixelBufferObject(w, h)
} }
if i.pbo.equal(*new(buffer)) { if i.pbo.equal(*new(buffer)) {
panic("opengl: newPixelBufferObject failed") panic("opengl: newPixelBufferObject failed")
} }
i.driver.context.replacePixelsWithPBO(i.pbo, i.textureNative, w, h, args) i.graphics.context.replacePixelsWithPBO(i.pbo, i.textureNative, w, h, args)
} }
func (i *Image) SetAsSource() { func (i *Image) SetAsSource() {
i.driver.state.source = i i.graphics.state.source = i
} }

View File

@ -255,12 +255,12 @@ func areSameFloat32Array(a, b []float32) bool {
} }
// useProgram uses the program (programTexture). // useProgram uses the program (programTexture).
func (d *Driver) useProgram(mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error { func (g *Graphics) useProgram(mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error {
destination := d.state.destination destination := g.state.destination
if destination == nil { if destination == nil {
panic("destination image is not set") panic("destination image is not set")
} }
source := d.state.source source := g.state.source
if source == nil { if source == nil {
panic("source image is not set") panic("source image is not set")
} }
@ -271,73 +271,73 @@ func (d *Driver) useProgram(mode driver.CompositeMode, colorM *affine.ColorM, fi
dstW := destination.width dstW := destination.width
srcW, srcH := source.width, source.height srcW, srcH := source.width, source.height
d.context.blendFunc(mode) g.context.blendFunc(mode)
program := d.state.programs[programKey{ program := g.state.programs[programKey{
useColorM: colorM != nil, useColorM: colorM != nil,
filter: filter, filter: filter,
address: address, address: address,
}] }]
if !d.state.lastProgram.equal(program) { if !g.state.lastProgram.equal(program) {
d.context.useProgram(program) g.context.useProgram(program)
if d.state.lastProgram.equal(zeroProgram) { if g.state.lastProgram.equal(zeroProgram) {
theArrayBufferLayout.enable(&d.context, program) theArrayBufferLayout.enable(&g.context, program)
d.context.bindBuffer(arrayBuffer, d.state.arrayBuffer) g.context.bindBuffer(arrayBuffer, g.state.arrayBuffer)
d.context.bindBuffer(elementArrayBuffer, d.state.elementArrayBuffer) g.context.bindBuffer(elementArrayBuffer, g.state.elementArrayBuffer)
d.context.uniformInt(program, "texture", 0) g.context.uniformInt(program, "texture", 0)
} }
d.state.lastProgram = program g.state.lastProgram = program
d.state.lastViewportWidth = 0 g.state.lastViewportWidth = 0
d.state.lastViewportHeight = 0 g.state.lastViewportHeight = 0
d.state.lastColorMatrix = nil g.state.lastColorMatrix = nil
d.state.lastColorMatrixTranslation = nil g.state.lastColorMatrixTranslation = nil
d.state.lastSourceWidth = 0 g.state.lastSourceWidth = 0
d.state.lastSourceHeight = 0 g.state.lastSourceHeight = 0
} }
vw := destination.framebuffer.width vw := destination.framebuffer.width
vh := destination.framebuffer.height vh := destination.framebuffer.height
if d.state.lastViewportWidth != vw || d.state.lastViewportHeight != vh { if g.state.lastViewportWidth != vw || g.state.lastViewportHeight != vh {
d.context.uniformFloats(program, "viewport_size", []float32{float32(vw), float32(vh)}) g.context.uniformFloats(program, "viewport_size", []float32{float32(vw), float32(vh)})
d.state.lastViewportWidth = vw g.state.lastViewportWidth = vw
d.state.lastViewportHeight = vh g.state.lastViewportHeight = vh
} }
if colorM != nil { if colorM != nil {
esBody, esTranslate := colorM.UnsafeElements() esBody, esTranslate := colorM.UnsafeElements()
if !areSameFloat32Array(d.state.lastColorMatrix, esBody) { if !areSameFloat32Array(g.state.lastColorMatrix, esBody) {
d.context.uniformFloats(program, "color_matrix_body", esBody) g.context.uniformFloats(program, "color_matrix_body", esBody)
// ColorM's elements are immutable. It's OK to hold the reference without copying. // ColorM's elements are immutable. It's OK to hold the reference without copying.
d.state.lastColorMatrix = esBody g.state.lastColorMatrix = esBody
} }
if !areSameFloat32Array(d.state.lastColorMatrixTranslation, esTranslate) { if !areSameFloat32Array(g.state.lastColorMatrixTranslation, esTranslate) {
d.context.uniformFloats(program, "color_matrix_translation", esTranslate) g.context.uniformFloats(program, "color_matrix_translation", esTranslate)
// ColorM's elements are immutable. It's OK to hold the reference without copying. // ColorM's elements are immutable. It's OK to hold the reference without copying.
d.state.lastColorMatrixTranslation = esTranslate g.state.lastColorMatrixTranslation = esTranslate
} }
} }
if filter != driver.FilterNearest { if filter != driver.FilterNearest {
sw := graphics.InternalImageSize(srcW) sw := graphics.InternalImageSize(srcW)
sh := graphics.InternalImageSize(srcH) sh := graphics.InternalImageSize(srcH)
if d.state.lastSourceWidth != sw || d.state.lastSourceHeight != sh { if g.state.lastSourceWidth != sw || g.state.lastSourceHeight != sh {
d.context.uniformFloats(program, "source_size", []float32{float32(sw), float32(sh)}) g.context.uniformFloats(program, "source_size", []float32{float32(sw), float32(sh)})
d.state.lastSourceWidth = sw g.state.lastSourceWidth = sw
d.state.lastSourceHeight = sh g.state.lastSourceHeight = sh
} }
} }
if filter == driver.FilterScreen { if filter == driver.FilterScreen {
scale := float32(dstW) / float32(srcW) scale := float32(dstW) / float32(srcW)
d.context.uniformFloat(program, "scale", scale) g.context.uniformFloat(program, "scale", scale)
} }
// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture // We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml // See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
d.context.bindTexture(source.textureNative) g.context.bindTexture(source.textureNative)
d.state.source = nil g.state.source = nil
d.state.destination = nil g.state.destination = nil
return nil return nil
} }

View File

@ -290,7 +290,7 @@ func (u *UserInterface) run(context driver.UIContext, mainloop bool) (err error)
} else { } else {
ctx, u.glWorker = gl.NewContext() ctx, u.glWorker = gl.NewContext()
} }
u.Graphics().(*opengl.Driver).SetMobileGLContext(ctx) u.Graphics().(*opengl.Graphics).SetMobileGLContext(ctx)
} else { } else {
u.t = thread.New() u.t = thread.New()
u.Graphics().SetThread(u.t) u.Graphics().SetThread(u.t)