mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
internal/graphicsdriver: add Blend struct
This is a preparation to specify blend factors and blend operators. Updates #2382
This commit is contained in:
parent
2f146d5e4f
commit
09a7d39874
77
graphics.go
77
graphics.go
@ -15,6 +15,8 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
@ -41,50 +43,97 @@ type CompositeMode int
|
|||||||
const (
|
const (
|
||||||
// Regular alpha blending
|
// Regular alpha blending
|
||||||
// c_out = c_src + c_dst × (1 - α_src)
|
// c_out = c_src + c_dst × (1 - α_src)
|
||||||
CompositeModeSourceOver CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceOver)
|
CompositeModeSourceOver CompositeMode = iota
|
||||||
|
|
||||||
// c_out = 0
|
// c_out = 0
|
||||||
CompositeModeClear CompositeMode = CompositeMode(graphicsdriver.CompositeModeClear)
|
CompositeModeClear
|
||||||
|
|
||||||
// c_out = c_src
|
// c_out = c_src
|
||||||
CompositeModeCopy CompositeMode = CompositeMode(graphicsdriver.CompositeModeCopy)
|
CompositeModeCopy
|
||||||
|
|
||||||
// c_out = c_dst
|
// c_out = c_dst
|
||||||
CompositeModeDestination CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestination)
|
CompositeModeDestination
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst
|
// c_out = c_src × (1 - α_dst) + c_dst
|
||||||
CompositeModeDestinationOver CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationOver)
|
CompositeModeDestinationOver
|
||||||
|
|
||||||
// c_out = c_src × α_dst
|
// c_out = c_src × α_dst
|
||||||
CompositeModeSourceIn CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceIn)
|
CompositeModeSourceIn
|
||||||
|
|
||||||
// c_out = c_dst × α_src
|
// c_out = c_dst × α_src
|
||||||
CompositeModeDestinationIn CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationIn)
|
CompositeModeDestinationIn
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst)
|
// c_out = c_src × (1 - α_dst)
|
||||||
CompositeModeSourceOut CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceOut)
|
CompositeModeSourceOut
|
||||||
|
|
||||||
// c_out = c_dst × (1 - α_src)
|
// c_out = c_dst × (1 - α_src)
|
||||||
CompositeModeDestinationOut CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationOut)
|
CompositeModeDestinationOut
|
||||||
|
|
||||||
// c_out = c_src × α_dst + c_dst × (1 - α_src)
|
// c_out = c_src × α_dst + c_dst × (1 - α_src)
|
||||||
CompositeModeSourceAtop CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceAtop)
|
CompositeModeSourceAtop
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst × α_src
|
// c_out = c_src × (1 - α_dst) + c_dst × α_src
|
||||||
CompositeModeDestinationAtop CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationAtop)
|
CompositeModeDestinationAtop
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
|
// c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
|
||||||
CompositeModeXor CompositeMode = CompositeMode(graphicsdriver.CompositeModeXor)
|
CompositeModeXor
|
||||||
|
|
||||||
// Sum of source and destination (a.k.a. 'plus' or 'additive')
|
// Sum of source and destination (a.k.a. 'plus' or 'additive')
|
||||||
// c_out = c_src + c_dst
|
// c_out = c_src + c_dst
|
||||||
CompositeModeLighter CompositeMode = CompositeMode(graphicsdriver.CompositeModeLighter)
|
CompositeModeLighter
|
||||||
|
|
||||||
// The product of source and destination (a.k.a 'multiply blend mode')
|
// The product of source and destination (a.k.a 'multiply blend mode')
|
||||||
// c_out = c_src * c_dst
|
// c_out = c_src * c_dst
|
||||||
CompositeModeMultiply CompositeMode = CompositeMode(graphicsdriver.CompositeModeMultiply)
|
CompositeModeMultiply
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (c CompositeMode) blend() graphicsdriver.Blend {
|
||||||
|
src, dst := c.blendFactors()
|
||||||
|
return graphicsdriver.Blend{
|
||||||
|
BlendFactorSourceColor: src,
|
||||||
|
BlendFactorSourceAlpha: src,
|
||||||
|
BlendFactorDestinationColor: dst,
|
||||||
|
BlendFactorDestinationAlpha: dst,
|
||||||
|
BlendOperationColor: graphicsdriver.BlendOperationAdd,
|
||||||
|
BlendOperationAlpha: graphicsdriver.BlendOperationAdd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CompositeMode) blendFactors() (src graphicsdriver.BlendFactor, dst graphicsdriver.BlendFactor) {
|
||||||
|
switch c {
|
||||||
|
case CompositeModeSourceOver:
|
||||||
|
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
||||||
|
case CompositeModeClear:
|
||||||
|
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorZero
|
||||||
|
case CompositeModeCopy:
|
||||||
|
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorZero
|
||||||
|
case CompositeModeDestination:
|
||||||
|
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOne
|
||||||
|
case CompositeModeDestinationOver:
|
||||||
|
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOne
|
||||||
|
case CompositeModeSourceIn:
|
||||||
|
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorZero
|
||||||
|
case CompositeModeDestinationIn:
|
||||||
|
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorSourceAlpha
|
||||||
|
case CompositeModeSourceOut:
|
||||||
|
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorZero
|
||||||
|
case CompositeModeDestinationOut:
|
||||||
|
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
||||||
|
case CompositeModeSourceAtop:
|
||||||
|
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
||||||
|
case CompositeModeDestinationAtop:
|
||||||
|
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorSourceAlpha
|
||||||
|
case CompositeModeXor:
|
||||||
|
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
||||||
|
case CompositeModeLighter:
|
||||||
|
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOne
|
||||||
|
case CompositeModeMultiply:
|
||||||
|
return graphicsdriver.BlendFactorDestinationColor, graphicsdriver.BlendFactorZero
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("ebiten: invalid composite mode: %d", c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GraphicsLibrary represets graphics libraries supported by the engine.
|
// GraphicsLibrary represets graphics libraries supported by the engine.
|
||||||
type GraphicsLibrary = ui.GraphicsLibrary
|
type GraphicsLibrary = ui.GraphicsLibrary
|
||||||
|
|
||||||
|
16
image.go
16
image.go
@ -215,7 +215,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
|||||||
options = &DrawImageOptions{}
|
options = &DrawImageOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
blend := options.CompositeMode.blend()
|
||||||
filter := builtinshader.Filter(options.Filter)
|
filter := builtinshader.Filter(options.Filter)
|
||||||
|
|
||||||
if offsetX, offsetY := i.adjustPosition(0, 0); offsetX != 0 || offsetY != 0 {
|
if offsetX, offsetY := i.adjustPosition(0, 0); offsetX != 0 || offsetY != 0 {
|
||||||
@ -245,7 +245,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
i.image.DrawTriangles(srcs, vs, is, mode, i.adjustedRegion(), graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, uniforms, false, canSkipMipmap(options.GeoM, filter))
|
i.image.DrawTriangles(srcs, vs, is, blend, i.adjustedRegion(), graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, uniforms, false, canSkipMipmap(options.GeoM, filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertex represents a vertex passed to DrawTriangles.
|
// Vertex represents a vertex passed to DrawTriangles.
|
||||||
@ -396,7 +396,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
options = &DrawTrianglesOptions{}
|
options = &DrawTrianglesOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
blend := options.CompositeMode.blend()
|
||||||
|
|
||||||
address := builtinshader.Address(options.Address)
|
address := builtinshader.Address(options.Address)
|
||||||
var sr graphicsdriver.Region
|
var sr graphicsdriver.Region
|
||||||
@ -455,7 +455,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
i.image.DrawTriangles(srcs, vs, is, mode, i.adjustedRegion(), sr, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, uniforms, options.FillRule == EvenOdd, filter != builtinshader.FilterLinear)
|
i.image.DrawTriangles(srcs, vs, is, blend, i.adjustedRegion(), sr, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, uniforms, options.FillRule == EvenOdd, filter != builtinshader.FilterLinear)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||||
@ -525,7 +525,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
options = &DrawTrianglesShaderOptions{}
|
options = &DrawTrianglesShaderOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
blend := options.CompositeMode.blend()
|
||||||
|
|
||||||
vs := graphics.Vertices(len(vertices))
|
vs := graphics.Vertices(len(vertices))
|
||||||
dst := i
|
dst := i
|
||||||
@ -589,7 +589,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
offsets[i][1] = float32(y - sy)
|
offsets[i][1] = float32(y - sy)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.image.DrawTriangles(imgs, vs, is, mode, i.adjustedRegion(), sr, offsets, shader.shader, shader.convertUniforms(options.Uniforms), options.FillRule == EvenOdd, true)
|
i.image.DrawTriangles(imgs, vs, is, blend, i.adjustedRegion(), sr, offsets, shader.shader, shader.convertUniforms(options.Uniforms), options.FillRule == EvenOdd, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectShaderOptions represents options for DrawRectShader.
|
// DrawRectShaderOptions represents options for DrawRectShader.
|
||||||
@ -645,7 +645,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
options = &DrawRectShaderOptions{}
|
options = &DrawRectShaderOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
blend := options.CompositeMode.blend()
|
||||||
|
|
||||||
var imgs [graphics.ShaderImageCount]*ui.Image
|
var imgs [graphics.ShaderImageCount]*ui.Image
|
||||||
for i, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
@ -690,7 +690,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
offsets[i][1] = float32(y - sy)
|
offsets[i][1] = float32(y - sy)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.image.DrawTriangles(imgs, vs, is, mode, i.adjustedRegion(), sr, offsets, shader.shader, shader.convertUniforms(options.Uniforms), false, true)
|
i.image.DrawTriangles(imgs, vs, is, blend, i.adjustedRegion(), sr, offsets, shader.shader, shader.convertUniforms(options.Uniforms), false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -309,7 +309,7 @@ func (i *Image) ensureIsolated() {
|
|||||||
Width: float32(w - 2*i.paddingSize()),
|
Width: float32(w - 2*i.paddingSize()),
|
||||||
Height: float32(h - 2*i.paddingSize()),
|
Height: float32(h - 2*i.paddingSize()),
|
||||||
}
|
}
|
||||||
newImg.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.CompositeModeCopy, dstRegion, graphicsdriver.Region{}, NearestFilterShader.shader, nil, false)
|
newImg.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.BlendCopy, dstRegion, graphicsdriver.Region{}, NearestFilterShader.shader, nil, false)
|
||||||
|
|
||||||
i.dispose(false)
|
i.dispose(false)
|
||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
@ -348,7 +348,7 @@ func (i *Image) putOnAtlas(graphicsDriver graphicsdriver.Graphics) error {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
newI.drawTriangles([graphics.ShaderImageCount]*Image{i}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader, nil, false, true)
|
newI.drawTriangles([graphics.ShaderImageCount]*Image{i}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader, nil, false, true)
|
||||||
|
|
||||||
newI.moveTo(i)
|
newI.moveTo(i)
|
||||||
i.usedAsSourceCount = 0
|
i.usedAsSourceCount = 0
|
||||||
@ -395,13 +395,13 @@ func (i *Image) processSrc(src *Image) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
i.drawTriangles(srcs, vertices, indices, mode, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false)
|
i.drawTriangles(srcs, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, keepOnAtlas bool) {
|
func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, keepOnAtlas bool) {
|
||||||
if i.disposed {
|
if i.disposed {
|
||||||
panic("atlas: the drawing target image must not be disposed (DrawTriangles)")
|
panic("atlas: the drawing target image must not be disposed (DrawTriangles)")
|
||||||
}
|
}
|
||||||
@ -472,7 +472,7 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
|||||||
imgs[i] = src.backend.restorable
|
imgs[i] = src.backend.restorable
|
||||||
}
|
}
|
||||||
|
|
||||||
i.backend.restorable.DrawTriangles(imgs, offsets, vertices, indices, mode, dstRegion, srcRegion, shader.shader, uniforms, evenOdd)
|
i.backend.restorable.DrawTriangles(imgs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader.shader, uniforms, evenOdd)
|
||||||
|
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
|
@ -106,7 +106,7 @@ func TestEnsureIsolated(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
img4.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img4.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img4.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ func TestEnsureIsolated(t *testing.T) {
|
|||||||
Width: size / 2,
|
Width: size / 2,
|
||||||
Height: size / 2,
|
Height: size / 2,
|
||||||
}
|
}
|
||||||
img3.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img5}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img5}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ func TestEnsureIsolated(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([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReputOnAtlas(t *testing.T) {
|
func TestReputOnAtlas(t *testing.T) {
|
||||||
@ -195,7 +195,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img2}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img2}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -207,7 +207,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// img1 is on an atlas again.
|
// img1 is on an atlas again.
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), true; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), true; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img1 as a render target again.
|
// Use img1 as a render target again.
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img2}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img2}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
|
img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// img1 is not on an atlas due to WritePixels.
|
// img1 is not on an atlas due to WritePixels.
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img3}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -391,7 +391,7 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
dst.WritePixels(pix, 0, 0, w, h)
|
dst.WritePixels(pix, 0, 0, w, h)
|
||||||
|
|
||||||
pix = make([]byte, 4*w*h)
|
pix = make([]byte, 4*w*h)
|
||||||
@ -439,7 +439,7 @@ func TestSmallImages(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
pix = make([]byte, 4*w*h)
|
pix = make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
||||||
@ -487,7 +487,7 @@ func TestLongImages(t *testing.T) {
|
|||||||
Width: dstW,
|
Width: dstW,
|
||||||
Height: dstH,
|
Height: dstH,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
pix = make([]byte, 4*dstW*dstH)
|
pix = make([]byte, 4*dstW*dstH)
|
||||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
||||||
@ -604,7 +604,7 @@ func TestDisposedAndReputOnAtlas(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
src.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src2}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
src.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src2}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -614,7 +614,7 @@ func TestDisposedAndReputOnAtlas(t *testing.T) {
|
|||||||
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -654,7 +654,7 @@ func TestImageIsNotReputOnAtlasWithoutUsingAsSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use src2 as a rendering target, and make src2 an independent image.
|
// Use src2 as a rendering target, and make src2 an independent image.
|
||||||
src2.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
src2.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -675,7 +675,7 @@ func TestImageIsNotReputOnAtlasWithoutUsingAsSource(t *testing.T) {
|
|||||||
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
if err := atlas.PutImagesOnAtlasForTesting(ui.GraphicsDriverForTesting()); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src2}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src2}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,12 @@ func TestShaderFillTwice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
g := ui.GraphicsDriverForTesting()
|
g := ui.GraphicsDriverForTesting()
|
||||||
s0 := atlas.NewShader(etesting.ShaderProgramFill(0xff, 0xff, 0xff, 0xff))
|
s0 := atlas.NewShader(etesting.ShaderProgramFill(0xff, 0xff, 0xff, 0xff))
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s0, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s0, nil, false)
|
||||||
|
|
||||||
// Vertices must be recreated (#1755)
|
// Vertices must be recreated (#1755)
|
||||||
vs = quadVertices(w, h, 0, 0, 1)
|
vs = quadVertices(w, h, 0, 0, 1)
|
||||||
s1 := atlas.NewShader(etesting.ShaderProgramFill(0x80, 0x80, 0x80, 0xff))
|
s1 := atlas.NewShader(etesting.ShaderProgramFill(0x80, 0x80, 0x80, 0xff))
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s1, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s1, nil, false)
|
||||||
|
|
||||||
pix := make([]byte, 4*w*h)
|
pix := make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(g, pix); err != nil {
|
if err := dst.ReadPixels(g, pix); err != nil {
|
||||||
@ -73,11 +73,11 @@ func TestImageDrawTwice(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src0}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src0}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
// Vertices must be recreated (#1755)
|
// Vertices must be recreated (#1755)
|
||||||
vs = quadVertices(w, h, 0, 0, 1)
|
vs = quadVertices(w, h, 0, 0, 1)
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src1}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
pix := make([]byte, 4*w*h)
|
pix := make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
||||||
|
@ -140,7 +140,7 @@ func (i *Image) WritePixels(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(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
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")
|
||||||
@ -150,7 +150,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
|||||||
if maybeCanAddDelayedCommand() {
|
if maybeCanAddDelayedCommand() {
|
||||||
if tryAddDelayedCommand(func() {
|
if tryAddDelayedCommand(func() {
|
||||||
// Arguments are not copied. Copying is the caller's responsibility.
|
// Arguments are not copied. Copying is the caller's responsibility.
|
||||||
i.DrawTriangles(srcs, vertices, indices, mode, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd)
|
i.DrawTriangles(srcs, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd)
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
|||||||
}
|
}
|
||||||
|
|
||||||
i.invalidatePixels()
|
i.invalidatePixels()
|
||||||
i.img.DrawTriangles(imgs, vertices, indices, mode, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd)
|
i.img.DrawTriangles(imgs, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
|
@ -89,7 +89,7 @@ func mustUseDifferentVertexBuffer(nextNumVertexFloats, nextNumIndices int) bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
if len(indices) > graphics.IndicesCount {
|
if len(indices) > graphics.IndicesCount {
|
||||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesCount but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesCount: %d", len(indices), graphics.IndicesCount))
|
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesCount but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesCount: %d", len(indices), graphics.IndicesCount))
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
|||||||
// 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, ok := q.commands[len(q.commands)-1].(*drawTrianglesCommand); ok {
|
if last, ok := q.commands[len(q.commands)-1].(*drawTrianglesCommand); ok {
|
||||||
if last.CanMergeWithDrawTrianglesCommand(dst, srcs, vertices, mode, dstRegion, srcRegion, shader, uniforms, evenOdd) {
|
if last.CanMergeWithDrawTrianglesCommand(dst, srcs, vertices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd) {
|
||||||
last.setVertices(q.lastVertices(len(vertices) + last.numVertices()))
|
last.setVertices(q.lastVertices(len(vertices) + last.numVertices()))
|
||||||
last.addNumIndices(len(indices))
|
last.addNumIndices(len(indices))
|
||||||
return
|
return
|
||||||
@ -137,7 +137,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
|||||||
c.offsets = offsets
|
c.offsets = offsets
|
||||||
c.vertices = q.lastVertices(len(vertices))
|
c.vertices = q.lastVertices(len(vertices))
|
||||||
c.nindices = len(indices)
|
c.nindices = len(indices)
|
||||||
c.mode = mode
|
c.blend = blend
|
||||||
c.dstRegion = dstRegion
|
c.dstRegion = dstRegion
|
||||||
c.srcRegion = srcRegion
|
c.srcRegion = srcRegion
|
||||||
c.shader = shader
|
c.shader = shader
|
||||||
@ -259,7 +259,7 @@ type drawTrianglesCommand struct {
|
|||||||
offsets [graphics.ShaderImageCount - 1][2]float32
|
offsets [graphics.ShaderImageCount - 1][2]float32
|
||||||
vertices []float32
|
vertices []float32
|
||||||
nindices int
|
nindices int
|
||||||
mode graphicsdriver.CompositeMode
|
blend graphicsdriver.Blend
|
||||||
dstRegion graphicsdriver.Region
|
dstRegion graphicsdriver.Region
|
||||||
srcRegion graphicsdriver.Region
|
srcRegion graphicsdriver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
@ -268,39 +268,14 @@ type drawTrianglesCommand struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *drawTrianglesCommand) String() string {
|
func (c *drawTrianglesCommand) String() string {
|
||||||
mode := ""
|
// TODO: Improve readability
|
||||||
switch c.mode {
|
blend := fmt.Sprintf("{src-color: %d, src-alpha: %d, dst-color: %d, dst-alpha: %d, op-color: %d, op-alpha: %d}",
|
||||||
case graphicsdriver.CompositeModeSourceOver:
|
c.blend.BlendFactorSourceColor,
|
||||||
mode = "source-over"
|
c.blend.BlendFactorSourceAlpha,
|
||||||
case graphicsdriver.CompositeModeClear:
|
c.blend.BlendFactorDestinationColor,
|
||||||
mode = "clear"
|
c.blend.BlendFactorDestinationAlpha,
|
||||||
case graphicsdriver.CompositeModeCopy:
|
c.blend.BlendOperationColor,
|
||||||
mode = "copy"
|
c.blend.BlendOperationAlpha)
|
||||||
case graphicsdriver.CompositeModeDestination:
|
|
||||||
mode = "destination"
|
|
||||||
case graphicsdriver.CompositeModeDestinationOver:
|
|
||||||
mode = "destination-over"
|
|
||||||
case graphicsdriver.CompositeModeSourceIn:
|
|
||||||
mode = "source-in"
|
|
||||||
case graphicsdriver.CompositeModeDestinationIn:
|
|
||||||
mode = "destination-in"
|
|
||||||
case graphicsdriver.CompositeModeSourceOut:
|
|
||||||
mode = "source-out"
|
|
||||||
case graphicsdriver.CompositeModeDestinationOut:
|
|
||||||
mode = "destination-out"
|
|
||||||
case graphicsdriver.CompositeModeSourceAtop:
|
|
||||||
mode = "source-atop"
|
|
||||||
case graphicsdriver.CompositeModeDestinationAtop:
|
|
||||||
mode = "destination-atop"
|
|
||||||
case graphicsdriver.CompositeModeXor:
|
|
||||||
mode = "xor"
|
|
||||||
case graphicsdriver.CompositeModeLighter:
|
|
||||||
mode = "lighter"
|
|
||||||
case graphicsdriver.CompositeModeMultiply:
|
|
||||||
mode = "multiply"
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("graphicscommand: invalid composite mode: %d", c.mode))
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := fmt.Sprintf("%d", c.dst.id)
|
dst := fmt.Sprintf("%d", c.dst.id)
|
||||||
if c.dst.screen {
|
if c.dst.screen {
|
||||||
@ -321,7 +296,7 @@ func (c *drawTrianglesCommand) String() string {
|
|||||||
|
|
||||||
r := fmt.Sprintf("(x:%d, y:%d, width:%d, height:%d)",
|
r := fmt.Sprintf("(x:%d, y:%d, width:%d, height:%d)",
|
||||||
int(c.dstRegion.X), int(c.dstRegion.Y), int(c.dstRegion.Width), int(c.dstRegion.Height))
|
int(c.dstRegion.X), int(c.dstRegion.Y), int(c.dstRegion.Width), int(c.dstRegion.Height))
|
||||||
return fmt.Sprintf("draw-triangles: dst: %s <- src: [%s], dst region: %s, num of indices: %d, mode: %s, even-odd: %t", dst, strings.Join(srcstrs[:], ", "), r, c.nindices, mode, c.evenOdd)
|
return fmt.Sprintf("draw-triangles: dst: %s <- src: [%s], dst region: %s, num of indices: %d, blend: %s, even-odd: %t", dst, strings.Join(srcstrs[:], ", "), r, c.nindices, blend, c.evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the drawTrianglesCommand.
|
// Exec executes the drawTrianglesCommand.
|
||||||
@ -340,7 +315,7 @@ func (c *drawTrianglesCommand) Exec(graphicsDriver graphicsdriver.Graphics, inde
|
|||||||
imgs[i] = src.image.ID()
|
imgs[i] = src.image.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
return graphicsDriver.DrawTriangles(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.mode, c.dstRegion, c.srcRegion, c.uniforms, c.evenOdd)
|
return graphicsDriver.DrawTriangles(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.blend, c.dstRegion, c.srcRegion, c.uniforms, c.evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *drawTrianglesCommand) numVertices() int {
|
func (c *drawTrianglesCommand) numVertices() int {
|
||||||
@ -361,7 +336,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 *Image, srcs [graphics.ShaderImageCount]*Image, vertices []float32, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) bool {
|
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, vertices []float32, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) bool {
|
||||||
if c.shader != shader {
|
if c.shader != shader {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -384,7 +359,7 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs
|
|||||||
if c.srcs != srcs {
|
if c.srcs != srcs {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if c.mode != mode {
|
if c.blend != blend {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if c.dstRegion != dstRegion {
|
if c.dstRegion != dstRegion {
|
||||||
|
@ -127,7 +127,7 @@ func (i *Image) InternalSize() (int, int) {
|
|||||||
//
|
//
|
||||||
// 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(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
continue
|
continue
|
||||||
@ -139,7 +139,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
|||||||
}
|
}
|
||||||
i.resolveBufferedWritePixels()
|
i.resolveBufferedWritePixels()
|
||||||
|
|
||||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, mode, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPixels reads the image's pixels.
|
// ReadPixels reads the image's pixels.
|
||||||
|
@ -65,7 +65,7 @@ func TestClear(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
||||||
|
|
||||||
pix := make([]byte, 4*w*h)
|
pix := make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
|
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
|
||||||
@ -96,8 +96,8 @@ func TestWritePixelsPartAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{clr}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{clr}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
||||||
dst.WritePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.WritePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
|
|
||||||
// TODO: Check the result.
|
// TODO: Check the result.
|
||||||
@ -115,11 +115,11 @@ func TestShader(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{clr}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{clr}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendClear, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
||||||
|
|
||||||
g := ui.GraphicsDriverForTesting()
|
g := ui.GraphicsDriverForTesting()
|
||||||
s := graphicscommand.NewShader(etesting.ShaderProgramFill(0xff, 0, 0, 0xff))
|
s := graphicscommand.NewShader(etesting.ShaderProgramFill(0xff, 0, 0, 0xff))
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, s, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
|
|
||||||
pix := make([]byte, 4*w*h)
|
pix := make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(g, pix, 0, 0, w, h); err != nil {
|
if err := dst.ReadPixels(g, pix, 0, 0, w, h); err != nil {
|
||||||
|
71
internal/graphicsdriver/blend.go
Normal file
71
internal/graphicsdriver/blend.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2022 The Ebitengine Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package graphicsdriver
|
||||||
|
|
||||||
|
type Blend struct {
|
||||||
|
BlendFactorSourceColor BlendFactor
|
||||||
|
BlendFactorSourceAlpha BlendFactor
|
||||||
|
BlendFactorDestinationColor BlendFactor
|
||||||
|
BlendFactorDestinationAlpha BlendFactor
|
||||||
|
BlendOperationColor BlendOperation
|
||||||
|
BlendOperationAlpha BlendOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
type BlendFactor int
|
||||||
|
|
||||||
|
const (
|
||||||
|
BlendFactorZero BlendFactor = iota
|
||||||
|
BlendFactorOne
|
||||||
|
BlendFactorSourceAlpha
|
||||||
|
BlendFactorDestinationAlpha
|
||||||
|
BlendFactorOneMinusSourceAlpha
|
||||||
|
BlendFactorOneMinusDestinationAlpha
|
||||||
|
BlendFactorDestinationColor
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlendOperation int
|
||||||
|
|
||||||
|
const (
|
||||||
|
BlendOperationAdd BlendOperation = iota
|
||||||
|
|
||||||
|
// TODO: Add more operators
|
||||||
|
)
|
||||||
|
|
||||||
|
var BlendSourceOver = Blend{
|
||||||
|
BlendFactorSourceColor: BlendFactorOne,
|
||||||
|
BlendFactorSourceAlpha: BlendFactorOne,
|
||||||
|
BlendFactorDestinationColor: BlendFactorOneMinusSourceAlpha,
|
||||||
|
BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
|
||||||
|
BlendOperationColor: BlendOperationAdd,
|
||||||
|
BlendOperationAlpha: BlendOperationAdd,
|
||||||
|
}
|
||||||
|
|
||||||
|
var BlendClear = Blend{
|
||||||
|
BlendFactorSourceColor: BlendFactorZero,
|
||||||
|
BlendFactorSourceAlpha: BlendFactorZero,
|
||||||
|
BlendFactorDestinationColor: BlendFactorZero,
|
||||||
|
BlendFactorDestinationAlpha: BlendFactorZero,
|
||||||
|
BlendOperationColor: BlendOperationAdd,
|
||||||
|
BlendOperationAlpha: BlendOperationAdd,
|
||||||
|
}
|
||||||
|
|
||||||
|
var BlendCopy = Blend{
|
||||||
|
BlendFactorSourceColor: BlendFactorOne,
|
||||||
|
BlendFactorSourceAlpha: BlendFactorOne,
|
||||||
|
BlendFactorDestinationColor: BlendFactorZero,
|
||||||
|
BlendFactorDestinationAlpha: BlendFactorZero,
|
||||||
|
BlendOperationColor: BlendOperationAdd,
|
||||||
|
BlendOperationAlpha: BlendOperationAdd,
|
||||||
|
}
|
@ -1,88 +0,0 @@
|
|||||||
// Copyright 2018 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package graphicsdriver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CompositeMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
CompositeModeUnknown CompositeMode = iota - 1
|
|
||||||
CompositeModeSourceOver // This value must be 0 (= initial value)
|
|
||||||
CompositeModeClear
|
|
||||||
CompositeModeCopy
|
|
||||||
CompositeModeDestination
|
|
||||||
CompositeModeDestinationOver
|
|
||||||
CompositeModeSourceIn
|
|
||||||
CompositeModeDestinationIn
|
|
||||||
CompositeModeSourceOut
|
|
||||||
CompositeModeDestinationOut
|
|
||||||
CompositeModeSourceAtop
|
|
||||||
CompositeModeDestinationAtop
|
|
||||||
CompositeModeXor
|
|
||||||
CompositeModeLighter
|
|
||||||
CompositeModeMultiply
|
|
||||||
|
|
||||||
CompositeModeMax = CompositeModeMultiply
|
|
||||||
)
|
|
||||||
|
|
||||||
type BlendFactor int
|
|
||||||
|
|
||||||
const (
|
|
||||||
BlendFactorZero BlendFactor = iota
|
|
||||||
BlendFactorOne
|
|
||||||
BlendFactorSourceAlpha
|
|
||||||
BlendFactorDestinationAlpha
|
|
||||||
BlendFactorOneMinusSourceAlpha
|
|
||||||
BlendFactorOneMinusDestinationAlpha
|
|
||||||
BlendFactorDestinationColor
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c CompositeMode) BlendFactors() (src BlendFactor, dst BlendFactor) {
|
|
||||||
switch c {
|
|
||||||
case CompositeModeSourceOver:
|
|
||||||
return BlendFactorOne, BlendFactorOneMinusSourceAlpha
|
|
||||||
case CompositeModeClear:
|
|
||||||
return BlendFactorZero, BlendFactorZero
|
|
||||||
case CompositeModeCopy:
|
|
||||||
return BlendFactorOne, BlendFactorZero
|
|
||||||
case CompositeModeDestination:
|
|
||||||
return BlendFactorZero, BlendFactorOne
|
|
||||||
case CompositeModeDestinationOver:
|
|
||||||
return BlendFactorOneMinusDestinationAlpha, BlendFactorOne
|
|
||||||
case CompositeModeSourceIn:
|
|
||||||
return BlendFactorDestinationAlpha, BlendFactorZero
|
|
||||||
case CompositeModeDestinationIn:
|
|
||||||
return BlendFactorZero, BlendFactorSourceAlpha
|
|
||||||
case CompositeModeSourceOut:
|
|
||||||
return BlendFactorOneMinusDestinationAlpha, BlendFactorZero
|
|
||||||
case CompositeModeDestinationOut:
|
|
||||||
return BlendFactorZero, BlendFactorOneMinusSourceAlpha
|
|
||||||
case CompositeModeSourceAtop:
|
|
||||||
return BlendFactorDestinationAlpha, BlendFactorOneMinusSourceAlpha
|
|
||||||
case CompositeModeDestinationAtop:
|
|
||||||
return BlendFactorOneMinusDestinationAlpha, BlendFactorSourceAlpha
|
|
||||||
case CompositeModeXor:
|
|
||||||
return BlendFactorOneMinusDestinationAlpha, BlendFactorOneMinusSourceAlpha
|
|
||||||
case CompositeModeLighter:
|
|
||||||
return BlendFactorOne, BlendFactorOne
|
|
||||||
case CompositeModeMultiply:
|
|
||||||
return BlendFactorDestinationColor, BlendFactorZero
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("graphicsdriver: invalid composite mode: %d", c))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1190,7 +1190,7 @@ func (g *Graphics) NewShader(program *shaderir.Program) (graphicsdriver.Shader,
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
||||||
if shaderID == graphicsdriver.InvalidShaderID {
|
if shaderID == graphicsdriver.InvalidShaderID {
|
||||||
return fmt.Errorf("directx: shader ID is invalid")
|
return fmt.Errorf("directx: shader ID is invalid")
|
||||||
}
|
}
|
||||||
@ -1315,7 +1315,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
|||||||
})
|
})
|
||||||
|
|
||||||
if evenOdd {
|
if evenOdd {
|
||||||
s, err := shader.pipelineState(mode, prepareStencil, dst.screen)
|
s, err := shader.pipelineState(blend, prepareStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1323,7 +1323,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err = shader.pipelineState(mode, drawWithStencil, dst.screen)
|
s, err = shader.pipelineState(blend, drawWithStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1331,7 +1331,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s, err := shader.pipelineState(mode, noStencil, dst.screen)
|
s, err := shader.pipelineState(blend, noStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1773,9 +1773,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type pipelineStateKey struct {
|
type pipelineStateKey struct {
|
||||||
compositeMode graphicsdriver.CompositeMode
|
blend graphicsdriver.Blend
|
||||||
stencilMode stencilMode
|
stencilMode stencilMode
|
||||||
screen bool
|
screen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
@ -1812,17 +1812,17 @@ func (s *Shader) disposeImpl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) pipelineState(compositeMode graphicsdriver.CompositeMode, stencilMode stencilMode, screen bool) (*_ID3D12PipelineState, error) {
|
func (s *Shader) pipelineState(blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (*_ID3D12PipelineState, error) {
|
||||||
key := pipelineStateKey{
|
key := pipelineStateKey{
|
||||||
compositeMode: compositeMode,
|
blend: blend,
|
||||||
stencilMode: stencilMode,
|
stencilMode: stencilMode,
|
||||||
screen: screen,
|
screen: screen,
|
||||||
}
|
}
|
||||||
if state, ok := s.pipelineStates[key]; ok {
|
if state, ok := s.pipelineStates[key]; ok {
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := s.graphics.pipelineStates.newPipelineState(s.graphics.device, s.vertexShader, s.pixelShader, compositeMode, stencilMode, screen)
|
state, err := s.graphics.pipelineStates.newPipelineState(s.graphics.device, s.vertexShader, s.pixelShader, blend, stencilMode, screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ import (
|
|||||||
|
|
||||||
const numDescriptorsPerFrame = 32
|
const numDescriptorsPerFrame = 32
|
||||||
|
|
||||||
func blendFactorToBlend(c graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
func blendFactorToBlend(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||||
switch c {
|
switch f {
|
||||||
case graphicsdriver.BlendFactorZero:
|
case graphicsdriver.BlendFactorZero:
|
||||||
return _D3D12_BLEND_ZERO
|
return _D3D12_BLEND_ZERO
|
||||||
case graphicsdriver.BlendFactorOne:
|
case graphicsdriver.BlendFactorOne:
|
||||||
@ -40,12 +40,23 @@ func blendFactorToBlend(c graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
|||||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||||
case graphicsdriver.BlendFactorDestinationColor:
|
case graphicsdriver.BlendFactorDestinationColor:
|
||||||
|
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
||||||
|
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
||||||
if alpha {
|
if alpha {
|
||||||
return _D3D12_BLEND_DEST_ALPHA
|
return _D3D12_BLEND_DEST_ALPHA
|
||||||
}
|
}
|
||||||
return _D3D12_BLEND_DEST_COLOR
|
return _D3D12_BLEND_DEST_COLOR
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("directx: invalid blend factor: %d", c))
|
panic(fmt.Sprintf("directx: invalid blend factor: %d", f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func blendOperationToBlendOp(o graphicsdriver.BlendOperation) _D3D12_BLEND_OP {
|
||||||
|
switch o {
|
||||||
|
case graphicsdriver.BlendOperationAdd:
|
||||||
|
return _D3D12_BLEND_OP_ADD
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +347,7 @@ func newShader(source []byte, defs []_D3D_SHADER_MACRO) (vsh, psh *_ID3DBlob, fe
|
|||||||
return v, p, nil
|
return v, p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3DBlob, compositeMode graphicsdriver.CompositeMode, stencilMode stencilMode, screen bool) (state *_ID3D12PipelineState, ferr error) {
|
func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3DBlob, blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (state *_ID3D12PipelineState, ferr error) {
|
||||||
rootSignature, err := p.ensureRootSignature(device)
|
rootSignature, err := p.ensureRootSignature(device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -391,7 +402,6 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a pipeline state.
|
// Create a pipeline state.
|
||||||
srcOp, dstOp := compositeMode.BlendFactors()
|
|
||||||
psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{
|
psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{
|
||||||
pRootSignature: rootSignature,
|
pRootSignature: rootSignature,
|
||||||
VS: _D3D12_SHADER_BYTECODE{
|
VS: _D3D12_SHADER_BYTECODE{
|
||||||
@ -409,12 +419,12 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
{
|
{
|
||||||
BlendEnable: 1,
|
BlendEnable: 1,
|
||||||
LogicOpEnable: 0,
|
LogicOpEnable: 0,
|
||||||
SrcBlend: blendFactorToBlend(srcOp, false),
|
SrcBlend: blendFactorToBlend(blend.BlendFactorSourceColor, false),
|
||||||
DestBlend: blendFactorToBlend(dstOp, false),
|
DestBlend: blendFactorToBlend(blend.BlendFactorDestinationColor, false),
|
||||||
BlendOp: _D3D12_BLEND_OP_ADD,
|
BlendOp: blendOperationToBlendOp(blend.BlendOperationColor),
|
||||||
SrcBlendAlpha: blendFactorToBlend(srcOp, true),
|
SrcBlendAlpha: blendFactorToBlend(blend.BlendFactorSourceAlpha, true),
|
||||||
DestBlendAlpha: blendFactorToBlend(dstOp, true),
|
DestBlendAlpha: blendFactorToBlend(blend.BlendFactorDestinationAlpha, true),
|
||||||
BlendOpAlpha: _D3D12_BLEND_OP_ADD,
|
BlendOpAlpha: blendOperationToBlendOp(blend.BlendOperationAlpha),
|
||||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||||
RenderTargetWriteMask: writeMask,
|
RenderTargetWriteMask: writeMask,
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ type Graphics interface {
|
|||||||
NewShader(program *shaderir.Program) (Shader, error)
|
NewShader(program *shaderir.Program) (Shader, error)
|
||||||
|
|
||||||
// DrawTriangles draws an image onto another image with the given parameters.
|
// DrawTriangles draws an image onto another image with the given parameters.
|
||||||
DrawTriangles(dst ImageID, srcs [graphics.ShaderImageCount]ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, dstRegion, srcRegion Region, uniforms [][]float32, evenOdd bool) error
|
DrawTriangles(dst ImageID, srcs [graphics.ShaderImageCount]ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, blend Blend, dstRegion, srcRegion Region, uniforms [][]float32, evenOdd bool) 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.
|
||||||
|
@ -317,7 +317,16 @@ func blendFactorToMetalBlendFactor(c graphicsdriver.BlendFactor) mtl.BlendFactor
|
|||||||
case graphicsdriver.BlendFactorDestinationColor:
|
case graphicsdriver.BlendFactorDestinationColor:
|
||||||
return mtl.BlendFactorDestinationColor
|
return mtl.BlendFactorDestinationColor
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("metal: invalid operation: %d", c))
|
panic(fmt.Sprintf("metal: invalid blend factor: %d", c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func blendOperationToMetalBlendOperation(o graphicsdriver.BlendOperation) mtl.BlendOperation {
|
||||||
|
switch o {
|
||||||
|
case graphicsdriver.BlendOperationAdd:
|
||||||
|
return mtl.BlendOperationAdd
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("metal: invalid blend operation: %d", o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +487,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graph
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
||||||
if shaderID == graphicsdriver.InvalidShaderID {
|
if shaderID == graphicsdriver.InvalidShaderID {
|
||||||
return fmt.Errorf("metal: shader ID is invalid")
|
return fmt.Errorf("metal: shader ID is invalid")
|
||||||
}
|
}
|
||||||
@ -575,14 +584,14 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if evenOdd {
|
if evenOdd {
|
||||||
prepareStencilRpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, mode, prepareStencil, dst.screen)
|
prepareStencilRpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, blend, prepareStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := g.draw(prepareStencilRpss, dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, prepareStencil); err != nil {
|
if err := g.draw(prepareStencilRpss, dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, prepareStencil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
drawWithStencilRpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, mode, drawWithStencil, dst.screen)
|
drawWithStencilRpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, blend, drawWithStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -590,7 +599,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, mode, noStencil, dst.screen)
|
rpss, err := g.shaders[shaderID].RenderPipelineState(&g.view, blend, noStencil, dst.screen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -290,6 +290,16 @@ const (
|
|||||||
BlendFactorOneMinusSource1Alpha BlendFactor = 18
|
BlendFactorOneMinusSource1Alpha BlendFactor = 18
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type BlendOperation uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
BlendOperationAdd BlendOperation = 0
|
||||||
|
BlendOperationSubtract BlendOperation = 1
|
||||||
|
BlendOperationReverseSubtract BlendOperation = 2
|
||||||
|
BlendOperationMin BlendOperation = 3
|
||||||
|
BlendOperationMax BlendOperation = 4
|
||||||
|
)
|
||||||
|
|
||||||
type ColorWriteMask uint8
|
type ColorWriteMask uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -383,6 +393,8 @@ type RenderPipelineColorAttachmentDescriptor struct {
|
|||||||
DestinationRGBBlendFactor BlendFactor
|
DestinationRGBBlendFactor BlendFactor
|
||||||
SourceAlphaBlendFactor BlendFactor
|
SourceAlphaBlendFactor BlendFactor
|
||||||
SourceRGBBlendFactor BlendFactor
|
SourceRGBBlendFactor BlendFactor
|
||||||
|
AlphaBlendOperation BlendOperation
|
||||||
|
RGBBlendOperation BlendOperation
|
||||||
|
|
||||||
WriteMask ColorWriteMask
|
WriteMask ColorWriteMask
|
||||||
}
|
}
|
||||||
@ -492,6 +504,8 @@ var (
|
|||||||
sel_setDestinationRGBBlendFactor = objc.RegisterName("setDestinationRGBBlendFactor:")
|
sel_setDestinationRGBBlendFactor = objc.RegisterName("setDestinationRGBBlendFactor:")
|
||||||
sel_setSourceAlphaBlendFactor = objc.RegisterName("setSourceAlphaBlendFactor:")
|
sel_setSourceAlphaBlendFactor = objc.RegisterName("setSourceAlphaBlendFactor:")
|
||||||
sel_setSourceRGBBlendFactor = objc.RegisterName("setSourceRGBBlendFactor:")
|
sel_setSourceRGBBlendFactor = objc.RegisterName("setSourceRGBBlendFactor:")
|
||||||
|
sel_setAlphaBlendOperation = objc.RegisterName("setAlphaBlendOperation:")
|
||||||
|
sel_setRgbBlendOperation = objc.RegisterName("setRgbBlendOperation:")
|
||||||
sel_setWriteMask = objc.RegisterName("setWriteMask:")
|
sel_setWriteMask = objc.RegisterName("setWriteMask:")
|
||||||
sel_setStencilAttachmentPixelFormat = objc.RegisterName("setStencilAttachmentPixelFormat:")
|
sel_setStencilAttachmentPixelFormat = objc.RegisterName("setStencilAttachmentPixelFormat:")
|
||||||
sel_newRenderPipelineStateWithDescriptor_error = objc.RegisterName("newRenderPipelineStateWithDescriptor:error:")
|
sel_newRenderPipelineStateWithDescriptor_error = objc.RegisterName("newRenderPipelineStateWithDescriptor:error:")
|
||||||
@ -624,6 +638,8 @@ func (d Device) MakeRenderPipelineState(rpd RenderPipelineDescriptor) (RenderPip
|
|||||||
colorAttachments0.Send(sel_setDestinationRGBBlendFactor, uintptr(rpd.ColorAttachments[0].DestinationRGBBlendFactor))
|
colorAttachments0.Send(sel_setDestinationRGBBlendFactor, uintptr(rpd.ColorAttachments[0].DestinationRGBBlendFactor))
|
||||||
colorAttachments0.Send(sel_setSourceAlphaBlendFactor, uintptr(rpd.ColorAttachments[0].SourceAlphaBlendFactor))
|
colorAttachments0.Send(sel_setSourceAlphaBlendFactor, uintptr(rpd.ColorAttachments[0].SourceAlphaBlendFactor))
|
||||||
colorAttachments0.Send(sel_setSourceRGBBlendFactor, uintptr(rpd.ColorAttachments[0].SourceRGBBlendFactor))
|
colorAttachments0.Send(sel_setSourceRGBBlendFactor, uintptr(rpd.ColorAttachments[0].SourceRGBBlendFactor))
|
||||||
|
colorAttachments0.Send(sel_setAlphaBlendOperation, uintptr(rpd.ColorAttachments[0].AlphaBlendOperation))
|
||||||
|
colorAttachments0.Send(sel_setRgbBlendOperation, uintptr(rpd.ColorAttachments[0].RGBBlendOperation))
|
||||||
colorAttachments0.Send(sel_setWriteMask, uintptr(rpd.ColorAttachments[0].WriteMask))
|
colorAttachments0.Send(sel_setWriteMask, uintptr(rpd.ColorAttachments[0].WriteMask))
|
||||||
renderPipelineDescriptor.Send(sel_setStencilAttachmentPixelFormat, uintptr(rpd.StencilAttachmentPixelFormat))
|
renderPipelineDescriptor.Send(sel_setStencilAttachmentPixelFormat, uintptr(rpd.StencilAttachmentPixelFormat))
|
||||||
var err cocoa.NSError
|
var err cocoa.NSError
|
||||||
|
@ -24,9 +24,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type shaderRpsKey struct {
|
type shaderRpsKey struct {
|
||||||
compositeMode graphicsdriver.CompositeMode
|
blend graphicsdriver.Blend
|
||||||
stencilMode stencilMode
|
stencilMode stencilMode
|
||||||
screen bool
|
screen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
@ -86,11 +86,11 @@ func (s *Shader) init(device mtl.Device) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) RenderPipelineState(view *view, compositeMode graphicsdriver.CompositeMode, stencilMode stencilMode, screen bool) (mtl.RenderPipelineState, error) {
|
func (s *Shader) RenderPipelineState(view *view, blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (mtl.RenderPipelineState, error) {
|
||||||
key := shaderRpsKey{
|
key := shaderRpsKey{
|
||||||
compositeMode: compositeMode,
|
blend: blend,
|
||||||
stencilMode: stencilMode,
|
stencilMode: stencilMode,
|
||||||
screen: screen,
|
screen: screen,
|
||||||
}
|
}
|
||||||
if rps, ok := s.rpss[key]; ok {
|
if rps, ok := s.rpss[key]; ok {
|
||||||
return rps, nil
|
return rps, nil
|
||||||
@ -112,11 +112,13 @@ func (s *Shader) RenderPipelineState(view *view, compositeMode graphicsdriver.Co
|
|||||||
rpld.ColorAttachments[0].PixelFormat = pix
|
rpld.ColorAttachments[0].PixelFormat = pix
|
||||||
rpld.ColorAttachments[0].BlendingEnabled = true
|
rpld.ColorAttachments[0].BlendingEnabled = true
|
||||||
|
|
||||||
src, dst := compositeMode.BlendFactors()
|
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorDestinationAlpha)
|
||||||
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = blendFactorToMetalBlendFactor(dst)
|
rpld.ColorAttachments[0].DestinationRGBBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorDestinationColor)
|
||||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = blendFactorToMetalBlendFactor(dst)
|
rpld.ColorAttachments[0].SourceAlphaBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorSourceAlpha)
|
||||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = blendFactorToMetalBlendFactor(src)
|
rpld.ColorAttachments[0].SourceRGBBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorSourceColor)
|
||||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = blendFactorToMetalBlendFactor(src)
|
rpld.ColorAttachments[0].AlphaBlendOperation = blendOperationToMetalBlendOperation(blend.BlendOperationAlpha)
|
||||||
|
rpld.ColorAttachments[0].RGBBlendOperation = blendOperationToMetalBlendOperation(blend.BlendOperationColor)
|
||||||
|
|
||||||
if stencilMode == prepareStencil {
|
if stencilMode == prepareStencil {
|
||||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,8 +33,14 @@ const (
|
|||||||
glZero blendFactor = 0
|
glZero blendFactor = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func convertBlendFactor(op graphicsdriver.BlendFactor) blendFactor {
|
type blendOperation int
|
||||||
switch op {
|
|
||||||
|
const (
|
||||||
|
glAdd blendOperation = 0x104
|
||||||
|
)
|
||||||
|
|
||||||
|
func convertBlendFactor(f graphicsdriver.BlendFactor) blendFactor {
|
||||||
|
switch f {
|
||||||
case graphicsdriver.BlendFactorZero:
|
case graphicsdriver.BlendFactorZero:
|
||||||
return glZero
|
return glZero
|
||||||
case graphicsdriver.BlendFactorOne:
|
case graphicsdriver.BlendFactorOne:
|
||||||
@ -50,7 +56,16 @@ func convertBlendFactor(op graphicsdriver.BlendFactor) blendFactor {
|
|||||||
case graphicsdriver.BlendFactorDestinationColor:
|
case graphicsdriver.BlendFactorDestinationColor:
|
||||||
return glDstColor
|
return glDstColor
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("opengl: invalid blend factor %d at convertBlendFactor", op))
|
panic(fmt.Sprintf("opengl: invalid blend factor %d", f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertBlendOperation(o graphicsdriver.BlendOperation) blendOperation {
|
||||||
|
switch o {
|
||||||
|
case graphicsdriver.BlendOperationAdd:
|
||||||
|
return glAdd
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("opengl: invalid blend operation %d", o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +77,7 @@ type context struct {
|
|||||||
lastRenderbuffer renderbufferNative
|
lastRenderbuffer renderbufferNative
|
||||||
lastViewportWidth int
|
lastViewportWidth int
|
||||||
lastViewportHeight int
|
lastViewportHeight int
|
||||||
lastCompositeMode graphicsdriver.CompositeMode
|
lastBlend graphicsdriver.Blend
|
||||||
maxTextureSize int
|
maxTextureSize int
|
||||||
maxTextureSizeOnce sync.Once
|
maxTextureSizeOnce sync.Once
|
||||||
highp bool
|
highp bool
|
||||||
|
@ -100,11 +100,11 @@ func (c *context) reset() error {
|
|||||||
c.lastFramebuffer = invalidFramebuffer
|
c.lastFramebuffer = invalidFramebuffer
|
||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
|
||||||
gl.Enable(gl.BLEND)
|
gl.Enable(gl.BLEND)
|
||||||
gl.Enable(gl.SCISSOR_TEST)
|
gl.Enable(gl.SCISSOR_TEST)
|
||||||
|
|
||||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
// Set the source over blending.
|
||||||
|
c.blend(graphicsdriver.BlendSourceOver)
|
||||||
|
|
||||||
f := int32(0)
|
f := int32(0)
|
||||||
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
|
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
|
||||||
@ -112,14 +112,21 @@ func (c *context) reset() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||||
if c.lastCompositeMode == mode {
|
if c.lastBlend == blend {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.lastCompositeMode = mode
|
c.lastBlend = blend
|
||||||
s, d := mode.BlendFactors()
|
gl.BlendFuncSeparate(
|
||||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
uint32(convertBlendFactor(blend.BlendFactorSourceColor)),
|
||||||
gl.BlendFunc(uint32(s2), uint32(d2))
|
uint32(convertBlendFactor(blend.BlendFactorDestinationColor)),
|
||||||
|
uint32(convertBlendFactor(blend.BlendFactorSourceAlpha)),
|
||||||
|
uint32(convertBlendFactor(blend.BlendFactorDestinationAlpha)),
|
||||||
|
)
|
||||||
|
gl.BlendEquationSeparate(
|
||||||
|
uint32(convertBlendOperation(blend.BlendOperationColor)),
|
||||||
|
uint32(convertBlendOperation(blend.BlendOperationAlpha)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) scissor(x, y, width, height int) {
|
func (c *context) scissor(x, y, width, height int) {
|
||||||
|
@ -93,10 +93,9 @@ func (c *context) reset() error {
|
|||||||
c.lastFramebuffer = invalidFramebuffer
|
c.lastFramebuffer = invalidFramebuffer
|
||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
|
||||||
c.ctx.Enable(gles.BLEND)
|
c.ctx.Enable(gles.BLEND)
|
||||||
c.ctx.Enable(gles.SCISSOR_TEST)
|
c.ctx.Enable(gles.SCISSOR_TEST)
|
||||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
c.blend(graphicsdriver.BlendSourceOver)
|
||||||
f := make([]int32, 1)
|
f := make([]int32, 1)
|
||||||
c.ctx.GetIntegerv(f, gles.FRAMEBUFFER_BINDING)
|
c.ctx.GetIntegerv(f, gles.FRAMEBUFFER_BINDING)
|
||||||
c.screenFramebuffer = framebufferNative(f[0])
|
c.screenFramebuffer = framebufferNative(f[0])
|
||||||
@ -104,14 +103,20 @@ func (c *context) reset() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||||
if c.lastCompositeMode == mode {
|
if c.lastBlend == blend {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.lastCompositeMode = mode
|
c.ctx.BlendFuncSeparate(
|
||||||
s, d := mode.BlendFactors()
|
uint32(convertBlendFactor(blend.BlendFactorSourceColor)),
|
||||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
uint32(convertBlendFactor(blend.BlendFactorDestinationColor)),
|
||||||
c.ctx.BlendFunc(uint32(s2), uint32(d2))
|
uint32(convertBlendFactor(blend.BlendFactorSourceAlpha)),
|
||||||
|
uint32(convertBlendFactor(blend.BlendFactorDestinationAlpha)),
|
||||||
|
)
|
||||||
|
c.ctx.BlendEquationSeparate(
|
||||||
|
uint32(convertBlendOperation(blend.BlendOperationColor)),
|
||||||
|
uint32(convertBlendOperation(blend.BlendOperationAlpha)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) scissor(x, y, width, height int) {
|
func (c *context) scissor(x, y, width, height int) {
|
||||||
|
@ -163,7 +163,6 @@ func (c *context) reset() error {
|
|||||||
c.lastFramebuffer = framebufferNative(js.Null())
|
c.lastFramebuffer = framebufferNative(js.Null())
|
||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
|
||||||
|
|
||||||
if err := c.initGL(); err != nil {
|
if err := c.initGL(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -175,7 +174,7 @@ func (c *context) reset() error {
|
|||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.enable.Invoke(gles.BLEND)
|
gl.enable.Invoke(gles.BLEND)
|
||||||
gl.enable.Invoke(gles.SCISSOR_TEST)
|
gl.enable.Invoke(gles.SCISSOR_TEST)
|
||||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
c.blend(graphicsdriver.BlendSourceOver)
|
||||||
f := gl.getParameter.Invoke(gles.FRAMEBUFFER_BINDING)
|
f := gl.getParameter.Invoke(gles.FRAMEBUFFER_BINDING)
|
||||||
c.screenFramebuffer = framebufferNative(f)
|
c.screenFramebuffer = framebufferNative(f)
|
||||||
|
|
||||||
@ -185,15 +184,22 @@ func (c *context) reset() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||||
if c.lastCompositeMode == mode {
|
if c.lastBlend == blend {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.lastCompositeMode = mode
|
c.lastBlend = blend
|
||||||
s, d := mode.BlendFactors()
|
|
||||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.blendFunc.Invoke(int(s2), int(d2))
|
gl.blendFuncSeparate.Invoke(
|
||||||
|
int(convertBlendFactor(blend.BlendFactorSourceColor)),
|
||||||
|
int(convertBlendFactor(blend.BlendFactorDestinationColor)),
|
||||||
|
int(convertBlendFactor(blend.BlendFactorSourceAlpha)),
|
||||||
|
int(convertBlendFactor(blend.BlendFactorDestinationAlpha)),
|
||||||
|
)
|
||||||
|
gl.blendEquationSeparate.Invoke(
|
||||||
|
int(convertBlendOperation(blend.BlendOperationColor)),
|
||||||
|
int(convertBlendOperation(blend.BlendOperationAlpha)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) scissor(x, y, width, height int) {
|
func (c *context) scissor(x, y, width, height int) {
|
||||||
|
@ -102,7 +102,8 @@ package gl
|
|||||||
// typedef void (APIENTRYP GPBINDFRAMEBUFFEREXT)(GLenum target, GLuint framebuffer);
|
// typedef void (APIENTRYP GPBINDFRAMEBUFFEREXT)(GLenum target, GLuint framebuffer);
|
||||||
// typedef void (APIENTRYP GPBINDRENDERBUFFEREXT)(GLenum target, GLuint renderbuffer);
|
// typedef void (APIENTRYP GPBINDRENDERBUFFEREXT)(GLenum target, GLuint renderbuffer);
|
||||||
// typedef void (APIENTRYP GPBINDTEXTURE)(GLenum target, GLuint texture);
|
// typedef void (APIENTRYP GPBINDTEXTURE)(GLenum target, GLuint texture);
|
||||||
// typedef void (APIENTRYP GPBLENDFUNC)(GLenum sfactor, GLenum dfactor);
|
// typedef void (APIENTRYP GPBLENDEQUATIONSEPARATE)(GLenum modeRGB, GLenum modeAlpha);
|
||||||
|
// typedef void (APIENTRYP GPBLENDFUNCSEPARATE)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
|
||||||
// typedef void (APIENTRYP GPBUFFERDATA)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
|
// typedef void (APIENTRYP GPBUFFERDATA)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
|
||||||
// typedef void (APIENTRYP GPBUFFERSUBDATA)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
|
// typedef void (APIENTRYP GPBUFFERSUBDATA)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
|
||||||
// typedef GLenum (APIENTRYP GPCHECKFRAMEBUFFERSTATUSEXT)(GLenum target);
|
// typedef GLenum (APIENTRYP GPCHECKFRAMEBUFFERSTATUSEXT)(GLenum target);
|
||||||
@ -197,8 +198,11 @@ package gl
|
|||||||
// static void glowBindTexture(GPBINDTEXTURE fnptr, GLenum target, GLuint texture) {
|
// static void glowBindTexture(GPBINDTEXTURE fnptr, GLenum target, GLuint texture) {
|
||||||
// (*fnptr)(target, texture);
|
// (*fnptr)(target, texture);
|
||||||
// }
|
// }
|
||||||
// static void glowBlendFunc(GPBLENDFUNC fnptr, GLenum sfactor, GLenum dfactor) {
|
// static void glowBlendEquationSeparate(GPBLENDEQUATIONSEPARATE fnptr, GLenum modeRGB, GLenum modeAlpha) {
|
||||||
// (*fnptr)(sfactor, dfactor);
|
// (*fnptr)(modeRGB, modeAlpha);
|
||||||
|
// }
|
||||||
|
// static void glowBlendFuncSeparate(GPBLENDFUNCSEPARATE fnptr, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
|
||||||
|
// (*fnptr)(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
// }
|
// }
|
||||||
// static void glowBufferData(GPBUFFERDATA fnptr, GLenum target, GLsizeiptr size, const void * data, GLenum usage) {
|
// static void glowBufferData(GPBUFFERDATA fnptr, GLenum target, GLsizeiptr size, const void * data, GLenum usage) {
|
||||||
// (*fnptr)(target, size, data, usage);
|
// (*fnptr)(target, size, data, usage);
|
||||||
@ -431,7 +435,8 @@ var (
|
|||||||
gpBindFramebufferEXT C.GPBINDFRAMEBUFFEREXT
|
gpBindFramebufferEXT C.GPBINDFRAMEBUFFEREXT
|
||||||
gpBindRenderbufferEXT C.GPBINDRENDERBUFFEREXT
|
gpBindRenderbufferEXT C.GPBINDRENDERBUFFEREXT
|
||||||
gpBindTexture C.GPBINDTEXTURE
|
gpBindTexture C.GPBINDTEXTURE
|
||||||
gpBlendFunc C.GPBLENDFUNC
|
gpBlendEquationSeparate C.GPBLENDEQUATIONSEPARATE
|
||||||
|
gpBlendFuncSeparate C.GPBLENDFUNCSEPARATE
|
||||||
gpBufferData C.GPBUFFERDATA
|
gpBufferData C.GPBUFFERDATA
|
||||||
gpBufferSubData C.GPBUFFERSUBDATA
|
gpBufferSubData C.GPBUFFERSUBDATA
|
||||||
gpCheckFramebufferStatusEXT C.GPCHECKFRAMEBUFFERSTATUSEXT
|
gpCheckFramebufferStatusEXT C.GPCHECKFRAMEBUFFERSTATUSEXT
|
||||||
@ -541,8 +546,12 @@ func BindTexture(target uint32, texture uint32) {
|
|||||||
C.glowBindTexture(gpBindTexture, (C.GLenum)(target), (C.GLuint)(texture))
|
C.glowBindTexture(gpBindTexture, (C.GLenum)(target), (C.GLuint)(texture))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BlendFunc(sfactor uint32, dfactor uint32) {
|
func BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||||
C.glowBlendFunc(gpBlendFunc, (C.GLenum)(sfactor), (C.GLenum)(dfactor))
|
C.glowBlendEquationSeparate(gpBlendEquationSeparate, (C.GLenum)(modeRGB), (C.GLenum)(modeAlpha))
|
||||||
|
}
|
||||||
|
|
||||||
|
func BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
|
||||||
|
C.glowBlendFuncSeparate(gpBlendFuncSeparate, (C.GLenum)(srcRGB), (C.GLenum)(dstRGB), (C.GLenum)(srcAlpha), (C.GLenum)(dstAlpha))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) {
|
func BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) {
|
||||||
@ -861,9 +870,13 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
|||||||
if gpBindTexture == nil {
|
if gpBindTexture == nil {
|
||||||
return errors.New("gl: glBindTexture is missing")
|
return errors.New("gl: glBindTexture is missing")
|
||||||
}
|
}
|
||||||
gpBlendFunc = (C.GPBLENDFUNC)(getProcAddr("glBlendFunc"))
|
gpBlendEquationSeparate = (C.GPBLENDEQUATIONSEPARATE)(getProcAddr("glBlendEquationSeparate"))
|
||||||
if gpBlendFunc == nil {
|
if gpBlendEquationSeparate == nil {
|
||||||
return errors.New("gl: glBlendFunc is missing")
|
return errors.New("gl: glBlendEquationSeparate is missing")
|
||||||
|
}
|
||||||
|
gpBlendFuncSeparate = (C.GPBLENDFUNCSEPARATE)(getProcAddr("glBlendFuncSeparate"))
|
||||||
|
if gpBlendFuncSeparate == nil {
|
||||||
|
return errors.New("gl: glBlendFuncSeparate is missing")
|
||||||
}
|
}
|
||||||
gpBufferData = (C.GPBUFFERDATA)(getProcAddr("glBufferData"))
|
gpBufferData = (C.GPBUFFERDATA)(getProcAddr("glBufferData"))
|
||||||
if gpBufferData == nil {
|
if gpBufferData == nil {
|
||||||
|
@ -20,7 +20,8 @@ var (
|
|||||||
gpBindFramebufferEXT uintptr
|
gpBindFramebufferEXT uintptr
|
||||||
gpBindRenderbufferEXT uintptr
|
gpBindRenderbufferEXT uintptr
|
||||||
gpBindTexture uintptr
|
gpBindTexture uintptr
|
||||||
gpBlendFunc uintptr
|
gpBlendEquationSeparate uintptr
|
||||||
|
gpBlendFuncSeparate uintptr
|
||||||
gpBufferData uintptr
|
gpBufferData uintptr
|
||||||
gpBufferSubData uintptr
|
gpBufferSubData uintptr
|
||||||
gpCheckFramebufferStatusEXT uintptr
|
gpCheckFramebufferStatusEXT uintptr
|
||||||
@ -130,8 +131,12 @@ func BindTexture(target uint32, texture uint32) {
|
|||||||
purego.SyscallN(gpBindTexture, uintptr(target), uintptr(texture))
|
purego.SyscallN(gpBindTexture, uintptr(target), uintptr(texture))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BlendFunc(sfactor uint32, dfactor uint32) {
|
func BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||||
purego.SyscallN(gpBlendFunc, uintptr(sfactor), uintptr(dfactor))
|
purego.SyscallN(gpBlendEquationSeparate, uintptr(modeRGB), uintptr(modeAlpha))
|
||||||
|
}
|
||||||
|
|
||||||
|
func BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
|
||||||
|
purego.SyscallN(gpBlendFuncSeparate, uintptr(srcRGB), uintptr(dstRGB), uintptr(srcAlpha), uintptr(dstAlpha))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) {
|
func BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) {
|
||||||
@ -450,9 +455,13 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
|||||||
if gpBindTexture == 0 {
|
if gpBindTexture == 0 {
|
||||||
return errors.New("gl: glBindTexture is missing")
|
return errors.New("gl: glBindTexture is missing")
|
||||||
}
|
}
|
||||||
gpBlendFunc = getProcAddr("glBlendFunc")
|
gpBlendEquationSeparate = getProcAddr("glBlendEquationSeparate")
|
||||||
if gpBlendFunc == 0 {
|
if gpBlendEquationSeparate == 0 {
|
||||||
return errors.New("gl: glBlendFunc is missing")
|
return errors.New("gl: glBlendEquationSeparate is missing")
|
||||||
|
}
|
||||||
|
gpBlendFuncSeparate = getProcAddr("glBlendFuncSeparate")
|
||||||
|
if gpBlendFuncSeparate == 0 {
|
||||||
|
return errors.New("gl: glBlendFuncSeparate is missing")
|
||||||
}
|
}
|
||||||
gpBufferData = getProcAddr("glBufferData")
|
gpBufferData = getProcAddr("glBufferData")
|
||||||
if gpBufferData == 0 {
|
if gpBufferData == 0 {
|
||||||
|
@ -26,7 +26,8 @@ type gl struct {
|
|||||||
bindFramebuffer js.Value
|
bindFramebuffer js.Value
|
||||||
bindRenderbuffer js.Value
|
bindRenderbuffer js.Value
|
||||||
bindTexture js.Value
|
bindTexture js.Value
|
||||||
blendFunc js.Value
|
blendEquationSeparate js.Value
|
||||||
|
blendFuncSeparate js.Value
|
||||||
bufferData js.Value
|
bufferData js.Value
|
||||||
bufferSubData js.Value
|
bufferSubData js.Value
|
||||||
checkFramebufferStatus js.Value
|
checkFramebufferStatus js.Value
|
||||||
@ -103,7 +104,8 @@ func (c *context) newGL(v js.Value) *gl {
|
|||||||
bindFramebuffer: v.Get("bindFramebuffer").Call("bind", v),
|
bindFramebuffer: v.Get("bindFramebuffer").Call("bind", v),
|
||||||
bindRenderbuffer: v.Get("bindRenderbuffer").Call("bind", v),
|
bindRenderbuffer: v.Get("bindRenderbuffer").Call("bind", v),
|
||||||
bindTexture: v.Get("bindTexture").Call("bind", v),
|
bindTexture: v.Get("bindTexture").Call("bind", v),
|
||||||
blendFunc: v.Get("blendFunc").Call("bind", v),
|
blendEquationSeparate: v.Get("blendEquationSeparate").Call("bind", v),
|
||||||
|
blendFuncSeparate: v.Get("blendFuncSeparate").Call("bind", v),
|
||||||
bufferData: v.Get("bufferData").Call("bind", v),
|
bufferData: v.Get("bufferData").Call("bind", v),
|
||||||
bufferSubData: v.Get("bufferSubData").Call("bind", v),
|
bufferSubData: v.Get("bufferSubData").Call("bind", v),
|
||||||
checkFramebufferStatus: v.Get("checkFramebufferStatus").Call("bind", v),
|
checkFramebufferStatus: v.Get("checkFramebufferStatus").Call("bind", v),
|
||||||
|
@ -78,8 +78,12 @@ func (DefaultContext) BindTexture(target uint32, texture uint32) {
|
|||||||
C.glBindTexture(C.GLenum(target), C.GLuint(texture))
|
C.glBindTexture(C.GLenum(target), C.GLuint(texture))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (DefaultContext) BlendFunc(sfactor uint32, dfactor uint32) {
|
func (DefaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||||
C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
|
C.glBlendEquationSeparate(C.GLenum(modeRGB), C.GLenum(modeAlpha))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
|
||||||
|
C.glBlendFuncSeparate(C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (DefaultContext) BufferData(target uint32, size int, data []byte, usage uint32) {
|
func (DefaultContext) BufferData(target uint32, size int, data []byte, usage uint32) {
|
||||||
|
@ -64,8 +64,12 @@ func (g *GomobileContext) BindTexture(target uint32, texture uint32) {
|
|||||||
g.ctx.BindTexture(gl.Enum(target), gl.Texture{Value: texture})
|
g.ctx.BindTexture(gl.Enum(target), gl.Texture{Value: texture})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GomobileContext) BlendFunc(sfactor uint32, dfactor uint32) {
|
func (g *GomobileContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||||
g.ctx.BlendFunc(gl.Enum(sfactor), gl.Enum(dfactor))
|
g.ctx.BlendEquationSeparate(gl.Enum(modeRGB), gl.Enum(modeAlpha))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GomobileContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
|
||||||
|
g.ctx.BlendFuncSeparate(gl.Enum(srcRGB), gl.Enum(dstRGB), gl.Enum(srcAlpha), gl.Enum(dstAlpha))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GomobileContext) BufferData(target uint32, size int, data []byte, usage uint32) {
|
func (g *GomobileContext) BufferData(target uint32, size int, data []byte, usage uint32) {
|
||||||
|
@ -22,7 +22,8 @@ type Context interface {
|
|||||||
BindFramebuffer(target uint32, framebuffer uint32)
|
BindFramebuffer(target uint32, framebuffer uint32)
|
||||||
BindRenderbuffer(target uint32, renderbuffer uint32)
|
BindRenderbuffer(target uint32, renderbuffer uint32)
|
||||||
BindTexture(target uint32, texture uint32)
|
BindTexture(target uint32, texture uint32)
|
||||||
BlendFunc(sfactor uint32, dfactor uint32)
|
BlendEquationSeparate(modeRGB uint32, modeAlpha uint32)
|
||||||
|
BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32)
|
||||||
BufferData(target uint32, size int, data []byte, usage uint32)
|
BufferData(target uint32, size int, data []byte, usage uint32)
|
||||||
BufferSubData(target uint32, offset int, data []byte)
|
BufferSubData(target uint32, offset int, data []byte)
|
||||||
CheckFramebufferStatus(target uint32) uint32
|
CheckFramebufferStatus(target uint32) uint32
|
||||||
|
@ -180,7 +180,7 @@ func (g *Graphics) uniformVariableName(idx int) string {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, offsets [graphics.ShaderImageCount - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
|
||||||
if shaderID == graphicsdriver.InvalidShaderID {
|
if shaderID == graphicsdriver.InvalidShaderID {
|
||||||
return fmt.Errorf("opengl: shader ID is invalid")
|
return fmt.Errorf("opengl: shader ID is invalid")
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
|||||||
int(dstRegion.Width),
|
int(dstRegion.Width),
|
||||||
int(dstRegion.Height),
|
int(dstRegion.Height),
|
||||||
)
|
)
|
||||||
g.context.blendFunc(mode)
|
g.context.blend(blend)
|
||||||
|
|
||||||
shader := g.shaders[shaderID]
|
shader := g.shaders[shaderID]
|
||||||
program := shader.p
|
program := shader.p
|
||||||
|
@ -65,7 +65,7 @@ func (m *Mipmap) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byt
|
|||||||
return m.orig.ReadPixels(graphicsDriver, pixels, x, y, width, height)
|
return m.orig.ReadPixels(graphicsDriver, pixels, x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
||||||
if len(indices) == 0 {
|
if len(indices) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices
|
|||||||
imgs[i] = src.orig
|
imgs[i] = src.orig
|
||||||
}
|
}
|
||||||
|
|
||||||
m.orig.DrawTriangles(imgs, vertices, indices, mode, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd)
|
m.orig.DrawTriangles(imgs, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd)
|
||||||
m.disposeMipmaps()
|
m.disposeMipmaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ func (m *Mipmap) level(level int) *buffered.Image {
|
|||||||
Width: float32(w2),
|
Width: float32(w2),
|
||||||
Height: float32(h2),
|
Height: float32(h2),
|
||||||
}
|
}
|
||||||
s.DrawTriangles([graphics.ShaderImageCount]*buffered.Image{src}, vs, is, graphicsdriver.CompositeModeCopy, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, nil, false)
|
s.DrawTriangles([graphics.ShaderImageCount]*buffered.Image{src}, vs, is, graphicsdriver.BlendCopy, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, shader.shader, nil, false)
|
||||||
m.setImg(level, s)
|
m.setImg(level, s)
|
||||||
|
|
||||||
return m.imgs[level]
|
return m.imgs[level]
|
||||||
|
@ -76,7 +76,7 @@ type drawTrianglesHistoryItem struct {
|
|||||||
offsets [graphics.ShaderImageCount - 1][2]float32
|
offsets [graphics.ShaderImageCount - 1][2]float32
|
||||||
vertices []float32
|
vertices []float32
|
||||||
indices []uint16
|
indices []uint16
|
||||||
mode graphicsdriver.CompositeMode
|
blend graphicsdriver.Blend
|
||||||
dstRegion graphicsdriver.Region
|
dstRegion graphicsdriver.Region
|
||||||
srcRegion graphicsdriver.Region
|
srcRegion graphicsdriver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
@ -218,7 +218,7 @@ func (i *Image) Extend(width, height int) *Image {
|
|||||||
Width: float32(sw),
|
Width: float32(sw),
|
||||||
Height: float32(sh),
|
Height: float32(sh),
|
||||||
}
|
}
|
||||||
newImg.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, NearestFilterShader, nil, false)
|
newImg.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, NearestFilterShader, nil, false)
|
||||||
|
|
||||||
// Overwrite the history as if the image newImg is created only by WritePixels.
|
// Overwrite the history as if the image newImg is created only by WritePixels.
|
||||||
newImg.clearDrawTrianglesHistory()
|
newImg.clearDrawTrianglesHistory()
|
||||||
@ -264,7 +264,7 @@ func clearImage(i *graphicscommand.Image) {
|
|||||||
Width: float32(dw),
|
Width: float32(dw),
|
||||||
Height: float32(dh),
|
Height: float32(dh),
|
||||||
}
|
}
|
||||||
i.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.CompositeModeClear, dstRegion, graphicsdriver.Region{}, NearestFilterShader.shader, nil, false)
|
i.DrawTriangles(srcs, offsets, vs, is, graphicsdriver.BlendClear, dstRegion, graphicsdriver.Region{}, NearestFilterShader.shader, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasePixelsForTesting returns the image's basePixels for testing.
|
// BasePixelsForTesting returns the image's basePixels for testing.
|
||||||
@ -371,7 +371,7 @@ func (i *Image) WritePixels(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(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
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")
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
|||||||
if srcstale || !needsRestoring() || !i.needsRestoring() {
|
if srcstale || !needsRestoring() || !i.needsRestoring() {
|
||||||
i.makeStale(image.Rect(0, 0, i.width, i.height))
|
i.makeStale(image.Rect(0, 0, i.width, i.height))
|
||||||
} else {
|
} else {
|
||||||
i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, mode, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
var imgs [graphics.ShaderImageCount]*graphicscommand.Image
|
var imgs [graphics.ShaderImageCount]*graphicscommand.Image
|
||||||
@ -405,11 +405,11 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
|||||||
}
|
}
|
||||||
imgs[i] = src.image
|
imgs[i] = src.image
|
||||||
}
|
}
|
||||||
i.image.DrawTriangles(imgs, offsets, vertices, indices, mode, dstRegion, srcRegion, shader.shader, uniforms, evenOdd)
|
i.image.DrawTriangles(imgs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader.shader, uniforms, evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
||||||
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Image, offsets [graphics.ShaderImageCount - 1][2]float32, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
|
||||||
if i.stale || !i.needsRestoring() {
|
if i.stale || !i.needsRestoring() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Imag
|
|||||||
offsets: offsets,
|
offsets: offsets,
|
||||||
vertices: vs,
|
vertices: vs,
|
||||||
indices: is,
|
indices: is,
|
||||||
mode: mode,
|
blend: blend,
|
||||||
dstRegion: dstRegion,
|
dstRegion: dstRegion,
|
||||||
srcRegion: srcRegion,
|
srcRegion: srcRegion,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
@ -620,7 +620,7 @@ func (i *Image) restore(graphicsDriver graphicsdriver.Graphics) error {
|
|||||||
}
|
}
|
||||||
imgs[i] = img.image
|
imgs[i] = img.image
|
||||||
}
|
}
|
||||||
gimg.DrawTriangles(imgs, c.offsets, c.vertices, c.indices, c.mode, c.dstRegion, c.srcRegion, c.shader.shader, c.uniforms, c.evenOdd)
|
gimg.DrawTriangles(imgs, c.offsets, c.vertices, c.indices, c.blend, c.dstRegion, c.srcRegion, c.shader.shader, c.uniforms, c.evenOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(i.drawTrianglesHistory) > 0 {
|
if len(i.drawTrianglesHistory) > 0 {
|
||||||
|
@ -145,7 +145,7 @@ func TestRestoreChain(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
}
|
}
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -193,10 +193,10 @@ func TestRestoreChain2(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
imgs[8].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[7]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[7], w, h, 0, 0), is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
imgs[8].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[7]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[7], w, h, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
imgs[9].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[8]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[8], w, h, 0, 0), is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
imgs[9].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[8]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[8], w, h, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[i], w, h, 0, 0), is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[i], w, h, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
@ -242,10 +242,10 @@ func TestRestoreOverrideSource(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
img2.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, w, h, 0, 0), is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img2.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img2, w, h, 0, 0), is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img2, w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img0.WritePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
img0.WritePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img0, w, h, 0, 0), is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img0, w, h, 0, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -331,23 +331,23 @@ func TestRestoreComplexGraph(t *testing.T) {
|
|||||||
}
|
}
|
||||||
var offsets [graphics.ShaderImageCount - 1][2]float32
|
var offsets [graphics.ShaderImageCount - 1][2]float32
|
||||||
vs := quadVertices(img0, w, h, 0, 0)
|
vs := quadVertices(img0, w, h, 0, 0)
|
||||||
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img1, w, h, 1, 0)
|
vs = quadVertices(img1, w, h, 1, 0)
|
||||||
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img1, w, h, 1, 0)
|
vs = quadVertices(img1, w, h, 1, 0)
|
||||||
img4.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img2, w, h, 2, 0)
|
vs = quadVertices(img2, w, h, 2, 0)
|
||||||
img4.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img3, w, h, 0, 0)
|
vs = quadVertices(img3, w, h, 0, 0)
|
||||||
img5.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img5.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img3, w, h, 0, 0)
|
vs = quadVertices(img3, w, h, 0, 0)
|
||||||
img6.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img6.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img4, w, h, 1, 0)
|
vs = quadVertices(img4, w, h, 1, 0)
|
||||||
img6.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img4}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img6.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img4}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img2, w, h, 0, 0)
|
vs = quadVertices(img2, w, h, 0, 0)
|
||||||
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
vs = quadVertices(img3, w, h, 2, 0)
|
vs = quadVertices(img3, w, h, 2, 0)
|
||||||
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img7.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img3}, offsets, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -445,8 +445,8 @@ func TestRestoreRecursive(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img0, w, h, 1, 0), is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img0, w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, w, h, 1, 0), is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, w, h, 1, 0), is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ func TestDrawTrianglesAndWritePixels(t *testing.T) {
|
|||||||
Width: 2,
|
Width: 2,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img1.WritePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
img1.WritePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||||
|
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
@ -592,8 +592,8 @@ func TestDispose(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img2, 1, 1, 0, 0), is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img2}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img2, 1, 1, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, 1, 1, 0, 0), is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img1}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(img1, 1, 1, 0, 0), is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img1.Dispose()
|
img1.Dispose()
|
||||||
|
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
@ -707,7 +707,7 @@ func TestWritePixelsOnly(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{img0}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
img0.WritePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
img0.WritePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||||
|
|
||||||
// BasePixelsForTesting is available without GPU accessing.
|
// BasePixelsForTesting is available without GPU accessing.
|
||||||
@ -766,7 +766,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
// 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.
|
||||||
@ -795,7 +795,7 @@ func TestAllowWritePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
dst.WritePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
dst.WritePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||||
// WritePixels for a whole image doesn't panic.
|
// WritePixels for a whole image doesn't panic.
|
||||||
}
|
}
|
||||||
@ -819,7 +819,7 @@ func TestAllowWritePixelsForPartAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
dst.WritePixels(make([]byte, 4*2*2), 0, 0, 2, 2)
|
dst.WritePixels(make([]byte, 4*2*2), 0, 0, 2, 2)
|
||||||
// WritePixels for a part of image doesn't panic.
|
// WritePixels for a part of image doesn't panic.
|
||||||
|
|
||||||
@ -922,7 +922,7 @@ func TestMutateSlices(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
for i := range vs {
|
for i := range vs {
|
||||||
vs[i] = 0
|
vs[i] = 0
|
||||||
}
|
}
|
||||||
@ -1119,7 +1119,7 @@ func TestDrawTrianglesAndReadPixels(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
|
|
||||||
pix := make([]byte, 4*w*h)
|
pix := make([]byte, 4*w*h)
|
||||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
|
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
|
||||||
|
@ -50,7 +50,7 @@ func clearImage(img *restorable.Image, w, h int) {
|
|||||||
Width: float32(w),
|
Width: float32(w),
|
||||||
Height: float32(h),
|
Height: float32(h),
|
||||||
}
|
}
|
||||||
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{emptyImage}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeClear, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{emptyImage}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.BlendClear, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShader(t *testing.T) {
|
func TestShader(t *testing.T) {
|
||||||
@ -64,7 +64,7 @@ func TestShader(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
|
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -99,7 +99,7 @@ func TestShaderChain(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[i], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageCount]*restorable.Image{imgs[i]}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(imgs[i], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||||
@ -137,7 +137,7 @@ func TestShaderMultipleSources(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
|
|
||||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||||
clearImage(srcs[0], 1, 1)
|
clearImage(srcs[0], 1, 1)
|
||||||
@ -178,7 +178,7 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
|
|
||||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||||
clearImage(srcs[0], 3, 1)
|
clearImage(srcs[0], 3, 1)
|
||||||
@ -208,7 +208,7 @@ func TestShaderDispose(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
img.DrawTriangles([graphics.ShaderImageCount]*restorable.Image{}, [graphics.ShaderImageCount - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, s, nil, false)
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -56,7 +56,7 @@ func (i *Image) MarkDisposed() {
|
|||||||
i.dotsCache = nil
|
i.dotsCache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, mode graphicsdriver.CompositeMode, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
||||||
i.flushCacheIfNeeded()
|
i.flushCacheIfNeeded()
|
||||||
|
|
||||||
var srcMipmaps [graphics.ShaderImageCount]*mipmap.Mipmap
|
var srcMipmaps [graphics.ShaderImageCount]*mipmap.Mipmap
|
||||||
@ -68,7 +68,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
|||||||
srcMipmaps[i] = src.mipmap
|
srcMipmaps[i] = src.mipmap
|
||||||
}
|
}
|
||||||
|
|
||||||
i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, mode, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd, canSkipMipmap)
|
i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd, canSkipMipmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
|
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
|
||||||
@ -190,7 +190,7 @@ func (i *Image) flushCacheIfNeeded() {
|
|||||||
Width: float32(i.width),
|
Width: float32(i.width),
|
||||||
Height: float32(i.height),
|
Height: float32(i.height),
|
||||||
}
|
}
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, graphicsdriver.CompositeModeCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader.shader, nil, false, true)
|
i.mipmap.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader.shader, nil, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DumpImages(dir string) (string, error) {
|
func DumpImages(dir string) (string, error) {
|
||||||
@ -230,5 +230,5 @@ func (i *Image) Fill(r, g, b, a float32, x, y, width, height int) {
|
|||||||
|
|
||||||
srcs := [graphics.ShaderImageCount]*Image{emptyImage}
|
srcs := [graphics.ShaderImageCount]*Image{emptyImage}
|
||||||
|
|
||||||
i.DrawTriangles(srcs, vs, is, graphicsdriver.CompositeModeCopy, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader, nil, false, true)
|
i.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, NearestFilterShader, nil, false, true)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user