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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
@ -41,50 +43,97 @@ type CompositeMode int
|
||||
const (
|
||||
// Regular alpha blending
|
||||
// c_out = c_src + c_dst × (1 - α_src)
|
||||
CompositeModeSourceOver CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceOver)
|
||||
CompositeModeSourceOver CompositeMode = iota
|
||||
|
||||
// c_out = 0
|
||||
CompositeModeClear CompositeMode = CompositeMode(graphicsdriver.CompositeModeClear)
|
||||
CompositeModeClear
|
||||
|
||||
// c_out = c_src
|
||||
CompositeModeCopy CompositeMode = CompositeMode(graphicsdriver.CompositeModeCopy)
|
||||
CompositeModeCopy
|
||||
|
||||
// c_out = c_dst
|
||||
CompositeModeDestination CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestination)
|
||||
CompositeModeDestination
|
||||
|
||||
// c_out = c_src × (1 - α_dst) + c_dst
|
||||
CompositeModeDestinationOver CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationOver)
|
||||
CompositeModeDestinationOver
|
||||
|
||||
// c_out = c_src × α_dst
|
||||
CompositeModeSourceIn CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceIn)
|
||||
CompositeModeSourceIn
|
||||
|
||||
// c_out = c_dst × α_src
|
||||
CompositeModeDestinationIn CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationIn)
|
||||
CompositeModeDestinationIn
|
||||
|
||||
// c_out = c_src × (1 - α_dst)
|
||||
CompositeModeSourceOut CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceOut)
|
||||
CompositeModeSourceOut
|
||||
|
||||
// c_out = c_dst × (1 - α_src)
|
||||
CompositeModeDestinationOut CompositeMode = CompositeMode(graphicsdriver.CompositeModeDestinationOut)
|
||||
CompositeModeDestinationOut
|
||||
|
||||
// c_out = c_src × α_dst + c_dst × (1 - α_src)
|
||||
CompositeModeSourceAtop CompositeMode = CompositeMode(graphicsdriver.CompositeModeSourceAtop)
|
||||
CompositeModeSourceAtop
|
||||
|
||||
// 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)
|
||||
CompositeModeXor CompositeMode = CompositeMode(graphicsdriver.CompositeModeXor)
|
||||
CompositeModeXor
|
||||
|
||||
// Sum of source and destination (a.k.a. 'plus' or 'additive')
|
||||
// c_out = c_src + c_dst
|
||||
CompositeModeLighter CompositeMode = CompositeMode(graphicsdriver.CompositeModeLighter)
|
||||
CompositeModeLighter
|
||||
|
||||
// The product of source and destination (a.k.a 'multiply blend mode')
|
||||
// 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.
|
||||
type GraphicsLibrary = ui.GraphicsLibrary
|
||||
|
||||
|
16
image.go
16
image.go
@ -215,7 +215,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
||||
options = &DrawImageOptions{}
|
||||
}
|
||||
|
||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
||||
blend := options.CompositeMode.blend()
|
||||
filter := builtinshader.Filter(options.Filter)
|
||||
|
||||
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.
|
||||
@ -396,7 +396,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
options = &DrawTrianglesOptions{}
|
||||
}
|
||||
|
||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
||||
blend := options.CompositeMode.blend()
|
||||
|
||||
address := builtinshader.Address(options.Address)
|
||||
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.
|
||||
@ -525,7 +525,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
options = &DrawTrianglesShaderOptions{}
|
||||
}
|
||||
|
||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
||||
blend := options.CompositeMode.blend()
|
||||
|
||||
vs := graphics.Vertices(len(vertices))
|
||||
dst := i
|
||||
@ -589,7 +589,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
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.
|
||||
@ -645,7 +645,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
||||
options = &DrawRectShaderOptions{}
|
||||
}
|
||||
|
||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
||||
blend := options.CompositeMode.blend()
|
||||
|
||||
var imgs [graphics.ShaderImageCount]*ui.Image
|
||||
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)
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -309,7 +309,7 @@ func (i *Image) ensureIsolated() {
|
||||
Width: float32(w - 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.backend = &backend{
|
||||
@ -348,7 +348,7 @@ func (i *Image) putOnAtlas(graphicsDriver graphicsdriver.Graphics) error {
|
||||
Width: w,
|
||||
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)
|
||||
i.usedAsSourceCount = 0
|
||||
@ -395,13 +395,13 @@ func (i *Image) processSrc(src *Image) {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 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()
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
if src == nil {
|
||||
|
@ -106,7 +106,7 @@ func TestEnsureIsolated(t *testing.T) {
|
||||
Width: 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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -119,7 +119,7 @@ func TestEnsureIsolated(t *testing.T) {
|
||||
Width: 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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -148,7 +148,7 @@ func TestEnsureIsolated(t *testing.T) {
|
||||
|
||||
// Check further drawing doesn't cause panic.
|
||||
// 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) {
|
||||
@ -195,7 +195,7 @@ func TestReputOnAtlas(t *testing.T) {
|
||||
Width: 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 {
|
||||
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 {
|
||||
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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -235,7 +235,7 @@ func TestReputOnAtlas(t *testing.T) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -259,7 +259,7 @@ func TestReputOnAtlas(t *testing.T) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -271,7 +271,7 @@ func TestReputOnAtlas(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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 {
|
||||
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.
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -391,7 +391,7 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
|
||||
pix = make([]byte, 4*w*h)
|
||||
@ -439,7 +439,7 @@ func TestSmallImages(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
||||
@ -487,7 +487,7 @@ func TestLongImages(t *testing.T) {
|
||||
Width: dstW,
|
||||
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)
|
||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix); err != nil {
|
||||
@ -604,7 +604,7 @@ func TestDisposedAndReputOnAtlas(t *testing.T) {
|
||||
Width: 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 {
|
||||
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 {
|
||||
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 {
|
||||
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.
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
@ -40,12 +40,12 @@ func TestShaderFillTwice(t *testing.T) {
|
||||
}
|
||||
g := ui.GraphicsDriverForTesting()
|
||||
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)
|
||||
vs = quadVertices(w, h, 0, 0, 1)
|
||||
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)
|
||||
if err := dst.ReadPixels(g, pix); err != nil {
|
||||
@ -73,11 +73,11 @@ func TestImageDrawTwice(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
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)
|
||||
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.
|
||||
//
|
||||
// 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 {
|
||||
if i == src {
|
||||
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 tryAddDelayedCommand(func() {
|
||||
// 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
|
||||
}
|
||||
@ -165,7 +165,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -89,7 +89,7 @@ func mustUseDifferentVertexBuffer(nextNumVertexFloats, nextNumIndices int) bool
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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.
|
||||
if !split && 0 < len(q.commands) {
|
||||
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.addNumIndices(len(indices))
|
||||
return
|
||||
@ -137,7 +137,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
||||
c.offsets = offsets
|
||||
c.vertices = q.lastVertices(len(vertices))
|
||||
c.nindices = len(indices)
|
||||
c.mode = mode
|
||||
c.blend = blend
|
||||
c.dstRegion = dstRegion
|
||||
c.srcRegion = srcRegion
|
||||
c.shader = shader
|
||||
@ -259,7 +259,7 @@ type drawTrianglesCommand struct {
|
||||
offsets [graphics.ShaderImageCount - 1][2]float32
|
||||
vertices []float32
|
||||
nindices int
|
||||
mode graphicsdriver.CompositeMode
|
||||
blend graphicsdriver.Blend
|
||||
dstRegion graphicsdriver.Region
|
||||
srcRegion graphicsdriver.Region
|
||||
shader *Shader
|
||||
@ -268,39 +268,14 @@ type drawTrianglesCommand struct {
|
||||
}
|
||||
|
||||
func (c *drawTrianglesCommand) String() string {
|
||||
mode := ""
|
||||
switch c.mode {
|
||||
case graphicsdriver.CompositeModeSourceOver:
|
||||
mode = "source-over"
|
||||
case graphicsdriver.CompositeModeClear:
|
||||
mode = "clear"
|
||||
case graphicsdriver.CompositeModeCopy:
|
||||
mode = "copy"
|
||||
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))
|
||||
}
|
||||
// TODO: Improve readability
|
||||
blend := fmt.Sprintf("{src-color: %d, src-alpha: %d, dst-color: %d, dst-alpha: %d, op-color: %d, op-alpha: %d}",
|
||||
c.blend.BlendFactorSourceColor,
|
||||
c.blend.BlendFactorSourceAlpha,
|
||||
c.blend.BlendFactorDestinationColor,
|
||||
c.blend.BlendFactorDestinationAlpha,
|
||||
c.blend.BlendOperationColor,
|
||||
c.blend.BlendOperationAlpha)
|
||||
|
||||
dst := fmt.Sprintf("%d", c.dst.id)
|
||||
if c.dst.screen {
|
||||
@ -321,7 +296,7 @@ func (c *drawTrianglesCommand) String() string {
|
||||
|
||||
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))
|
||||
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.
|
||||
@ -340,7 +315,7 @@ func (c *drawTrianglesCommand) Exec(graphicsDriver graphicsdriver.Graphics, inde
|
||||
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 {
|
||||
@ -361,7 +336,7 @@ func (c *drawTrianglesCommand) addNumIndices(n int) {
|
||||
|
||||
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
||||
// 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 {
|
||||
return false
|
||||
}
|
||||
@ -384,7 +359,7 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs
|
||||
if c.srcs != srcs {
|
||||
return false
|
||||
}
|
||||
if c.mode != mode {
|
||||
if c.blend != blend {
|
||||
return false
|
||||
}
|
||||
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
|
||||
// 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 {
|
||||
if src == nil {
|
||||
continue
|
||||
@ -139,7 +139,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
||||
}
|
||||
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.
|
||||
|
@ -65,7 +65,7 @@ func TestClear(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
|
||||
@ -96,8 +96,8 @@ func TestWritePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||
Width: w,
|
||||
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{src}, [graphics.ShaderImageCount - 1][2]float32{}, vs, is, graphicsdriver.CompositeModeSourceOver, 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.BlendSourceOver, dr, graphicsdriver.Region{}, nearestFilterShader, nil, false)
|
||||
dst.WritePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
|
||||
// TODO: Check the result.
|
||||
@ -115,11 +115,11 @@ func TestShader(t *testing.T) {
|
||||
Width: w,
|
||||
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()
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
return fmt.Errorf("directx: shader ID is invalid")
|
||||
}
|
||||
@ -1315,7 +1315,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
||||
})
|
||||
|
||||
if evenOdd {
|
||||
s, err := shader.pipelineState(mode, prepareStencil, dst.screen)
|
||||
s, err := shader.pipelineState(blend, prepareStencil, dst.screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1323,7 +1323,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
||||
return err
|
||||
}
|
||||
|
||||
s, err = shader.pipelineState(mode, drawWithStencil, dst.screen)
|
||||
s, err = shader.pipelineState(blend, drawWithStencil, dst.screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1331,7 +1331,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
s, err := shader.pipelineState(mode, noStencil, dst.screen)
|
||||
s, err := shader.pipelineState(blend, noStencil, dst.screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1773,7 +1773,7 @@ const (
|
||||
)
|
||||
|
||||
type pipelineStateKey struct {
|
||||
compositeMode graphicsdriver.CompositeMode
|
||||
blend graphicsdriver.Blend
|
||||
stencilMode stencilMode
|
||||
screen bool
|
||||
}
|
||||
@ -1812,9 +1812,9 @@ 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{
|
||||
compositeMode: compositeMode,
|
||||
blend: blend,
|
||||
stencilMode: stencilMode,
|
||||
screen: screen,
|
||||
}
|
||||
@ -1822,7 +1822,7 @@ func (s *Shader) pipelineState(compositeMode graphicsdriver.CompositeMode, stenc
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
|
||||
const numDescriptorsPerFrame = 32
|
||||
|
||||
func blendFactorToBlend(c graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||
switch c {
|
||||
func blendFactorToBlend(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||
switch f {
|
||||
case graphicsdriver.BlendFactorZero:
|
||||
return _D3D12_BLEND_ZERO
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
@ -40,12 +40,23 @@ func blendFactorToBlend(c graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
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 {
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_DEST_COLOR
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -391,7 +402,6 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
||||
}
|
||||
|
||||
// Create a pipeline state.
|
||||
srcOp, dstOp := compositeMode.BlendFactors()
|
||||
psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{
|
||||
pRootSignature: rootSignature,
|
||||
VS: _D3D12_SHADER_BYTECODE{
|
||||
@ -409,12 +419,12 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
||||
{
|
||||
BlendEnable: 1,
|
||||
LogicOpEnable: 0,
|
||||
SrcBlend: blendFactorToBlend(srcOp, false),
|
||||
DestBlend: blendFactorToBlend(dstOp, false),
|
||||
BlendOp: _D3D12_BLEND_OP_ADD,
|
||||
SrcBlendAlpha: blendFactorToBlend(srcOp, true),
|
||||
DestBlendAlpha: blendFactorToBlend(dstOp, true),
|
||||
BlendOpAlpha: _D3D12_BLEND_OP_ADD,
|
||||
SrcBlend: blendFactorToBlend(blend.BlendFactorSourceColor, false),
|
||||
DestBlend: blendFactorToBlend(blend.BlendFactorDestinationColor, false),
|
||||
BlendOp: blendOperationToBlendOp(blend.BlendOperationColor),
|
||||
SrcBlendAlpha: blendFactorToBlend(blend.BlendFactorSourceAlpha, true),
|
||||
DestBlendAlpha: blendFactorToBlend(blend.BlendFactorDestinationAlpha, true),
|
||||
BlendOpAlpha: blendOperationToBlendOp(blend.BlendOperationAlpha),
|
||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||
RenderTargetWriteMask: writeMask,
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ type Graphics interface {
|
||||
NewShader(program *shaderir.Program) (Shader, error)
|
||||
|
||||
// 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.
|
||||
|
@ -317,7 +317,16 @@ func blendFactorToMetalBlendFactor(c graphicsdriver.BlendFactor) mtl.BlendFactor
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
return mtl.BlendFactorDestinationColor
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
return fmt.Errorf("metal: shader ID is invalid")
|
||||
}
|
||||
@ -575,14 +584,14 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
if err := g.draw(prepareStencilRpss, dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, prepareStencil); err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@ -590,7 +599,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
|
||||
return err
|
||||
}
|
||||
} 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 {
|
||||
return err
|
||||
}
|
||||
|
@ -290,6 +290,16 @@ const (
|
||||
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
|
||||
|
||||
const (
|
||||
@ -383,6 +393,8 @@ type RenderPipelineColorAttachmentDescriptor struct {
|
||||
DestinationRGBBlendFactor BlendFactor
|
||||
SourceAlphaBlendFactor BlendFactor
|
||||
SourceRGBBlendFactor BlendFactor
|
||||
AlphaBlendOperation BlendOperation
|
||||
RGBBlendOperation BlendOperation
|
||||
|
||||
WriteMask ColorWriteMask
|
||||
}
|
||||
@ -492,6 +504,8 @@ var (
|
||||
sel_setDestinationRGBBlendFactor = objc.RegisterName("setDestinationRGBBlendFactor:")
|
||||
sel_setSourceAlphaBlendFactor = objc.RegisterName("setSourceAlphaBlendFactor:")
|
||||
sel_setSourceRGBBlendFactor = objc.RegisterName("setSourceRGBBlendFactor:")
|
||||
sel_setAlphaBlendOperation = objc.RegisterName("setAlphaBlendOperation:")
|
||||
sel_setRgbBlendOperation = objc.RegisterName("setRgbBlendOperation:")
|
||||
sel_setWriteMask = objc.RegisterName("setWriteMask:")
|
||||
sel_setStencilAttachmentPixelFormat = objc.RegisterName("setStencilAttachmentPixelFormat:")
|
||||
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_setSourceAlphaBlendFactor, uintptr(rpd.ColorAttachments[0].SourceAlphaBlendFactor))
|
||||
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))
|
||||
renderPipelineDescriptor.Send(sel_setStencilAttachmentPixelFormat, uintptr(rpd.StencilAttachmentPixelFormat))
|
||||
var err cocoa.NSError
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
type shaderRpsKey struct {
|
||||
compositeMode graphicsdriver.CompositeMode
|
||||
blend graphicsdriver.Blend
|
||||
stencilMode stencilMode
|
||||
screen bool
|
||||
}
|
||||
@ -86,9 +86,9 @@ func (s *Shader) init(device mtl.Device) error {
|
||||
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{
|
||||
compositeMode: compositeMode,
|
||||
blend: blend,
|
||||
stencilMode: stencilMode,
|
||||
screen: screen,
|
||||
}
|
||||
@ -112,11 +112,13 @@ func (s *Shader) RenderPipelineState(view *view, compositeMode graphicsdriver.Co
|
||||
rpld.ColorAttachments[0].PixelFormat = pix
|
||||
rpld.ColorAttachments[0].BlendingEnabled = true
|
||||
|
||||
src, dst := compositeMode.BlendFactors()
|
||||
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = blendFactorToMetalBlendFactor(dst)
|
||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = blendFactorToMetalBlendFactor(dst)
|
||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = blendFactorToMetalBlendFactor(src)
|
||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = blendFactorToMetalBlendFactor(src)
|
||||
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorDestinationAlpha)
|
||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorDestinationColor)
|
||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorSourceAlpha)
|
||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = blendFactorToMetalBlendFactor(blend.BlendFactorSourceColor)
|
||||
rpld.ColorAttachments[0].AlphaBlendOperation = blendOperationToMetalBlendOperation(blend.BlendOperationAlpha)
|
||||
rpld.ColorAttachments[0].RGBBlendOperation = blendOperationToMetalBlendOperation(blend.BlendOperationColor)
|
||||
|
||||
if stencilMode == prepareStencil {
|
||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
||||
} else {
|
||||
|
@ -33,8 +33,14 @@ const (
|
||||
glZero blendFactor = 0
|
||||
)
|
||||
|
||||
func convertBlendFactor(op graphicsdriver.BlendFactor) blendFactor {
|
||||
switch op {
|
||||
type blendOperation int
|
||||
|
||||
const (
|
||||
glAdd blendOperation = 0x104
|
||||
)
|
||||
|
||||
func convertBlendFactor(f graphicsdriver.BlendFactor) blendFactor {
|
||||
switch f {
|
||||
case graphicsdriver.BlendFactorZero:
|
||||
return glZero
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
@ -50,7 +56,16 @@ func convertBlendFactor(op graphicsdriver.BlendFactor) blendFactor {
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
return glDstColor
|
||||
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
|
||||
lastViewportWidth int
|
||||
lastViewportHeight int
|
||||
lastCompositeMode graphicsdriver.CompositeMode
|
||||
lastBlend graphicsdriver.Blend
|
||||
maxTextureSize int
|
||||
maxTextureSizeOnce sync.Once
|
||||
highp bool
|
||||
|
@ -100,11 +100,11 @@ func (c *context) reset() error {
|
||||
c.lastFramebuffer = invalidFramebuffer
|
||||
c.lastViewportWidth = 0
|
||||
c.lastViewportHeight = 0
|
||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
||||
gl.Enable(gl.BLEND)
|
||||
gl.Enable(gl.SCISSOR_TEST)
|
||||
|
||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
||||
// Set the source over blending.
|
||||
c.blend(graphicsdriver.BlendSourceOver)
|
||||
|
||||
f := int32(0)
|
||||
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
|
||||
@ -112,14 +112,21 @@ func (c *context) reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
||||
if c.lastCompositeMode == mode {
|
||||
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||
if c.lastBlend == blend {
|
||||
return
|
||||
}
|
||||
c.lastCompositeMode = mode
|
||||
s, d := mode.BlendFactors()
|
||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
||||
gl.BlendFunc(uint32(s2), uint32(d2))
|
||||
c.lastBlend = blend
|
||||
gl.BlendFuncSeparate(
|
||||
uint32(convertBlendFactor(blend.BlendFactorSourceColor)),
|
||||
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) {
|
||||
|
@ -93,10 +93,9 @@ func (c *context) reset() error {
|
||||
c.lastFramebuffer = invalidFramebuffer
|
||||
c.lastViewportWidth = 0
|
||||
c.lastViewportHeight = 0
|
||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
||||
c.ctx.Enable(gles.BLEND)
|
||||
c.ctx.Enable(gles.SCISSOR_TEST)
|
||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
||||
c.blend(graphicsdriver.BlendSourceOver)
|
||||
f := make([]int32, 1)
|
||||
c.ctx.GetIntegerv(f, gles.FRAMEBUFFER_BINDING)
|
||||
c.screenFramebuffer = framebufferNative(f[0])
|
||||
@ -104,14 +103,20 @@ func (c *context) reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
||||
if c.lastCompositeMode == mode {
|
||||
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||
if c.lastBlend == blend {
|
||||
return
|
||||
}
|
||||
c.lastCompositeMode = mode
|
||||
s, d := mode.BlendFactors()
|
||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
||||
c.ctx.BlendFunc(uint32(s2), uint32(d2))
|
||||
c.ctx.BlendFuncSeparate(
|
||||
uint32(convertBlendFactor(blend.BlendFactorSourceColor)),
|
||||
uint32(convertBlendFactor(blend.BlendFactorDestinationColor)),
|
||||
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) {
|
||||
|
@ -163,7 +163,6 @@ func (c *context) reset() error {
|
||||
c.lastFramebuffer = framebufferNative(js.Null())
|
||||
c.lastViewportWidth = 0
|
||||
c.lastViewportHeight = 0
|
||||
c.lastCompositeMode = graphicsdriver.CompositeModeUnknown
|
||||
|
||||
if err := c.initGL(); err != nil {
|
||||
return err
|
||||
@ -175,7 +174,7 @@ func (c *context) reset() error {
|
||||
gl := c.gl
|
||||
gl.enable.Invoke(gles.BLEND)
|
||||
gl.enable.Invoke(gles.SCISSOR_TEST)
|
||||
c.blendFunc(graphicsdriver.CompositeModeSourceOver)
|
||||
c.blend(graphicsdriver.BlendSourceOver)
|
||||
f := gl.getParameter.Invoke(gles.FRAMEBUFFER_BINDING)
|
||||
c.screenFramebuffer = framebufferNative(f)
|
||||
|
||||
@ -185,15 +184,22 @@ func (c *context) reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) blendFunc(mode graphicsdriver.CompositeMode) {
|
||||
if c.lastCompositeMode == mode {
|
||||
func (c *context) blend(blend graphicsdriver.Blend) {
|
||||
if c.lastBlend == blend {
|
||||
return
|
||||
}
|
||||
c.lastCompositeMode = mode
|
||||
s, d := mode.BlendFactors()
|
||||
s2, d2 := convertBlendFactor(s), convertBlendFactor(d)
|
||||
c.lastBlend = blend
|
||||
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) {
|
||||
|
@ -102,7 +102,8 @@ package gl
|
||||
// typedef void (APIENTRYP GPBINDFRAMEBUFFEREXT)(GLenum target, GLuint framebuffer);
|
||||
// typedef void (APIENTRYP GPBINDRENDERBUFFEREXT)(GLenum target, GLuint renderbuffer);
|
||||
// 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 GPBUFFERSUBDATA)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
|
||||
// typedef GLenum (APIENTRYP GPCHECKFRAMEBUFFERSTATUSEXT)(GLenum target);
|
||||
@ -197,8 +198,11 @@ package gl
|
||||
// static void glowBindTexture(GPBINDTEXTURE fnptr, GLenum target, GLuint texture) {
|
||||
// (*fnptr)(target, texture);
|
||||
// }
|
||||
// static void glowBlendFunc(GPBLENDFUNC fnptr, GLenum sfactor, GLenum dfactor) {
|
||||
// (*fnptr)(sfactor, dfactor);
|
||||
// static void glowBlendEquationSeparate(GPBLENDEQUATIONSEPARATE fnptr, GLenum modeRGB, GLenum modeAlpha) {
|
||||
// (*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) {
|
||||
// (*fnptr)(target, size, data, usage);
|
||||
@ -431,7 +435,8 @@ var (
|
||||
gpBindFramebufferEXT C.GPBINDFRAMEBUFFEREXT
|
||||
gpBindRenderbufferEXT C.GPBINDRENDERBUFFEREXT
|
||||
gpBindTexture C.GPBINDTEXTURE
|
||||
gpBlendFunc C.GPBLENDFUNC
|
||||
gpBlendEquationSeparate C.GPBLENDEQUATIONSEPARATE
|
||||
gpBlendFuncSeparate C.GPBLENDFUNCSEPARATE
|
||||
gpBufferData C.GPBUFFERDATA
|
||||
gpBufferSubData C.GPBUFFERSUBDATA
|
||||
gpCheckFramebufferStatusEXT C.GPCHECKFRAMEBUFFERSTATUSEXT
|
||||
@ -541,8 +546,12 @@ func BindTexture(target uint32, texture uint32) {
|
||||
C.glowBindTexture(gpBindTexture, (C.GLenum)(target), (C.GLuint)(texture))
|
||||
}
|
||||
|
||||
func BlendFunc(sfactor uint32, dfactor uint32) {
|
||||
C.glowBlendFunc(gpBlendFunc, (C.GLenum)(sfactor), (C.GLenum)(dfactor))
|
||||
func BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||
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) {
|
||||
@ -861,9 +870,13 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
||||
if gpBindTexture == nil {
|
||||
return errors.New("gl: glBindTexture is missing")
|
||||
}
|
||||
gpBlendFunc = (C.GPBLENDFUNC)(getProcAddr("glBlendFunc"))
|
||||
if gpBlendFunc == nil {
|
||||
return errors.New("gl: glBlendFunc is missing")
|
||||
gpBlendEquationSeparate = (C.GPBLENDEQUATIONSEPARATE)(getProcAddr("glBlendEquationSeparate"))
|
||||
if gpBlendEquationSeparate == nil {
|
||||
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"))
|
||||
if gpBufferData == nil {
|
||||
|
@ -20,7 +20,8 @@ var (
|
||||
gpBindFramebufferEXT uintptr
|
||||
gpBindRenderbufferEXT uintptr
|
||||
gpBindTexture uintptr
|
||||
gpBlendFunc uintptr
|
||||
gpBlendEquationSeparate uintptr
|
||||
gpBlendFuncSeparate uintptr
|
||||
gpBufferData uintptr
|
||||
gpBufferSubData uintptr
|
||||
gpCheckFramebufferStatusEXT uintptr
|
||||
@ -130,8 +131,12 @@ func BindTexture(target uint32, texture uint32) {
|
||||
purego.SyscallN(gpBindTexture, uintptr(target), uintptr(texture))
|
||||
}
|
||||
|
||||
func BlendFunc(sfactor uint32, dfactor uint32) {
|
||||
purego.SyscallN(gpBlendFunc, uintptr(sfactor), uintptr(dfactor))
|
||||
func BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||
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) {
|
||||
@ -450,9 +455,13 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
||||
if gpBindTexture == 0 {
|
||||
return errors.New("gl: glBindTexture is missing")
|
||||
}
|
||||
gpBlendFunc = getProcAddr("glBlendFunc")
|
||||
if gpBlendFunc == 0 {
|
||||
return errors.New("gl: glBlendFunc is missing")
|
||||
gpBlendEquationSeparate = getProcAddr("glBlendEquationSeparate")
|
||||
if gpBlendEquationSeparate == 0 {
|
||||
return errors.New("gl: glBlendEquationSeparate is missing")
|
||||
}
|
||||
gpBlendFuncSeparate = getProcAddr("glBlendFuncSeparate")
|
||||
if gpBlendFuncSeparate == 0 {
|
||||
return errors.New("gl: glBlendFuncSeparate is missing")
|
||||
}
|
||||
gpBufferData = getProcAddr("glBufferData")
|
||||
if gpBufferData == 0 {
|
||||
|
@ -26,7 +26,8 @@ type gl struct {
|
||||
bindFramebuffer js.Value
|
||||
bindRenderbuffer js.Value
|
||||
bindTexture js.Value
|
||||
blendFunc js.Value
|
||||
blendEquationSeparate js.Value
|
||||
blendFuncSeparate js.Value
|
||||
bufferData js.Value
|
||||
bufferSubData js.Value
|
||||
checkFramebufferStatus js.Value
|
||||
@ -103,7 +104,8 @@ func (c *context) newGL(v js.Value) *gl {
|
||||
bindFramebuffer: v.Get("bindFramebuffer").Call("bind", v),
|
||||
bindRenderbuffer: v.Get("bindRenderbuffer").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),
|
||||
bufferSubData: v.Get("bufferSubData").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))
|
||||
}
|
||||
|
||||
func (DefaultContext) BlendFunc(sfactor uint32, dfactor uint32) {
|
||||
C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
|
||||
func (DefaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||
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) {
|
||||
|
@ -64,8 +64,12 @@ func (g *GomobileContext) BindTexture(target uint32, texture uint32) {
|
||||
g.ctx.BindTexture(gl.Enum(target), gl.Texture{Value: texture})
|
||||
}
|
||||
|
||||
func (g *GomobileContext) BlendFunc(sfactor uint32, dfactor uint32) {
|
||||
g.ctx.BlendFunc(gl.Enum(sfactor), gl.Enum(dfactor))
|
||||
func (g *GomobileContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
||||
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) {
|
||||
|
@ -22,7 +22,8 @@ type Context interface {
|
||||
BindFramebuffer(target uint32, framebuffer uint32)
|
||||
BindRenderbuffer(target uint32, renderbuffer 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)
|
||||
BufferSubData(target uint32, offset int, data []byte)
|
||||
CheckFramebufferStatus(target uint32) uint32
|
||||
|
@ -180,7 +180,7 @@ func (g *Graphics) uniformVariableName(idx int) string {
|
||||
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 {
|
||||
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.Height),
|
||||
)
|
||||
g.context.blendFunc(mode)
|
||||
g.context.blend(blend)
|
||||
|
||||
shader := g.shaders[shaderID]
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
return
|
||||
}
|
||||
@ -123,7 +123,7 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices
|
||||
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()
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ func (m *Mipmap) level(level int) *buffered.Image {
|
||||
Width: float32(w2),
|
||||
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)
|
||||
|
||||
return m.imgs[level]
|
||||
|
@ -76,7 +76,7 @@ type drawTrianglesHistoryItem struct {
|
||||
offsets [graphics.ShaderImageCount - 1][2]float32
|
||||
vertices []float32
|
||||
indices []uint16
|
||||
mode graphicsdriver.CompositeMode
|
||||
blend graphicsdriver.Blend
|
||||
dstRegion graphicsdriver.Region
|
||||
srcRegion graphicsdriver.Region
|
||||
shader *Shader
|
||||
@ -218,7 +218,7 @@ func (i *Image) Extend(width, height int) *Image {
|
||||
Width: float32(sw),
|
||||
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.
|
||||
newImg.clearDrawTrianglesHistory()
|
||||
@ -264,7 +264,7 @@ func clearImage(i *graphicscommand.Image) {
|
||||
Width: float32(dw),
|
||||
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.
|
||||
@ -371,7 +371,7 @@ func (i *Image) WritePixels(pixels []byte, x, y, width, height int) {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 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 {
|
||||
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() {
|
||||
i.makeStale(image.Rect(0, 0, i.width, i.height))
|
||||
} 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
|
||||
@ -405,11 +405,11 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
||||
}
|
||||
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.
|
||||
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() {
|
||||
return
|
||||
}
|
||||
@ -434,7 +434,7 @@ func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageCount]*Imag
|
||||
offsets: offsets,
|
||||
vertices: vs,
|
||||
indices: is,
|
||||
mode: mode,
|
||||
blend: blend,
|
||||
dstRegion: dstRegion,
|
||||
srcRegion: srcRegion,
|
||||
shader: shader,
|
||||
@ -620,7 +620,7 @@ func (i *Image) restore(graphicsDriver graphicsdriver.Graphics) error {
|
||||
}
|
||||
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 {
|
||||
|
@ -145,7 +145,7 @@ func TestRestoreChain(t *testing.T) {
|
||||
Width: 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 {
|
||||
t.Fatal(err)
|
||||
@ -193,10 +193,10 @@ func TestRestoreChain2(t *testing.T) {
|
||||
Width: w,
|
||||
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[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[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.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||
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 {
|
||||
@ -242,10 +242,10 @@ func TestRestoreOverrideSource(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
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)
|
||||
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.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -331,23 +331,23 @@ func TestRestoreComplexGraph(t *testing.T) {
|
||||
}
|
||||
var offsets [graphics.ShaderImageCount - 1][2]float32
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -445,8 +445,8 @@ func TestRestoreRecursive(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
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)
|
||||
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.BlendSourceOver, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -549,7 +549,7 @@ func TestDrawTrianglesAndWritePixels(t *testing.T) {
|
||||
Width: 2,
|
||||
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)
|
||||
|
||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||
@ -592,8 +592,8 @@ func TestDispose(t *testing.T) {
|
||||
Width: 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)
|
||||
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)
|
||||
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.BlendCopy, dr, graphicsdriver.Region{}, restorable.NearestFilterShader, nil, false)
|
||||
img1.Dispose()
|
||||
|
||||
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting(), false); err != nil {
|
||||
@ -707,7 +707,7 @@ func TestWritePixelsOnly(t *testing.T) {
|
||||
Width: 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)
|
||||
|
||||
// BasePixelsForTesting is available without GPU accessing.
|
||||
@ -766,7 +766,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
||||
Width: w,
|
||||
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
|
||||
// stale.
|
||||
@ -795,7 +795,7 @@ func TestAllowWritePixelsAfterDrawTriangles(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
// WritePixels for a whole image doesn't panic.
|
||||
}
|
||||
@ -819,7 +819,7 @@ func TestAllowWritePixelsForPartAfterDrawTriangles(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
// WritePixels for a part of image doesn't panic.
|
||||
|
||||
@ -922,7 +922,7 @@ func TestMutateSlices(t *testing.T) {
|
||||
Width: w,
|
||||
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 {
|
||||
vs[i] = 0
|
||||
}
|
||||
@ -1119,7 +1119,7 @@ func TestDrawTrianglesAndReadPixels(t *testing.T) {
|
||||
Width: w,
|
||||
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)
|
||||
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),
|
||||
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) {
|
||||
@ -64,7 +64,7 @@ func TestShader(t *testing.T) {
|
||||
Width: 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 {
|
||||
t.Fatal(err)
|
||||
@ -99,7 +99,7 @@ func TestShaderChain(t *testing.T) {
|
||||
Width: 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 {
|
||||
@ -137,7 +137,7 @@ func TestShaderMultipleSources(t *testing.T) {
|
||||
Width: 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.
|
||||
clearImage(srcs[0], 1, 1)
|
||||
@ -178,7 +178,7 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
|
||||
Width: 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.
|
||||
clearImage(srcs[0], 3, 1)
|
||||
@ -208,7 +208,7 @@ func TestShaderDispose(t *testing.T) {
|
||||
Width: 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
|
||||
// stale.
|
||||
|
@ -56,7 +56,7 @@ func (i *Image) MarkDisposed() {
|
||||
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()
|
||||
|
||||
var srcMipmaps [graphics.ShaderImageCount]*mipmap.Mipmap
|
||||
@ -68,7 +68,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
||||
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) {
|
||||
@ -190,7 +190,7 @@ func (i *Image) flushCacheIfNeeded() {
|
||||
Width: float32(i.width),
|
||||
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) {
|
||||
@ -230,5 +230,5 @@ func (i *Image) Fill(r, g, b, a float32, x, y, width, height int) {
|
||||
|
||||
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