mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
shader: Use the fixed number of images for shaders
This changes uses arrays rather than slices in order to avoid heap allocations. Updates #1193
This commit is contained in:
parent
0c13fff62a
commit
e0d5763a60
@ -78,7 +78,7 @@ func (g *Game) Update(screen *ebiten.Image) error {
|
|||||||
g.shaders = map[int]*ebiten.Shader{}
|
g.shaders = map[int]*ebiten.Shader{}
|
||||||
}
|
}
|
||||||
if _, ok := g.shaders[g.idx]; !ok {
|
if _, ok := g.shaders[g.idx]; !ok {
|
||||||
s, err := ebiten.NewShader([]byte(shaderSrcs[g.idx]), 1)
|
s, err := ebiten.NewShader([]byte(shaderSrcs[g.idx]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
[]float32{float32(cx), float32(cy)}, // Cursor
|
[]float32{float32(cx), float32(cy)}, // Cursor
|
||||||
}
|
}
|
||||||
if g.idx != 0 {
|
if g.idx != 0 {
|
||||||
op.Images = append(op.Images, gophersImage)
|
op.Images[0] = gophersImage
|
||||||
}
|
}
|
||||||
screen.DrawTrianglesWithShader(vs, is, s, op)
|
screen.DrawTrianglesWithShader(vs, is, s, op)
|
||||||
|
|
||||||
|
25
image.go
25
image.go
@ -15,6 +15,7 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
@ -205,7 +206,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
|
|||||||
sy1 := float32(bounds.Max.Y)
|
sy1 := float32(bounds.Max.Y)
|
||||||
vs := graphics.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, 1, 1, 1, 1, filter == driver.FilterScreen)
|
vs := graphics.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, 1, 1, 1, 1, filter == driver.FilterScreen)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
i.buffered.DrawTriangles(img.buffered, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
i.buffered.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{img.buffered}, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,15 +343,22 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.buffered.DrawTriangles(img.buffered, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, nil, nil, nil)
|
i.buffered.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{img.buffered}, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DrawTrianglesWithShaderOptions struct {
|
type DrawTrianglesWithShaderOptions struct {
|
||||||
Uniforms []interface{}
|
Uniforms []interface{}
|
||||||
Images []*Image
|
Images [4]*Image
|
||||||
CompositeMode CompositeMode
|
CompositeMode CompositeMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var op DrawTrianglesWithShaderOptions
|
||||||
|
if got, want := len(op.Images), graphics.ShaderImageNum; got != want {
|
||||||
|
panic(fmt.Sprintf("ebiten: len((DrawTrianglesWithShaderOptions{}).Images) must be %d but %d", want, got))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Add comments and tests
|
// TODO: Add comments and tests
|
||||||
func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesWithShaderOptions) {
|
func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesWithShaderOptions) {
|
||||||
i.copyCheck()
|
i.copyCheck()
|
||||||
@ -381,8 +389,11 @@ func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, sha
|
|||||||
us := append([]interface{}{[]float32{0, 0}}, options.Uniforms...)
|
us := append([]interface{}{[]float32{0, 0}}, options.Uniforms...)
|
||||||
|
|
||||||
var imgw, imgh int
|
var imgw, imgh int
|
||||||
var imgs []*buffered.Image
|
var imgs [graphics.ShaderImageNum]*buffered.Image
|
||||||
for _, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if img.isDisposed() {
|
if img.isDisposed() {
|
||||||
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
||||||
}
|
}
|
||||||
@ -391,7 +402,7 @@ func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, sha
|
|||||||
} else if w, h := img.Size(); imgw != w || imgh != h {
|
} else if w, h := img.Size(); imgw != w || imgh != h {
|
||||||
panic("ebiten: all the source images must be the same size")
|
panic("ebiten: all the source images must be the same size")
|
||||||
}
|
}
|
||||||
imgs = append(imgs, img.buffered)
|
imgs[i] = img.buffered
|
||||||
}
|
}
|
||||||
|
|
||||||
vs := make([]float32, len(vertices)*graphics.VertexFloatNum)
|
vs := make([]float32, len(vertices)*graphics.VertexFloatNum)
|
||||||
@ -408,7 +419,7 @@ func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, sha
|
|||||||
is := make([]uint16, len(indices))
|
is := make([]uint16, len(indices))
|
||||||
copy(is, indices)
|
copy(is, indices)
|
||||||
|
|
||||||
i.buffered.DrawTriangles(nil, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, us, imgs)
|
i.buffered.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, us)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubImage returns an image representing the portion of the image p visible through r.
|
// SubImage returns an image representing the portion of the image p visible through r.
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/mipmap"
|
"github.com/hajimehoshi/ebiten/internal/mipmap"
|
||||||
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
||||||
)
|
)
|
||||||
@ -235,13 +236,8 @@ func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) {
|
|||||||
// DrawTriangles draws the src image with the given vertices.
|
// DrawTriangles draws the src image with the given vertices.
|
||||||
//
|
//
|
||||||
// Copying vertices and indices is the caller's responsibility.
|
// Copying vertices and indices is the caller's responsibility.
|
||||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if src != nil {
|
for _, src := range srcs {
|
||||||
if i == src {
|
|
||||||
panic("buffered: Image.DrawTriangles: src must be different from the receiver")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, src := range images {
|
|
||||||
if i == src {
|
if i == src {
|
||||||
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
||||||
}
|
}
|
||||||
@ -250,17 +246,17 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16,
|
|||||||
if maybeCanAddDelayedCommand() {
|
if maybeCanAddDelayedCommand() {
|
||||||
if tryAddDelayedCommand(func() error {
|
if tryAddDelayedCommand(func() error {
|
||||||
// Arguments are not copied. Copying is the caller's responsibility.
|
// Arguments are not copied. Copying is the caller's responsibility.
|
||||||
i.DrawTriangles(src, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms, images)
|
i.DrawTriangles(srcs, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms)
|
||||||
return nil
|
return nil
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if src != nil {
|
for _, src := range srcs {
|
||||||
src.resolvePendingPixels(true)
|
if src == nil {
|
||||||
}
|
continue
|
||||||
for _, src := range images {
|
}
|
||||||
src.resolvePendingPixels(true)
|
src.resolvePendingPixels(true)
|
||||||
}
|
}
|
||||||
i.resolvePendingPixels(false)
|
i.resolvePendingPixels(false)
|
||||||
@ -270,17 +266,15 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16,
|
|||||||
s = shader.shader
|
s = shader.shader
|
||||||
}
|
}
|
||||||
|
|
||||||
var srcImg *mipmap.Mipmap
|
var imgs [graphics.ShaderImageNum]*mipmap.Mipmap
|
||||||
if src != nil {
|
for i, img := range srcs {
|
||||||
srcImg = src.img
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
imgs[i] = img.img
|
||||||
}
|
}
|
||||||
|
|
||||||
var imgs []*mipmap.Mipmap
|
i.img.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||||
for _, img := range images {
|
|
||||||
imgs = append(imgs, img.img)
|
|
||||||
}
|
|
||||||
|
|
||||||
i.img.DrawTriangles(srcImg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, imgs)
|
|
||||||
i.invalidatePendingPixels()
|
i.invalidatePendingPixels()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
||||||
"github.com/hajimehoshi/ebiten/internal/thread"
|
"github.com/hajimehoshi/ebiten/internal/thread"
|
||||||
)
|
)
|
||||||
@ -44,6 +45,7 @@ type Graphics interface {
|
|||||||
IsGL() bool
|
IsGL() bool
|
||||||
HasHighPrecisionFloat() bool
|
HasHighPrecisionFloat() bool
|
||||||
MaxImageSize() int
|
MaxImageSize() int
|
||||||
|
InvalidImageID() ImageID
|
||||||
|
|
||||||
NewShader(program *shaderir.Program) (Shader, error)
|
NewShader(program *shaderir.Program) (Shader, error)
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ type Graphics interface {
|
|||||||
//
|
//
|
||||||
// * float32
|
// * float32
|
||||||
// * []float32
|
// * []float32
|
||||||
DrawShader(dst ImageID, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, uniforms []interface{}, srcs []ImageID) error
|
DrawShader(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, uniforms []interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||||
|
@ -18,6 +18,8 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/web"
|
"github.com/hajimehoshi/ebiten/internal/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ShaderImageNum = 4
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles.
|
IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles.
|
||||||
VertexFloatNum = 8
|
VertexFloatNum = 8
|
||||||
|
@ -17,6 +17,7 @@ package graphicscommand
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
@ -65,7 +66,7 @@ type command interface {
|
|||||||
NumIndices() int
|
NumIndices() int
|
||||||
AddNumVertices(n int)
|
AddNumVertices(n int)
|
||||||
AddNumIndices(n int)
|
AddNumIndices(n int)
|
||||||
CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool
|
CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type size struct {
|
type size struct {
|
||||||
@ -143,7 +144,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if len(indices) > graphics.IndicesNum {
|
if len(indices) > graphics.IndicesNum {
|
||||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
||||||
}
|
}
|
||||||
@ -155,28 +156,30 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []f
|
|||||||
split = true
|
split = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if src != nil {
|
// Assume that all the image sizes are same.
|
||||||
q.appendVertices(vertices, src)
|
var firstSrc *Image
|
||||||
} else if len(images) > 0 {
|
for _, src := range srcs {
|
||||||
q.appendVertices(vertices, images[0])
|
if src != nil {
|
||||||
} else {
|
firstSrc = src
|
||||||
q.appendVertices(vertices, nil)
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
q.appendVertices(vertices, firstSrc)
|
||||||
q.appendIndices(indices, uint16(q.nextIndex))
|
q.appendIndices(indices, uint16(q.nextIndex))
|
||||||
q.nextIndex += len(vertices) / graphics.VertexFloatNum
|
q.nextIndex += len(vertices) / graphics.VertexFloatNum
|
||||||
q.tmpNumIndices += len(indices)
|
q.tmpNumIndices += len(indices)
|
||||||
|
|
||||||
// TODO: If dst is the screen, reorder the command to be the last.
|
// TODO: If dst is the screen, reorder the command to be the last.
|
||||||
if !split && 0 < len(q.commands) {
|
if !split && 0 < len(q.commands) {
|
||||||
if last := q.commands[len(q.commands)-1]; last.CanMergeWithDrawTrianglesCommand(dst, src, color, mode, filter, address, sourceRegion, shader) {
|
if last := q.commands[len(q.commands)-1]; last.CanMergeWithDrawTrianglesCommand(dst, srcs, color, mode, filter, address, sourceRegion, shader) {
|
||||||
last.AddNumVertices(len(vertices))
|
last.AddNumVertices(len(vertices))
|
||||||
last.AddNumIndices(len(indices))
|
last.AddNumIndices(len(indices))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if address != driver.AddressUnsafe {
|
if firstSrc != nil && address != driver.AddressUnsafe {
|
||||||
w, h := src.InternalSize()
|
w, h := firstSrc.InternalSize()
|
||||||
sourceRegion.X /= float32(w)
|
sourceRegion.X /= float32(w)
|
||||||
sourceRegion.Y /= float32(h)
|
sourceRegion.Y /= float32(h)
|
||||||
sourceRegion.Width /= float32(w)
|
sourceRegion.Width /= float32(w)
|
||||||
@ -185,7 +188,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []f
|
|||||||
|
|
||||||
c := &drawTrianglesCommand{
|
c := &drawTrianglesCommand{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
src: src,
|
srcs: srcs,
|
||||||
nvertices: len(vertices),
|
nvertices: len(vertices),
|
||||||
nindices: len(indices),
|
nindices: len(indices),
|
||||||
color: color,
|
color: color,
|
||||||
@ -195,7 +198,6 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []f
|
|||||||
sourceRegion: sourceRegion,
|
sourceRegion: sourceRegion,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
uniforms: uniforms,
|
uniforms: uniforms,
|
||||||
images: images,
|
|
||||||
}
|
}
|
||||||
q.commands = append(q.commands, c)
|
q.commands = append(q.commands, c)
|
||||||
}
|
}
|
||||||
@ -312,7 +314,7 @@ func FlushCommands() error {
|
|||||||
// drawTrianglesCommand represents a drawing command to draw an image on another image.
|
// drawTrianglesCommand represents a drawing command to draw an image on another image.
|
||||||
type drawTrianglesCommand struct {
|
type drawTrianglesCommand struct {
|
||||||
dst *Image
|
dst *Image
|
||||||
src *Image
|
srcs [graphics.ShaderImageNum]*Image
|
||||||
nvertices int
|
nvertices int
|
||||||
nindices int
|
nindices int
|
||||||
color *affine.ColorM
|
color *affine.ColorM
|
||||||
@ -322,7 +324,6 @@ type drawTrianglesCommand struct {
|
|||||||
sourceRegion driver.Region
|
sourceRegion driver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
uniforms []interface{}
|
uniforms []interface{}
|
||||||
images []*Image
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *drawTrianglesCommand) String() string {
|
func (c *drawTrianglesCommand) String() string {
|
||||||
@ -391,12 +392,19 @@ func (c *drawTrianglesCommand) String() string {
|
|||||||
panic(fmt.Sprintf("graphicscommand: invalid address: %d", c.address))
|
panic(fmt.Sprintf("graphicscommand: invalid address: %d", c.address))
|
||||||
}
|
}
|
||||||
|
|
||||||
src := fmt.Sprintf("%d", c.src.id)
|
var srcstrs [graphics.ShaderImageNum]string
|
||||||
if c.src.screen {
|
for i, src := range c.srcs {
|
||||||
src += " (screen)"
|
if src == nil {
|
||||||
|
srcstrs[i] = "(nil)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
srcstrs[i] = fmt.Sprintf("%d", src.id)
|
||||||
|
if src.screen {
|
||||||
|
srcstrs[i] += " (screen)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("draw-triangles: dst: %s <- src: %s, num of indices: %d, colorm: %v, mode %s, filter: %s, address: %s", dst, src, c.nindices, c.color, mode, filter, address)
|
return fmt.Sprintf("draw-triangles: dst: %s <- src: [%s], num of indices: %d, colorm: %v, mode %s, filter: %s, address: %s", dst, strings.Join(srcstrs[:], ", "), c.nindices, c.color, mode, filter, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the drawTrianglesCommand.
|
// Exec executes the drawTrianglesCommand.
|
||||||
@ -407,9 +415,13 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.shader != nil {
|
if c.shader != nil {
|
||||||
var imgs []driver.ImageID
|
var imgs [graphics.ShaderImageNum]driver.ImageID
|
||||||
for _, img := range c.images {
|
for i, src := range c.srcs {
|
||||||
imgs = append(imgs, img.image.ID())
|
if src == nil {
|
||||||
|
imgs[i] = theGraphicsDriver.InvalidImageID()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
imgs[i] = src.image.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The last uniform variables are added at /shader.go and represents a viewport size.
|
// The last uniform variables are added at /shader.go and represents a viewport size.
|
||||||
@ -418,9 +430,9 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
|||||||
viewport[0] = float32(w)
|
viewport[0] = float32(w)
|
||||||
viewport[1] = float32(h)
|
viewport[1] = float32(h)
|
||||||
|
|
||||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), c.shader.shader.ID(), c.nindices, indexOffset, c.mode, c.uniforms, imgs)
|
return theGraphicsDriver.DrawShader(c.dst.image.ID(), imgs, c.shader.shader.ID(), c.nindices, indexOffset, c.mode, c.uniforms)
|
||||||
}
|
}
|
||||||
return theGraphicsDriver.Draw(c.dst.image.ID(), c.src.image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.sourceRegion)
|
return theGraphicsDriver.Draw(c.dst.image.ID(), c.srcs[0].image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.sourceRegion)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *drawTrianglesCommand) NumVertices() int {
|
func (c *drawTrianglesCommand) NumVertices() int {
|
||||||
@ -441,7 +453,7 @@ func (c *drawTrianglesCommand) AddNumIndices(n int) {
|
|||||||
|
|
||||||
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
||||||
// with the drawTrianglesCommand c.
|
// with the drawTrianglesCommand c.
|
||||||
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
// If a shader is used, commands are not merged.
|
// If a shader is used, commands are not merged.
|
||||||
//
|
//
|
||||||
// TODO: Merge shader commands considering uniform variables.
|
// TODO: Merge shader commands considering uniform variables.
|
||||||
@ -451,7 +463,7 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image,
|
|||||||
if c.dst != dst {
|
if c.dst != dst {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if c.src != src {
|
if c.srcs != srcs {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !c.color.Equals(color) {
|
if !c.color.Equals(color) {
|
||||||
@ -502,7 +514,7 @@ func (c *replacePixelsCommand) AddNumVertices(n int) {
|
|||||||
func (c *replacePixelsCommand) AddNumIndices(n int) {
|
func (c *replacePixelsCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *replacePixelsCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *replacePixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +551,7 @@ func (c *pixelsCommand) AddNumVertices(n int) {
|
|||||||
func (c *pixelsCommand) AddNumIndices(n int) {
|
func (c *pixelsCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *pixelsCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *pixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,7 +584,7 @@ func (c *disposeImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *disposeImageCommand) AddNumIndices(n int) {
|
func (c *disposeImageCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *disposeImageCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *disposeImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +617,7 @@ func (c *disposeShaderCommand) AddNumVertices(n int) {
|
|||||||
func (c *disposeShaderCommand) AddNumIndices(n int) {
|
func (c *disposeShaderCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *disposeShaderCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *disposeShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +656,7 @@ func (c *newImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *newImageCommand) AddNumIndices(n int) {
|
func (c *newImageCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *newImageCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *newImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,7 +692,7 @@ func (c *newScreenFramebufferImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *newScreenFramebufferImageCommand) AddNumIndices(n int) {
|
func (c *newScreenFramebufferImageCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *newScreenFramebufferImageCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *newScreenFramebufferImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +727,7 @@ func (c *newShaderCommand) AddNumVertices(n int) {
|
|||||||
func (c *newShaderCommand) AddNumIndices(n int) {
|
func (c *newShaderCommand) AddNumIndices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *newShaderCommand) CanMergeWithDrawTrianglesCommand(dst, src *Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
func (c *newShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,13 +126,6 @@ func (i *Image) InternalSize() (int, int) {
|
|||||||
return i.internalWidth, i.internalHeight
|
return i.internalWidth, i.internalHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func processSrc(src *Image) {
|
|
||||||
if src.screen {
|
|
||||||
panic("graphicscommand: the screen image cannot be the rendering source")
|
|
||||||
}
|
|
||||||
src.resolveBufferedReplacePixels()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DrawTriangles draws triangles with the given image.
|
// DrawTriangles draws triangles with the given image.
|
||||||
//
|
//
|
||||||
// The vertex floats are:
|
// The vertex floats are:
|
||||||
@ -154,22 +147,25 @@ func processSrc(src *Image) {
|
|||||||
//
|
//
|
||||||
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
||||||
// elements for the source image are not used.
|
// elements for the source image are not used.
|
||||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if i.lastCommand == lastCommandNone {
|
if i.lastCommand == lastCommandNone {
|
||||||
if !i.screen && mode != driver.CompositeModeClear {
|
if !i.screen && mode != driver.CompositeModeClear {
|
||||||
panic("graphicscommand: the image must be cleared first")
|
panic("graphicscommand: the image must be cleared first")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if src != nil {
|
for _, src := range srcs {
|
||||||
processSrc(src)
|
if src == nil {
|
||||||
}
|
continue
|
||||||
for _, src := range images {
|
}
|
||||||
processSrc(src)
|
if src.screen {
|
||||||
|
panic("graphicscommand: the screen image cannot be the rendering source")
|
||||||
|
}
|
||||||
|
src.resolveBufferedReplacePixels()
|
||||||
}
|
}
|
||||||
i.resolveBufferedReplacePixels()
|
i.resolveBufferedReplacePixels()
|
||||||
|
|
||||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, src, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms, images)
|
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms)
|
||||||
|
|
||||||
if i.lastCommand == lastCommandNone && !i.screen {
|
if i.lastCommand == lastCommandNone && !i.screen {
|
||||||
i.lastCommand = lastCommandClear
|
i.lastCommand = lastCommandClear
|
||||||
|
@ -44,7 +44,7 @@ func TestClear(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w/2, h/2)
|
vs := quadVertices(w/2, h/2)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
pix, err := dst.Pixels()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -74,8 +74,8 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
|||||||
dst := NewImage(w, h)
|
dst := NewImage(w, h)
|
||||||
vs := quadVertices(w/2, h/2)
|
vs := quadVertices(w/2, h/2)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,14 +89,14 @@ func TestShader(t *testing.T) {
|
|||||||
dst := NewImage(w, h)
|
dst := NewImage(w, h)
|
||||||
vs := quadVertices(w, h)
|
vs := quadVertices(w, h)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
s := NewShader(&ir)
|
||||||
us := []interface{}{
|
us := []interface{}{
|
||||||
[]float32{0, 0},
|
[]float32{0, 0},
|
||||||
}
|
}
|
||||||
dst.DrawTriangles(nil, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||||
|
|
||||||
pix, err := dst.Pixels()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -432,6 +432,10 @@ func (g *Graphics) genNextImageID() driver.ImageID {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Graphics) InvalidImageID() driver.ImageID {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Graphics) NewImage(width, height int) (driver.Image, error) {
|
func (g *Graphics) NewImage(width, height int) (driver.Image, error) {
|
||||||
g.checkSize(width, height)
|
g.checkSize(width, height)
|
||||||
td := mtl.TextureDescriptor{
|
td := mtl.TextureDescriptor{
|
||||||
@ -796,7 +800,7 @@ func (g *Graphics) NewShader(program *shaderir.Program) (driver.Shader, error) {
|
|||||||
panic("metal: NewShader is not implemented")
|
panic("metal: NewShader is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}, srcs []driver.ImageID) error {
|
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||||
panic("metal: DrawShader is not implemented")
|
panic("metal: DrawShader is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,10 @@ func (g *Graphics) genNextImageID() driver.ImageID {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Graphics) InvalidImageID() driver.ImageID {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Graphics) genNextShaderID() driver.ShaderID {
|
func (g *Graphics) genNextShaderID() driver.ShaderID {
|
||||||
id := g.nextShaderID
|
id := g.nextShaderID
|
||||||
g.nextShaderID++
|
g.nextShaderID++
|
||||||
@ -215,7 +219,15 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.useProgram(program, uniforms, []textureNative{source.textureNative}); err != nil {
|
var imgs [graphics.ShaderImageNum]textureVariable
|
||||||
|
for i := range imgs {
|
||||||
|
if i == 0 {
|
||||||
|
imgs[i].valid = true
|
||||||
|
imgs[i].native = source.textureNative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.useProgram(program, uniforms, imgs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +287,7 @@ func (g *Graphics) removeShader(shader *Shader) {
|
|||||||
delete(g.shaders, shader.id)
|
delete(g.shaders, shader.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}, srcs []driver.ImageID) error {
|
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||||
d := g.images[dst]
|
d := g.images[dst]
|
||||||
s := g.shaders[shader]
|
s := g.shaders[shader]
|
||||||
|
|
||||||
@ -292,9 +304,13 @@ func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexL
|
|||||||
us[k].value = v
|
us[k].value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
ts := make([]textureNative, len(srcs))
|
var ts [graphics.ShaderImageNum]textureVariable
|
||||||
for k, v := range srcs {
|
for i, src := range srcs {
|
||||||
ts[k] = g.images[v].textureNative
|
if src == g.InvalidImageID() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ts[i].valid = true
|
||||||
|
ts[i].native = g.images[src].textureNative
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.useProgram(s.p, us, ts); err != nil {
|
if err := g.useProgram(s.p, us, ts); err != nil {
|
||||||
|
@ -239,8 +239,13 @@ type uniformVariable struct {
|
|||||||
value interface{}
|
value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type textureVariable struct {
|
||||||
|
valid bool
|
||||||
|
native textureNative
|
||||||
|
}
|
||||||
|
|
||||||
// useProgram uses the program (programTexture).
|
// useProgram uses the program (programTexture).
|
||||||
func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures []textureNative) error {
|
func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures [graphics.ShaderImageNum]textureVariable) error {
|
||||||
if !g.state.lastProgram.equal(program) {
|
if !g.state.lastProgram.equal(program) {
|
||||||
g.context.useProgram(program)
|
g.context.useProgram(program)
|
||||||
if g.state.lastProgram.equal(zeroProgram) {
|
if g.state.lastProgram.equal(zeroProgram) {
|
||||||
@ -278,13 +283,16 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, t := range textures {
|
for i, t := range textures {
|
||||||
|
if !t.valid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
g.context.uniformInt(program, fmt.Sprintf("T%d", i), i)
|
g.context.uniformInt(program, fmt.Sprintf("T%d", i), i)
|
||||||
if g.state.lastActiveTexture != i {
|
if g.state.lastActiveTexture != i {
|
||||||
g.context.activeTexture(i)
|
g.context.activeTexture(i)
|
||||||
g.state.lastActiveTexture = i
|
g.state.lastActiveTexture = i
|
||||||
}
|
}
|
||||||
// Apparently, a texture must be bound every time. The cache is not used here.
|
// Apparently, a texture must be bound every time. The cache is not used here.
|
||||||
g.context.bindTexture(t)
|
g.context.bindTexture(t.native)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -87,9 +87,10 @@ func (m *Mipmap) Pixels(x, y, width, height int) ([]byte, error) {
|
|||||||
return m.orig.Pixels(x, y, width, height)
|
return m.orig.Pixels(x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Mipmap) {
|
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
level := 0
|
level := 0
|
||||||
if src != nil && !src.volatile && filter != driver.FilterScreen {
|
// TODO: Do we need to check all the sources' states of being volatile?
|
||||||
|
if srcs[0] != nil && !srcs[0].volatile && filter != driver.FilterScreen {
|
||||||
level = math.MaxInt32
|
level = math.MaxInt32
|
||||||
for i := 0; i < len(indices)/3; i++ {
|
for i := 0; i < len(indices)/3; i++ {
|
||||||
const n = graphics.VertexFloatNum
|
const n = graphics.VertexFloatNum
|
||||||
@ -138,30 +139,27 @@ func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16
|
|||||||
s = shader.shader
|
s = shader.shader
|
||||||
}
|
}
|
||||||
|
|
||||||
var srcimg *shareable.Image
|
var imgs [graphics.ShaderImageNum]*shareable.Image
|
||||||
if src != nil {
|
for i, src := range srcs {
|
||||||
srcimg = src.orig
|
if src == nil {
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
if level != 0 {
|
if level != 0 {
|
||||||
if img := src.level(level); img != nil {
|
if img := src.level(level); img != nil {
|
||||||
srcimg = img
|
const n = graphics.VertexFloatNum
|
||||||
const n = graphics.VertexFloatNum
|
s := float32(pow2(level))
|
||||||
s := float32(pow2(level))
|
for i := 0; i < len(vertices)/n; i++ {
|
||||||
for i := 0; i < len(vertices)/n; i++ {
|
vertices[i*n+2] /= s
|
||||||
vertices[i*n+2] /= s
|
vertices[i*n+3] /= s
|
||||||
vertices[i*n+3] /= s
|
}
|
||||||
|
imgs[i] = img
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
imgs[i] = src.orig
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Do we need to consider mipmaps here?
|
m.orig.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||||
var imgs []*shareable.Image
|
|
||||||
for _, img := range images {
|
|
||||||
imgs = append(imgs, img.orig)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.orig.DrawTriangles(srcimg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, imgs)
|
|
||||||
m.disposeMipmaps()
|
m.disposeMipmaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +220,7 @@ func (m *Mipmap) level(level int) *shareable.Image {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s := shareable.NewImage(w2, h2, m.volatile)
|
s := shareable.NewImage(w2, h2, m.volatile)
|
||||||
s.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
s.DrawTriangles([graphics.ShaderImageNum]*shareable.Image{src}, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
m.imgs[level] = s
|
m.imgs[level] = s
|
||||||
|
|
||||||
return m.imgs[level]
|
return m.imgs[level]
|
||||||
|
@ -69,7 +69,7 @@ func (p *Pixels) At(i, j int) (byte, byte, byte, byte) {
|
|||||||
|
|
||||||
// drawTrianglesHistoryItem is an item for history of draw-image commands.
|
// drawTrianglesHistoryItem is an item for history of draw-image commands.
|
||||||
type drawTrianglesHistoryItem struct {
|
type drawTrianglesHistoryItem struct {
|
||||||
image *Image
|
images [graphics.ShaderImageNum]*Image
|
||||||
vertices []float32
|
vertices []float32
|
||||||
indices []uint16
|
indices []uint16
|
||||||
colorm *affine.ColorM
|
colorm *affine.ColorM
|
||||||
@ -79,7 +79,6 @@ type drawTrianglesHistoryItem struct {
|
|||||||
sourceRegion driver.Region
|
sourceRegion driver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
uniforms []interface{}
|
uniforms []interface{}
|
||||||
images []*Image
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image represents an image that can be restored when GL context is lost.
|
// Image represents an image that can be restored when GL context is lost.
|
||||||
@ -260,7 +259,7 @@ func fillImage(i *graphicscommand.Image, clr color.RGBA) {
|
|||||||
// Add 1 pixels for paddings.
|
// Add 1 pixels for paddings.
|
||||||
vs := quadVertices(0, 0, float32(dw), float32(dh), 1, 1, float32(sw-1), float32(sh-1), rf, gf, bf, af)
|
vs := quadVertices(0, 0, float32(dw), float32(dh), 1, 1, float32(sw-1), float32(sh-1), rf, gf, bf, af)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
i.DrawTriangles(emptyImage.image, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
i.DrawTriangles([graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasePixelsForTesting returns the image's basePixels for testing.
|
// BasePixelsForTesting returns the image's basePixels for testing.
|
||||||
@ -352,7 +351,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if i.priority {
|
if i.priority {
|
||||||
panic("restorable: DrawTriangles cannot be called on a priority image")
|
panic("restorable: DrawTriangles cannot be called on a priority image")
|
||||||
}
|
}
|
||||||
@ -363,41 +362,38 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
|
|
||||||
// TODO: Add tests to confirm this logic.
|
// TODO: Add tests to confirm this logic.
|
||||||
var srcstale bool
|
var srcstale bool
|
||||||
if img != nil && (img.stale || img.volatile) {
|
for _, src := range srcs {
|
||||||
srcstale = true
|
if src == nil {
|
||||||
}
|
continue
|
||||||
if !srcstale {
|
}
|
||||||
for _, t := range images {
|
if src.stale || src.volatile {
|
||||||
if t.stale || t.volatile {
|
srcstale = true
|
||||||
srcstale = true
|
break
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if srcstale || i.screen || !needsRestoring() || i.volatile {
|
if srcstale || i.screen || !needsRestoring() || i.volatile {
|
||||||
i.makeStale()
|
i.makeStale()
|
||||||
} else {
|
} else {
|
||||||
i.appendDrawTrianglesHistory(img, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms, images)
|
i.appendDrawTrianglesHistory(srcs, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms)
|
||||||
}
|
}
|
||||||
var s *graphicscommand.Shader
|
var s *graphicscommand.Shader
|
||||||
if shader != nil {
|
if shader != nil {
|
||||||
s = shader.shader
|
s = shader.shader
|
||||||
}
|
}
|
||||||
var gimg *graphicscommand.Image
|
|
||||||
if img != nil {
|
|
||||||
gimg = img.image
|
|
||||||
}
|
|
||||||
|
|
||||||
var ts []*graphicscommand.Image
|
var imgs [graphics.ShaderImageNum]*graphicscommand.Image
|
||||||
for _, t := range images {
|
for i, src := range srcs {
|
||||||
ts = append(ts, t.image)
|
if src == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
imgs[i] = src.image
|
||||||
}
|
}
|
||||||
i.image.DrawTriangles(gimg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, ts)
|
i.image.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
||||||
func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if i.stale || i.volatile || i.screen {
|
if i.stale || i.volatile || i.screen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -416,7 +412,7 @@ func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, ind
|
|||||||
copy(is, indices)
|
copy(is, indices)
|
||||||
|
|
||||||
item := &drawTrianglesHistoryItem{
|
item := &drawTrianglesHistoryItem{
|
||||||
image: image,
|
images: srcs,
|
||||||
vertices: vs,
|
vertices: vs,
|
||||||
indices: is,
|
indices: is,
|
||||||
colorm: colorm,
|
colorm: colorm,
|
||||||
@ -426,7 +422,6 @@ func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, ind
|
|||||||
sourceRegion: sourceRegion,
|
sourceRegion: sourceRegion,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
uniforms: uniforms,
|
uniforms: uniforms,
|
||||||
images: images,
|
|
||||||
}
|
}
|
||||||
i.drawTrianglesHistory = append(i.drawTrianglesHistory, item)
|
i.drawTrianglesHistory = append(i.drawTrianglesHistory, item)
|
||||||
}
|
}
|
||||||
@ -515,10 +510,10 @@ func (i *Image) resolveStale() error {
|
|||||||
// dependsOn reports whether the image depends on target.
|
// dependsOn reports whether the image depends on target.
|
||||||
func (i *Image) dependsOn(target *Image) bool {
|
func (i *Image) dependsOn(target *Image) bool {
|
||||||
for _, c := range i.drawTrianglesHistory {
|
for _, c := range i.drawTrianglesHistory {
|
||||||
if c.image == target {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, img := range c.images {
|
for _, img := range c.images {
|
||||||
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if img == target {
|
if img == target {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -541,10 +536,10 @@ func (i *Image) dependsOnShader(shader *Shader) bool {
|
|||||||
func (i *Image) dependingImages() map[*Image]struct{} {
|
func (i *Image) dependingImages() map[*Image]struct{} {
|
||||||
r := map[*Image]struct{}{}
|
r := map[*Image]struct{}{}
|
||||||
for _, c := range i.drawTrianglesHistory {
|
for _, c := range i.drawTrianglesHistory {
|
||||||
if c.image != nil {
|
|
||||||
r[c.image] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, img := range c.images {
|
for _, img := range c.images {
|
||||||
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
r[img] = struct{}{}
|
r[img] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,23 +587,22 @@ func (i *Image) restore() error {
|
|||||||
i.basePixels.Apply(gimg)
|
i.basePixels.Apply(gimg)
|
||||||
|
|
||||||
for _, c := range i.drawTrianglesHistory {
|
for _, c := range i.drawTrianglesHistory {
|
||||||
if c.image != nil && c.image.hasDependency() {
|
|
||||||
panic("restorable: all dependencies must be already resolved but not")
|
|
||||||
}
|
|
||||||
// TODO: Check the uniform variable's images.
|
|
||||||
var img *graphicscommand.Image
|
|
||||||
if c.image != nil {
|
|
||||||
img = c.image.image
|
|
||||||
}
|
|
||||||
var s *graphicscommand.Shader
|
var s *graphicscommand.Shader
|
||||||
if c.shader != nil {
|
if c.shader != nil {
|
||||||
s = c.shader.shader
|
s = c.shader.shader
|
||||||
}
|
}
|
||||||
var imgs []*graphicscommand.Image
|
|
||||||
for _, img := range c.images {
|
var imgs [graphics.ShaderImageNum]*graphicscommand.Image
|
||||||
imgs = append(imgs, img.image)
|
for i, img := range c.images {
|
||||||
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if img.hasDependency() {
|
||||||
|
panic("restorable: all dependencies must be already resolved but not")
|
||||||
|
}
|
||||||
|
imgs[i] = img.image
|
||||||
}
|
}
|
||||||
gimg.DrawTriangles(img, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.sourceRegion, s, c.uniforms, imgs)
|
gimg.DrawTriangles(imgs, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.sourceRegion, s, c.uniforms)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(i.drawTrianglesHistory) > 0 {
|
if len(i.drawTrianglesHistory) > 0 {
|
||||||
|
@ -131,7 +131,7 @@ func TestRestoreChain(t *testing.T) {
|
|||||||
for i := 0; i < num-1; i++ {
|
for i := 0; i < num-1; i++ {
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
imgs[i+1].DrawTriangles(imgs[i], vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
}
|
}
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -173,10 +173,10 @@ func TestRestoreChain2(t *testing.T) {
|
|||||||
imgs[8].ReplacePixels([]byte{clr8.R, clr8.G, clr8.B, clr8.A}, 0, 0, w, h)
|
imgs[8].ReplacePixels([]byte{clr8.R, clr8.G, clr8.B, clr8.A}, 0, 0, w, h)
|
||||||
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
imgs[8].DrawTriangles(imgs[7], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
imgs[8].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[7]}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
imgs[9].DrawTriangles(imgs[8], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
imgs[9].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[8]}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
imgs[i+1].DrawTriangles(imgs[i], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -216,10 +216,10 @@ func TestRestoreOverrideSource(t *testing.T) {
|
|||||||
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
||||||
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img2.DrawTriangles(img1, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img2.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img3.DrawTriangles(img2, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
||||||
img1.DrawTriangles(img0, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -298,23 +298,23 @@ func TestRestoreComplexGraph(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img3.DrawTriangles(img0, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img3.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img4.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 2, 0)
|
vs = quadVertices(w, h, 2, 0)
|
||||||
img4.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img5.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img5.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img6.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img6.DrawTriangles(img4, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img4}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img7.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
vs = quadVertices(w, h, 2, 0)
|
vs = quadVertices(w, h, 2, 0)
|
||||||
img7.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -406,8 +406,8 @@ func TestRestoreRecursive(t *testing.T) {
|
|||||||
img0.Dispose()
|
img0.Dispose()
|
||||||
}()
|
}()
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img0, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img0.DrawTriangles(img1, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -501,7 +501,7 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -538,8 +538,8 @@ func TestDispose(t *testing.T) {
|
|||||||
defer img2.Dispose()
|
defer img2.Dispose()
|
||||||
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img2, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img0.DrawTriangles(img1, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img1.Dispose()
|
img1.Dispose()
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -647,7 +647,7 @@ func TestReplacePixelsOnly(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||||
|
|
||||||
// BasePixelsForTesting is available without GPU accessing.
|
// BasePixelsForTesting is available without GPU accessing.
|
||||||
@ -700,7 +700,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
|||||||
src.ReplacePixels(pix, 0, 0, w, h)
|
src.ReplacePixels(pix, 0, 0, w, h)
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
||||||
// stale.
|
// stale.
|
||||||
@ -721,7 +721,7 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||||
// ReplacePixels for a whole image doesn't panic.
|
// ReplacePixels for a whole image doesn't panic.
|
||||||
}
|
}
|
||||||
@ -739,7 +739,7 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,7 +828,7 @@ func TestFill2(t *testing.T) {
|
|||||||
dst := NewImage(w, h, false)
|
dst := NewImage(w, h, false)
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
// Fill src with a different color. This should not affect dst.
|
// Fill src with a different color. This should not affect dst.
|
||||||
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
||||||
@ -867,7 +867,7 @@ func TestMutateSlices(t *testing.T) {
|
|||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := make([]uint16, len(graphics.QuadIndices()))
|
is := make([]uint16, len(graphics.QuadIndices()))
|
||||||
copy(is, graphics.QuadIndices())
|
copy(is, graphics.QuadIndices())
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
for i := range vs {
|
for i := range vs {
|
||||||
vs[i] = 0
|
vs[i] = 0
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func TestShader(t *testing.T) {
|
|||||||
us := []interface{}{
|
us := []interface{}{
|
||||||
[]float32{0, 0},
|
[]float32{0, 0},
|
||||||
}
|
}
|
||||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -75,7 +75,7 @@ func TestShaderChain(t *testing.T) {
|
|||||||
us := []interface{}{
|
us := []interface{}{
|
||||||
[]float32{0, 0},
|
[]float32{0, 0},
|
||||||
}
|
}
|
||||||
imgs[i+1].DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, imgs[i:i+1])
|
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -99,7 +99,7 @@ func TestShaderMultipleSources(t *testing.T) {
|
|||||||
t.Skip("shader is not available on this environment")
|
t.Skip("shader is not available on this environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
srcs := make([]*Image, 3)
|
var srcs [graphics.ShaderImageNum]*Image
|
||||||
for i := range srcs {
|
for i := range srcs {
|
||||||
srcs[i] = NewImage(1, 1, false)
|
srcs[i] = NewImage(1, 1, false)
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ func TestShaderMultipleSources(t *testing.T) {
|
|||||||
us := []interface{}{
|
us := []interface{}{
|
||||||
[]float32{0, 0},
|
[]float32{0, 0},
|
||||||
}
|
}
|
||||||
dst.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, srcs)
|
dst.DrawTriangles(srcs, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||||
|
|
||||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||||
srcs[0].Fill(color.RGBA{})
|
srcs[0].Fill(color.RGBA{})
|
||||||
@ -146,7 +146,7 @@ func TestShaderDispose(t *testing.T) {
|
|||||||
us := []interface{}{
|
us := []interface{}{
|
||||||
[]float32{0, 0},
|
[]float32{0, 0},
|
||||||
}
|
}
|
||||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||||
|
|
||||||
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
|
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
|
||||||
// stale.
|
// stale.
|
||||||
|
@ -220,7 +220,7 @@ func (i *Image) ensureNotShared() {
|
|||||||
dx1, dy1, sx1, sy1, 1, 1, 1, 1,
|
dx1, dy1, sx1, sy1, 1, 1, 1, 1,
|
||||||
}
|
}
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
newImg.DrawTriangles(i.backend.restorable, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
newImg.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{i.backend.restorable}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
i.dispose(false)
|
i.dispose(false)
|
||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
@ -273,6 +273,9 @@ func (i *Image) regionWithPadding() (x, y, width, height int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) processSrc(src *Image) {
|
func (i *Image) processSrc(src *Image) {
|
||||||
|
if src == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if src.disposed {
|
if src.disposed {
|
||||||
panic("shareable: the drawing source image must not be disposed (DrawTriangles)")
|
panic("shareable: the drawing source image must not be disposed (DrawTriangles)")
|
||||||
}
|
}
|
||||||
@ -287,12 +290,6 @@ func (i *Image) processSrc(src *Image) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeSharedIfNeeded(src *Image) {
|
|
||||||
if !src.isShared() && src.shareable() {
|
|
||||||
imagesToMakeShared[src] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DrawTriangles draws triangles with the given image.
|
// DrawTriangles draws triangles with the given image.
|
||||||
//
|
//
|
||||||
// The vertex floats are:
|
// The vertex floats are:
|
||||||
@ -305,7 +302,7 @@ func makeSharedIfNeeded(src *Image) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, images []*Image) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
// Do not use defer for performance.
|
// Do not use defer for performance.
|
||||||
|
|
||||||
@ -314,14 +311,7 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
}
|
}
|
||||||
i.ensureNotShared()
|
i.ensureNotShared()
|
||||||
|
|
||||||
if img != nil {
|
for _, src := range srcs {
|
||||||
i.processSrc(img)
|
|
||||||
}
|
|
||||||
firstImg := img
|
|
||||||
for _, src := range images {
|
|
||||||
if firstImg == nil {
|
|
||||||
firstImg = src
|
|
||||||
}
|
|
||||||
i.processSrc(src)
|
i.processSrc(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,9 +322,10 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
dy = paddingSize
|
dy = paddingSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Pass the offsets as uniform variables for second and following images.
|
||||||
var oxf, oyf float32
|
var oxf, oyf float32
|
||||||
if firstImg != nil {
|
if srcs[0] != nil {
|
||||||
ox, oy, _, _ := firstImg.regionWithPadding()
|
ox, oy, _, _ := srcs[0].regionWithPadding()
|
||||||
ox += paddingSize
|
ox += paddingSize
|
||||||
oy += paddingSize
|
oy += paddingSize
|
||||||
oxf, oyf = float32(ox), float32(oy)
|
oxf, oyf = float32(ox), float32(oy)
|
||||||
@ -356,25 +347,26 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
|||||||
s = shader.shader
|
s = shader.shader
|
||||||
}
|
}
|
||||||
|
|
||||||
var imgs []*restorable.Image
|
var imgs [graphics.ShaderImageNum]*restorable.Image
|
||||||
for _, img := range images {
|
for i, src := range srcs {
|
||||||
imgs = append(imgs, img.backend.restorable)
|
if src == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
imgs[i] = src.backend.restorable
|
||||||
}
|
}
|
||||||
|
|
||||||
var r *restorable.Image
|
i.backend.restorable.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||||
if img != nil {
|
|
||||||
r = img.backend.restorable
|
|
||||||
}
|
|
||||||
i.backend.restorable.DrawTriangles(r, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, imgs)
|
|
||||||
|
|
||||||
i.nonUpdatedCount = 0
|
i.nonUpdatedCount = 0
|
||||||
delete(imagesToMakeShared, i)
|
delete(imagesToMakeShared, i)
|
||||||
|
|
||||||
if img != nil {
|
for _, src := range srcs {
|
||||||
makeSharedIfNeeded(img)
|
if src == nil {
|
||||||
}
|
continue
|
||||||
for _, src := range images {
|
}
|
||||||
makeSharedIfNeeded(src)
|
if !src.isShared() && src.shareable() {
|
||||||
|
imagesToMakeShared[src] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backendsM.Unlock()
|
backendsM.Unlock()
|
||||||
|
@ -96,7 +96,7 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
// img4.ensureNotShared() should be called.
|
// img4.ensureNotShared() should be called.
|
||||||
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
want := false
|
want := false
|
||||||
if got := img4.IsSharedForTesting(); got != want {
|
if got := img4.IsSharedForTesting(); got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
@ -126,7 +126,7 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
|
|
||||||
// Check further drawing doesn't cause panic.
|
// Check further drawing doesn't cause panic.
|
||||||
// This bug was fixed by 03dcd948.
|
// This bug was fixed by 03dcd948.
|
||||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReshared(t *testing.T) {
|
func TestReshared(t *testing.T) {
|
||||||
@ -166,7 +166,7 @@ func TestReshared(t *testing.T) {
|
|||||||
// Use img1 as a render target.
|
// Use img1 as a render target.
|
||||||
vs := quadVertices(size, size, 0, 0, 1)
|
vs := quadVertices(size, size, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0, 1)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.ReplacePixels(pix)
|
dst.ReplacePixels(pix)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
@ -368,7 +368,7 @@ func TestSmallImages(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0, 1)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -410,7 +410,7 @@ func TestLongImages(t *testing.T) {
|
|||||||
const scale = 120
|
const scale = 120
|
||||||
vs := quadVertices(w, h, 0, 0, scale)
|
vs := quadVertices(w, h, 0, 0, scale)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/buffered"
|
"github.com/hajimehoshi/ebiten/internal/buffered"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/shader"
|
"github.com/hajimehoshi/ebiten/internal/shader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ type Shader struct {
|
|||||||
shader *buffered.Shader
|
shader *buffered.Shader
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShader(src []byte, textureNum int) (*Shader, error) {
|
func NewShader(src []byte) (*Shader, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.Write(src)
|
buf.Write(src)
|
||||||
buf.WriteString(shaderSuffix)
|
buf.WriteString(shaderSuffix)
|
||||||
@ -47,7 +48,7 @@ func NewShader(src []byte, textureNum int) (*Shader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create a pseudo vertex entrypoint to treat the attribute values correctly.
|
// TODO: Create a pseudo vertex entrypoint to treat the attribute values correctly.
|
||||||
s, err := shader.Compile(fs, f, "Vertex", "Fragment", textureNum)
|
s, err := shader.Compile(fs, f, "Vertex", "Fragment", graphics.ShaderImageNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user