From ed961505d241e10b4cc8ffc1b0789e03afbcb5ad Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 6 Nov 2018 03:44:43 +0900 Subject: [PATCH] opengl: Refactoring: Hide projection matrix inside opengl package --- internal/graphicscommand/command.go | 18 ++++++--------- internal/opengl/image.go | 12 ++++++++-- internal/opengl/program.go | 34 ++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index 54ccf2688..c77edae21 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -227,20 +227,16 @@ func (c *drawImageCommand) String() string { // Exec executes the drawImageCommand. func (c *drawImageCommand) Exec(indexOffsetInBytes int) error { - // On some environments, viewport size must be within the framebuffer size. - // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). - // Use the same size of the framebuffer here. - if err := c.dst.image.SetViewport(); err != nil { - return err - } - + // TODO: Is it ok not to bind any framebuffer here? if c.nindices == 0 { return nil } - proj := c.dst.image.ProjectionMatrix() - dw, dh := c.dst.Size() - sw, sh := c.src.Size() - opengl.UseProgram(c.mode, proj, c.src.image, dw, dh, sw, sh, c.color, c.filter) + + c.dst.image.SetAsDestination() + c.src.image.SetAsSource() + if err := opengl.UseProgram(c.mode, c.color, c.filter); err != nil { + return err + } opengl.GetContext().DrawElements(c.nindices, indexOffsetInBytes) // glFlush() might be necessary at least on MacBook Pro (a smilar problem at #419), diff --git a/internal/opengl/image.go b/internal/opengl/image.go index 5a77aaf06..0995e5662 100644 --- a/internal/opengl/image.go +++ b/internal/opengl/image.go @@ -85,7 +85,11 @@ func (i *Image) Delete() { } } -func (i *Image) SetViewport() error { +func (i *Image) SetAsDestination() { + theOpenGLState.destination = i +} + +func (i *Image) setViewport() error { if err := i.ensureFramebuffer(); err != nil { return err } @@ -104,7 +108,7 @@ func (i *Image) Pixels() ([]byte, error) { return p, nil } -func (i *Image) ProjectionMatrix() []float32 { +func (i *Image) projectionMatrix() []float32 { if i.framebuffer == nil { panic("not reached") } @@ -127,3 +131,7 @@ func (i *Image) ensureFramebuffer() error { func (i *Image) TexSubImage2D(p []byte, x, y, width, height int) { theContext.texSubImage2D(i.textureNative, p, x, y, width, height) } + +func (i *Image) SetAsSource() { + theOpenGLState.source = i +} diff --git a/internal/opengl/program.go b/internal/opengl/program.go index f6b0c02a1..6463f254f 100644 --- a/internal/opengl/program.go +++ b/internal/opengl/program.go @@ -130,6 +130,9 @@ type openGLState struct { lastColorMatrixTranslation []float32 lastSourceWidth int lastSourceHeight int + + source *Image + destination *Image } var ( @@ -265,15 +268,40 @@ func BufferSubData(vertices []float32, indices []uint16) { c.elementArrayBufferSubData(indices) } -func UseProgram(mode graphics.CompositeMode, proj []float32, src *Image, dstW, dstH, srcW, srcH int, colorM *affine.ColorM, filter graphics.Filter) { +func UseProgram(mode graphics.CompositeMode, colorM *affine.ColorM, filter graphics.Filter) error { + destination := theOpenGLState.destination + if destination == nil { + panic("destination image is not set") + } + source := theOpenGLState.source + if source == nil { + panic("source image is not set") + } + + // On some environments, viewport size must be within the framebuffer size. + // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). + // Use the same size of the framebuffer here. + if err := destination.setViewport(); err != nil { + return err + } + proj := destination.projectionMatrix() + dw, dh := destination.width, destination.height + sw, sh := source.width, source.height + GetContext().blendFunc(mode) - theOpenGLState.useProgram(proj, src.textureNative, dstW, dstH, srcW, srcH, colorM, filter) + theOpenGLState.useProgram(proj, dw, dh, sw, sh, colorM, filter) + + theOpenGLState.source = nil + theOpenGLState.destination = nil + return nil } // useProgram uses the program (programTexture). -func (s *openGLState) useProgram(proj []float32, texture textureNative, dstW, dstH, srcW, srcH int, colorM *affine.ColorM, filter graphics.Filter) { +func (s *openGLState) useProgram(proj []float32, dstW, dstH, srcW, srcH int, colorM *affine.ColorM, filter graphics.Filter) { c := GetContext() + texture := theOpenGLState.source.textureNative + var program program switch filter { case graphics.FilterNearest: