mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
parent
e4e8e7254e
commit
ed028110cf
95
examples/clip/main.go
Normal file
95
examples/clip/main.go
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// +build example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
_ "image/jpeg"
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/examples/resources/images"
|
||||
)
|
||||
|
||||
const (
|
||||
screenWidth = 640
|
||||
screenHeight = 480
|
||||
)
|
||||
|
||||
var (
|
||||
gophersImage *ebiten.Image
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
count int
|
||||
}
|
||||
|
||||
func (g *Game) Update() error {
|
||||
g.count++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
w, h := gophersImage.Size()
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
|
||||
// Move the image's center to the screen's upper-left corner.
|
||||
// This is a preparation for rotating. When geometry matrices are applied,
|
||||
// the origin point is the upper-left corner.
|
||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
||||
|
||||
// Rotate the image. As a result, the anchor point of this rotate is
|
||||
// the center of the image.
|
||||
op.GeoM.Rotate(float64(g.count%360) * 2 * math.Pi / 360)
|
||||
|
||||
// Move the image to the screen's center.
|
||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||
|
||||
// Use SubImage to clip the rendering region.
|
||||
const size = 60
|
||||
r := image.Rect(320-size, 240-size, 320+size, 240+size)
|
||||
screen.SubImage(r).(*ebiten.Image).DrawImage(gophersImage, op)
|
||||
}
|
||||
|
||||
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||
return screenWidth, screenHeight
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Decode image from a byte slice instead of a file so that
|
||||
// this example works in any working directory.
|
||||
// If you want to use a file, there are some options:
|
||||
// 1) Use os.Open and pass the file to the image decoder.
|
||||
// This is a very regular way, but doesn't work on browsers.
|
||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
||||
// This works even on browsers.
|
||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
||||
// This also works on browsers.
|
||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
gophersImage = ebiten.NewImageFromImage(img)
|
||||
|
||||
ebiten.SetWindowSize(screenWidth, screenHeight)
|
||||
ebiten.SetWindowTitle("Clip (Ebiten Demo)")
|
||||
if err := ebiten.RunGame(&Game{}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
50
image.go
50
image.go
@ -158,9 +158,12 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubImage() {
|
||||
panic("ebiten: render to a sub-image is not implemented (DrawImage)")
|
||||
dstBounds := i.Bounds()
|
||||
dstRegion := driver.Region{
|
||||
X: float32(dstBounds.Min.X),
|
||||
Y: float32(dstBounds.Min.Y),
|
||||
Width: float32(dstBounds.Dx()),
|
||||
Height: float32(dstBounds.Dy()),
|
||||
}
|
||||
|
||||
// Calculate vertices before locking because the user can do anything in
|
||||
@ -183,7 +186,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
||||
is := graphics.QuadIndices()
|
||||
|
||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, canSkipMipmap(options.GeoM, filter))
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, canSkipMipmap(options.GeoM, filter))
|
||||
}
|
||||
|
||||
// Vertex represents a vertex passed to DrawTriangles.
|
||||
@ -267,10 +270,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
return
|
||||
}
|
||||
|
||||
if i.isSubImage() {
|
||||
panic("ebiten: render to a sub-image is not implemented (DrawTriangles)")
|
||||
}
|
||||
|
||||
if len(indices)%3 != 0 {
|
||||
panic("ebiten: len(indices) % 3 must be 0")
|
||||
}
|
||||
@ -279,6 +278,14 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
}
|
||||
// TODO: Check the maximum value of indices and len(vertices)?
|
||||
|
||||
dstBounds := i.Bounds()
|
||||
dstRegion := driver.Region{
|
||||
X: float32(dstBounds.Min.X),
|
||||
Y: float32(dstBounds.Min.Y),
|
||||
Width: float32(dstBounds.Dx()),
|
||||
Height: float32(dstBounds.Dy()),
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = &DrawTrianglesOptions{}
|
||||
}
|
||||
@ -315,7 +322,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
|
||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
||||
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, address, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, address, dstRegion, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||
}
|
||||
|
||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||
@ -366,10 +373,6 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
return
|
||||
}
|
||||
|
||||
if i.isSubImage() {
|
||||
panic("ebiten: render to a sub-image is not implemented (DrawTrianglesShader)")
|
||||
}
|
||||
|
||||
if len(indices)%3 != 0 {
|
||||
panic("ebiten: len(indices) % 3 must be 0")
|
||||
}
|
||||
@ -378,6 +381,14 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
}
|
||||
// TODO: Check the maximum value of indices and len(vertices)?
|
||||
|
||||
dstBounds := i.Bounds()
|
||||
dstRegion := driver.Region{
|
||||
X: float32(dstBounds.Min.X),
|
||||
Y: float32(dstBounds.Min.Y),
|
||||
Width: float32(dstBounds.Dx()),
|
||||
Height: float32(dstBounds.Dy()),
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = &DrawTrianglesShaderOptions{}
|
||||
}
|
||||
@ -447,7 +458,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
}
|
||||
|
||||
us := shader.convertUniforms(options.Uniforms)
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, offsets, shader.shader, us, false)
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, false)
|
||||
}
|
||||
|
||||
// DrawRectShaderOptions represents options for DrawRectShader.
|
||||
@ -498,9 +509,12 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubImage() {
|
||||
panic("ebiten: rendering to a sub-image is not implemented (DrawRectShader)")
|
||||
dstBounds := i.Bounds()
|
||||
dstRegion := driver.Region{
|
||||
X: float32(dstBounds.Min.X),
|
||||
Y: float32(dstBounds.Min.Y),
|
||||
Width: float32(dstBounds.Dx()),
|
||||
Height: float32(dstBounds.Dy()),
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
@ -556,7 +570,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
||||
}
|
||||
|
||||
us := shader.convertUniforms(options.Uniforms)
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, offsets, shader.shader, us, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
||||
}
|
||||
|
||||
// SubImage returns an image representing the portion of the image p visible through r.
|
||||
|
@ -2181,3 +2181,29 @@ func TestImageNewImageFromImageWithZeroSize(t *testing.T) {
|
||||
img := image.NewRGBA(image.Rect(0, 0, 0, 1))
|
||||
_ = NewImageFromImage(img)
|
||||
}
|
||||
|
||||
func TestImageClip(t *testing.T) {
|
||||
const (
|
||||
w = 16
|
||||
h = 16
|
||||
)
|
||||
dst := NewImage(w, h)
|
||||
src := NewImage(w, h)
|
||||
|
||||
dst.Fill(color.RGBA{0xff, 0, 0, 0xff})
|
||||
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
||||
|
||||
dst.SubImage(image.Rect(4, 5, 12, 14)).(*Image).DrawImage(src, nil)
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
got := dst.At(i, j).(color.RGBA)
|
||||
want := color.RGBA{0xff, 0, 0, 0xff}
|
||||
if 4 <= i && i < 12 && 5 <= j && j < 14 {
|
||||
want = color.RGBA{0, 0xff, 0, 0xff}
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ func (i *Image) replacePendingPixels(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.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}) {
|
||||
for _, src := range srcs {
|
||||
if i == src {
|
||||
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
||||
@ -259,7 +259,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
if maybeCanAddDelayedCommand() {
|
||||
if tryAddDelayedCommand(func() error {
|
||||
// Arguments are not copied. Copying is the caller's responsibility.
|
||||
i.DrawTriangles(srcs, vertices, indices, colorm, mode, filter, address, sourceRegion, subimageOffsets, shader, uniforms)
|
||||
i.DrawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms)
|
||||
return nil
|
||||
}) {
|
||||
return
|
||||
@ -285,7 +285,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
}
|
||||
i.resolvePendingPixels(false)
|
||||
|
||||
i.img.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, subimageOffsets, s, uniforms)
|
||||
i.img.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms)
|
||||
i.invalidatePendingPixels()
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ type Graphics interface {
|
||||
// Draw draws an image onto another image.
|
||||
//
|
||||
// TODO: Merge this into DrawShader.
|
||||
Draw(dst, src ImageID, indexLen int, indexOffset int, mode CompositeMode, colorM *affine.ColorM, filter Filter, address Address, sourceRegion Region) error
|
||||
Draw(dst, src ImageID, indexLen int, indexOffset int, mode CompositeMode, colorM *affine.ColorM, filter Filter, address Address, dstRegion, srcRegion Region) error
|
||||
|
||||
// DrawShader draws the shader.
|
||||
//
|
||||
@ -58,7 +58,7 @@ type Graphics interface {
|
||||
//
|
||||
// * float32
|
||||
// * []float32
|
||||
DrawShader(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, sourceRegion Region, mode CompositeMode, uniforms []interface{}) error
|
||||
DrawShader(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, dstRegion, srcRegion Region, mode CompositeMode, uniforms []interface{}) error
|
||||
}
|
||||
|
||||
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||
|
@ -54,7 +54,7 @@ type command interface {
|
||||
NumIndices() int
|
||||
AddNumVertices(n int)
|
||||
AddNumIndices(n int)
|
||||
CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool
|
||||
CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool
|
||||
}
|
||||
|
||||
type size struct {
|
||||
@ -132,7 +132,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
|
||||
}
|
||||
|
||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
if len(indices) > graphics.IndicesNum {
|
||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
||||
}
|
||||
@ -153,10 +153,10 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
||||
|
||||
if srcs[0] != nil {
|
||||
w, h := srcs[0].InternalSize()
|
||||
sourceRegion.X /= float32(w)
|
||||
sourceRegion.Y /= float32(h)
|
||||
sourceRegion.Width /= float32(w)
|
||||
sourceRegion.Height /= float32(h)
|
||||
srcRegion.X /= float32(w)
|
||||
srcRegion.Y /= float32(h)
|
||||
srcRegion.Width /= float32(w)
|
||||
srcRegion.Height /= float32(h)
|
||||
for i := range offsets {
|
||||
offsets[i][0] /= float32(w)
|
||||
offsets[i][1] /= float32(h)
|
||||
@ -166,7 +166,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) {
|
||||
// TODO: Pass offsets and uniforms when merging considers the shader.
|
||||
if last := q.commands[len(q.commands)-1]; last.CanMergeWithDrawTrianglesCommand(dst, srcs, color, mode, filter, address, sourceRegion, shader) {
|
||||
if last := q.commands[len(q.commands)-1]; last.CanMergeWithDrawTrianglesCommand(dst, srcs, color, mode, filter, address, dstRegion, srcRegion, shader) {
|
||||
last.AddNumVertices(len(vertices))
|
||||
last.AddNumIndices(len(indices))
|
||||
return
|
||||
@ -183,7 +183,8 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
||||
mode: mode,
|
||||
filter: filter,
|
||||
address: address,
|
||||
sourceRegion: sourceRegion,
|
||||
dstRegion: dstRegion,
|
||||
srcRegion: srcRegion,
|
||||
shader: shader,
|
||||
uniforms: uniforms,
|
||||
}
|
||||
@ -317,7 +318,8 @@ type drawTrianglesCommand struct {
|
||||
mode driver.CompositeMode
|
||||
filter driver.Filter
|
||||
address driver.Address
|
||||
sourceRegion driver.Region
|
||||
dstRegion driver.Region
|
||||
srcRegion driver.Region
|
||||
shader *Shader
|
||||
uniforms []interface{}
|
||||
}
|
||||
@ -420,9 +422,9 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
||||
imgs[i] = src.image.ID()
|
||||
}
|
||||
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.sourceRegion, c.mode, c.uniforms)
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.dstRegion, c.srcRegion, c.mode, c.uniforms)
|
||||
}
|
||||
return theGraphicsDriver.Draw(c.dst.image.ID(), c.srcs[0].image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.sourceRegion)
|
||||
return theGraphicsDriver.Draw(c.dst.image.ID(), c.srcs[0].image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.dstRegion, c.srcRegion)
|
||||
}
|
||||
|
||||
func (c *drawTrianglesCommand) NumVertices() int {
|
||||
@ -443,7 +445,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.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
// If a shader is used, commands are not merged.
|
||||
//
|
||||
// TODO: Merge shader commands considering uniform variables.
|
||||
@ -468,7 +470,10 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs
|
||||
if c.address != address {
|
||||
return false
|
||||
}
|
||||
if c.sourceRegion != sourceRegion {
|
||||
if c.dstRegion != dstRegion {
|
||||
return false
|
||||
}
|
||||
if c.srcRegion != srcRegion {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -504,7 +509,7 @@ func (c *replacePixelsCommand) AddNumVertices(n int) {
|
||||
func (c *replacePixelsCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *replacePixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *replacePixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -532,7 +537,7 @@ func (c *syncCommand) AddNumVertices(n int) {
|
||||
func (c *syncCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *syncCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *syncCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -573,7 +578,7 @@ func (c *pixelsCommand) AddNumVertices(n int) {
|
||||
func (c *pixelsCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *pixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *pixelsCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -606,7 +611,7 @@ func (c *disposeImageCommand) AddNumVertices(n int) {
|
||||
func (c *disposeImageCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *disposeImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *disposeImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -639,7 +644,7 @@ func (c *disposeShaderCommand) AddNumVertices(n int) {
|
||||
func (c *disposeShaderCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *disposeShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *disposeShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -678,7 +683,7 @@ func (c *newImageCommand) AddNumVertices(n int) {
|
||||
func (c *newImageCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *newImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *newImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -714,7 +719,7 @@ func (c *newScreenFramebufferImageCommand) AddNumVertices(n int) {
|
||||
func (c *newScreenFramebufferImageCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *newScreenFramebufferImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *newScreenFramebufferImageCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -749,7 +754,7 @@ func (c *newShaderCommand) AddNumVertices(n int) {
|
||||
func (c *newShaderCommand) AddNumIndices(n int) {
|
||||
}
|
||||
|
||||
func (c *newShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader) bool {
|
||||
func (c *newShaderCommand) CanMergeWithDrawTrianglesCommand(dst *Image, src [graphics.ShaderImageNum]*Image, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,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.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
if i.lastCommand == lastCommandNone {
|
||||
if !i.screen && mode != driver.CompositeModeClear {
|
||||
panic("graphicscommand: the image must be cleared first")
|
||||
@ -177,7 +177,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
||||
}
|
||||
i.resolveBufferedReplacePixels()
|
||||
|
||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms)
|
||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, clr, mode, filter, address, dstRegion, srcRegion, shader, uniforms)
|
||||
|
||||
if i.lastCommand == lastCommandNone && !i.screen {
|
||||
i.lastCommand = lastCommandClear
|
||||
|
@ -44,7 +44,13 @@ func TestClear(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w/2, h/2)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels()
|
||||
if err != nil {
|
||||
@ -74,8 +80,14 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||
dst := NewImage(w, h)
|
||||
vs := quadVertices(w/2, h/2)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
}
|
||||
|
||||
@ -85,11 +97,17 @@ func TestShader(t *testing.T) {
|
||||
dst := NewImage(w, h)
|
||||
vs := quadVertices(w, h)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
|
||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||
s := NewShader(&ir)
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
|
||||
pix, err := dst.Pixels()
|
||||
if err != nil {
|
||||
|
@ -611,7 +611,7 @@ func (g *Graphics) Reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms []interface{}) error {
|
||||
func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion driver.Region, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms []interface{}) error {
|
||||
g.view.update()
|
||||
|
||||
rpd := mtl.RenderPassDescriptor{}
|
||||
@ -653,6 +653,12 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, srcs [graphics.
|
||||
ZNear: -1,
|
||||
ZFar: 1,
|
||||
})
|
||||
rce.SetScissorRect(mtl.ScissorRect{
|
||||
X: int(dstRegion.X),
|
||||
Y: int(dstRegion.Y),
|
||||
Width: int(dstRegion.Width),
|
||||
Height: int(dstRegion.Height),
|
||||
})
|
||||
rce.SetVertexBuffer(g.vb, 0, 0)
|
||||
|
||||
for i, u := range uniforms {
|
||||
@ -680,7 +686,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, srcs [graphics.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Graphics) Draw(dstID, srcID driver.ImageID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, sourceRegion driver.Region) error {
|
||||
func (g *Graphics) Draw(dstID, srcID driver.ImageID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region) error {
|
||||
dst := g.images[dstID]
|
||||
dst.waitUntilSyncFinishes()
|
||||
|
||||
@ -718,13 +724,13 @@ func (g *Graphics) Draw(dstID, srcID driver.ImageID, indexLen int, indexOffset i
|
||||
esTranslate,
|
||||
scale,
|
||||
[]float32{
|
||||
sourceRegion.X,
|
||||
sourceRegion.Y,
|
||||
sourceRegion.X + sourceRegion.Width,
|
||||
sourceRegion.Y + sourceRegion.Height,
|
||||
srcRegion.X,
|
||||
srcRegion.Y,
|
||||
srcRegion.X + srcRegion.Width,
|
||||
srcRegion.Y + srcRegion.Height,
|
||||
},
|
||||
}
|
||||
if err := g.draw(rps, dst, srcs, indexLen, indexOffset, uniforms); err != nil {
|
||||
if err := g.draw(rps, dst, dstRegion, srcs, indexLen, indexOffset, uniforms); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -947,7 +953,7 @@ func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
||||
bce.EndEncoding()
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, sourceRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, dstRegion, srcRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
dst := g.images[dstID]
|
||||
dst.waitUntilSyncFinishes()
|
||||
|
||||
@ -987,11 +993,11 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
us[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
|
||||
|
||||
// Set the source region's origin of texture0.
|
||||
uorigin := []float32{float32(sourceRegion.X), float32(sourceRegion.Y)}
|
||||
uorigin := []float32{float32(srcRegion.X), float32(srcRegion.Y)}
|
||||
us[graphics.TextureSourceRegionOriginUniformVariableIndex] = uorigin
|
||||
|
||||
// Set the source region's size of texture0.
|
||||
ussize := []float32{float32(sourceRegion.Width), float32(sourceRegion.Height)}
|
||||
ussize := []float32{float32(srcRegion.Width), float32(srcRegion.Height)}
|
||||
us[graphics.TextureSourceRegionSizeUniformVariableIndex] = ussize
|
||||
|
||||
// Set the additional uniform variables.
|
||||
@ -1000,7 +1006,7 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
us[offset+i] = v
|
||||
}
|
||||
|
||||
if err := g.draw(rps, dst, srcs, indexLen, indexOffset, us); err != nil {
|
||||
if err := g.draw(rps, dst, dstRegion, srcs, indexLen, indexOffset, us); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -650,6 +650,13 @@ func (rce RenderCommandEncoder) SetViewport(viewport Viewport) {
|
||||
C.RenderCommandEncoder_SetViewport(rce.commandEncoder, viewport.c())
|
||||
}
|
||||
|
||||
// SetScissorRect sets the scissor rectangle for a fragment scissor test.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515583-setscissorrect
|
||||
func (rce RenderCommandEncoder) SetScissorRect(scissorRect ScissorRect) {
|
||||
C.RenderCommandEncoder_SetScissorRect(rce.commandEncoder, scissorRect.c())
|
||||
}
|
||||
|
||||
// SetVertexBuffer sets a buffer for the vertex shader function at an index
|
||||
// in the buffer argument table with an offset that specifies the start of the data.
|
||||
//
|
||||
@ -909,3 +916,22 @@ func (v *Viewport) c() C.struct_Viewport {
|
||||
ZFar: C.double(v.ZFar),
|
||||
}
|
||||
}
|
||||
|
||||
// ScissorRect represents a rectangle for the scissor fragment test.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlscissorrect
|
||||
type ScissorRect struct {
|
||||
X int
|
||||
Y int
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
|
||||
func (s *ScissorRect) c() C.struct_ScissorRect {
|
||||
return C.struct_ScissorRect{
|
||||
X: C.uint_t(s.X),
|
||||
Y: C.uint_t(s.Y),
|
||||
Width: C.uint_t(s.Width),
|
||||
Height: C.uint_t(s.Height),
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,13 @@ struct Viewport {
|
||||
double ZFar;
|
||||
};
|
||||
|
||||
struct ScissorRect {
|
||||
uint_t X;
|
||||
uint_t Y;
|
||||
uint_t Width;
|
||||
uint_t Height;
|
||||
};
|
||||
|
||||
struct Device CreateSystemDefaultDevice();
|
||||
struct Devices CopyAllDevices();
|
||||
|
||||
@ -139,6 +146,8 @@ void RenderCommandEncoder_SetRenderPipelineState(void *renderCommandEncoder,
|
||||
void *renderPipelineState);
|
||||
void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
||||
struct Viewport viewport);
|
||||
void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
|
||||
struct ScissorRect scissorRect);
|
||||
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||
void *buffer, uint_t offset,
|
||||
uint_t index);
|
||||
|
@ -209,6 +209,17 @@ void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
||||
}];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
|
||||
struct ScissorRect scissorRect) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setScissorRect:(MTLScissorRect){
|
||||
.x = scissorRect.X,
|
||||
.y = scissorRect.Y,
|
||||
.width = scissorRect.Width,
|
||||
.height = scissorRect.Height,
|
||||
}];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||
void *buffer, uint_t offset,
|
||||
uint_t index) {
|
||||
|
@ -116,6 +116,7 @@ func (c *context) reset() error {
|
||||
c.lastViewportHeight = 0
|
||||
c.lastCompositeMode = driver.CompositeModeUnknown
|
||||
gl.Enable(gl.BLEND)
|
||||
gl.Enable(gl.SCISSOR_TEST)
|
||||
|
||||
c.blendFunc(driver.CompositeModeSourceOver)
|
||||
|
||||
@ -135,6 +136,10 @@ func (c *context) blendFunc(mode driver.CompositeMode) {
|
||||
gl.BlendFunc(uint32(s2), uint32(d2))
|
||||
}
|
||||
|
||||
func (c *context) scissor(x, y, width, height int) {
|
||||
gl.Scissor(int32(x), int32(y), int32(width), int32(height))
|
||||
}
|
||||
|
||||
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||
var t uint32
|
||||
gl.GenTextures(1, &t)
|
||||
|
@ -104,6 +104,7 @@ var (
|
||||
nearest js.Value
|
||||
noError js.Value
|
||||
rgba js.Value
|
||||
scissorTest js.Value
|
||||
texture2d js.Value
|
||||
textureMagFilter js.Value
|
||||
textureMinFilter js.Value
|
||||
@ -159,6 +160,7 @@ func init() {
|
||||
nearest = contextPrototype.Get("NEAREST")
|
||||
noError = contextPrototype.Get("NO_ERROR")
|
||||
rgba = contextPrototype.Get("RGBA")
|
||||
scissorTest = contextPrototype.Get("SCISSOR_TEST")
|
||||
texture0 = contextPrototype.Get("TEXTURE0").Int()
|
||||
texture2d = contextPrototype.Get("TEXTURE_2D")
|
||||
textureMagFilter = contextPrototype.Get("TEXTURE_MAG_FILTER")
|
||||
@ -222,6 +224,7 @@ func (c *context) reset() error {
|
||||
}
|
||||
gl := c.gl
|
||||
gl.Call("enable", blend)
|
||||
gl.Call("enable", scissorTest)
|
||||
c.blendFunc(driver.CompositeModeSourceOver)
|
||||
f := gl.Call("getParameter", framebufferBinding)
|
||||
c.screenFramebuffer = framebufferNative(f)
|
||||
@ -240,6 +243,11 @@ func (c *context) blendFunc(mode driver.CompositeMode) {
|
||||
gl.Call("blendFunc", int(s2), int(d2))
|
||||
}
|
||||
|
||||
func (c *context) scissor(x, y, width, height int) {
|
||||
gl := c.gl
|
||||
gl.Call("scissor", x, y, width, height)
|
||||
}
|
||||
|
||||
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||
c.ensureGL()
|
||||
gl := c.gl
|
||||
|
@ -106,6 +106,7 @@ func (c *context) reset() error {
|
||||
c.lastViewportHeight = 0
|
||||
c.lastCompositeMode = driver.CompositeModeUnknown
|
||||
c.ctx.Enable(gles.BLEND)
|
||||
c.ctx.Enable(gles.SCISSOR_TEST)
|
||||
c.blendFunc(driver.CompositeModeSourceOver)
|
||||
f := make([]int32, 1)
|
||||
c.ctx.GetIntegerv(f, gles.FRAMEBUFFER_BINDING)
|
||||
@ -124,6 +125,10 @@ func (c *context) blendFunc(mode driver.CompositeMode) {
|
||||
c.ctx.BlendFunc(uint32(s2), uint32(d2))
|
||||
}
|
||||
|
||||
func (c *context) scissor(x, y, width, height int) {
|
||||
c.ctx.Scissor(int32(x), int32(y), int32(width), int32(height))
|
||||
}
|
||||
|
||||
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||
t := c.ctx.GenTextures(1)[0]
|
||||
if t <= 0 {
|
||||
|
@ -57,6 +57,7 @@ const (
|
||||
TEXTURE_WRAP_S = 0x2802
|
||||
TEXTURE_WRAP_T = 0x2803
|
||||
TRIANGLES = 0x0004
|
||||
SCISSOR_TEST = 0x0C11
|
||||
UNPACK_ALIGNMENT = 0x0CF5
|
||||
UNSIGNED_BYTE = 0x1401
|
||||
UNSIGNED_SHORT = 0x1403
|
||||
|
@ -147,6 +147,7 @@ package gl
|
||||
// typedef void (APIENTRYP GPLINKPROGRAM)(GLuint program);
|
||||
// typedef void (APIENTRYP GPPIXELSTOREI)(GLenum pname, GLint param);
|
||||
// typedef void (APIENTRYP GPREADPIXELS)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
|
||||
// typedef void (APIENTRYP GPSCISSOR)(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
// typedef void (APIENTRYP GPSHADERSOURCE)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
|
||||
// typedef void (APIENTRYP GPTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
|
||||
// typedef void (APIENTRYP GPTEXPARAMETERI)(GLenum target, GLenum pname, GLint param);
|
||||
@ -320,6 +321,9 @@ package gl
|
||||
// static void glowReadPixels(GPREADPIXELS fnptr, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) {
|
||||
// (*fnptr)(x, y, width, height, format, type, pixels);
|
||||
// }
|
||||
// static void glowScissor(GPSCISSOR fnptr, GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
// (*fnptr)(x, y, width, height);
|
||||
// }
|
||||
// static void glowShaderSource(GPSHADERSOURCE fnptr, GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) {
|
||||
// (*fnptr)(shader, count, string, length);
|
||||
// }
|
||||
@ -428,6 +432,7 @@ var (
|
||||
gpLinkProgram C.GPLINKPROGRAM
|
||||
gpPixelStorei C.GPPIXELSTOREI
|
||||
gpReadPixels C.GPREADPIXELS
|
||||
gpScissor C.GPSCISSOR
|
||||
gpShaderSource C.GPSHADERSOURCE
|
||||
gpTexImage2D C.GPTEXIMAGE2D
|
||||
gpTexParameteri C.GPTEXPARAMETERI
|
||||
@ -661,6 +666,10 @@ func ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtyp
|
||||
C.glowReadPixels(gpReadPixels, (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLenum)(xtype), pixels)
|
||||
}
|
||||
|
||||
func Scissor(x int32, y int32, width int32, height int32) {
|
||||
C.glowScissor(gpScissor, (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height))
|
||||
}
|
||||
|
||||
func ShaderSource(shader uint32, count int32, xstring **uint8, length *int32) {
|
||||
C.glowShaderSource(gpShaderSource, (C.GLuint)(shader), (C.GLsizei)(count), (**C.GLchar)(unsafe.Pointer(xstring)), (*C.GLint)(unsafe.Pointer(length)))
|
||||
}
|
||||
@ -884,6 +893,10 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
||||
if gpReadPixels == nil {
|
||||
return errors.New("glReadPixels")
|
||||
}
|
||||
gpScissor = (C.GPSCISSOR)(getProcAddr("glScissor"))
|
||||
if gpScissor == nil {
|
||||
return errors.New("glScissor")
|
||||
}
|
||||
gpShaderSource = (C.GPSHADERSOURCE)(getProcAddr("glShaderSource"))
|
||||
if gpShaderSource == nil {
|
||||
return errors.New("glShaderSource")
|
||||
|
@ -62,6 +62,7 @@ var (
|
||||
gpLinkProgram uintptr
|
||||
gpPixelStorei uintptr
|
||||
gpReadPixels uintptr
|
||||
gpScissor uintptr
|
||||
gpShaderSource uintptr
|
||||
gpTexImage2D uintptr
|
||||
gpTexParameteri uintptr
|
||||
@ -295,6 +296,10 @@ func ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtyp
|
||||
syscall.Syscall9(gpReadPixels, 7, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(pixels), 0, 0)
|
||||
}
|
||||
|
||||
func Scissor(x int32, y int32, width int32, height int32) {
|
||||
syscall.Syscall6(gpScissor, 4, uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0, 0)
|
||||
}
|
||||
|
||||
func ShaderSource(shader uint32, count int32, xstring **uint8, length *int32) {
|
||||
syscall.Syscall6(gpShaderSource, 4, uintptr(shader), uintptr(count), uintptr(unsafe.Pointer(xstring)), uintptr(unsafe.Pointer(length)), 0, 0)
|
||||
}
|
||||
@ -518,6 +523,10 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
||||
if gpReadPixels == 0 {
|
||||
return errors.New("glReadPixels")
|
||||
}
|
||||
gpScissor = getProcAddr("glScissor")
|
||||
if gpScissor == 0 {
|
||||
return errors.New("glScissor")
|
||||
}
|
||||
gpShaderSource = getProcAddr("glShaderSource")
|
||||
if gpShaderSource == 0 {
|
||||
return errors.New("glShaderSource")
|
||||
|
@ -54,6 +54,7 @@ const (
|
||||
NO_ERROR = 0
|
||||
READ_WRITE = 0x88BA
|
||||
RGBA = 0x1908
|
||||
SCISSOR_TEST = 0x0C11
|
||||
TEXTURE0 = 0x84C0
|
||||
TEXTURE_2D = 0x0DE1
|
||||
TEXTURE_MAG_FILTER = 0x2800
|
||||
|
@ -242,6 +242,10 @@ func (DefaultContext) ReadPixels(dst []byte, x int32, y int32, width int32, heig
|
||||
C.glReadPixels(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(xtype), unsafe.Pointer(&dst[0]))
|
||||
}
|
||||
|
||||
func (DefaultContext) Scissor(x, y, width, height int32) {
|
||||
C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
|
||||
}
|
||||
|
||||
func (DefaultContext) ShaderSource(shader uint32, xstring string) {
|
||||
s, free := cStringPtr(xstring)
|
||||
defer free()
|
||||
|
@ -224,6 +224,10 @@ func (g *GomobileContext) ReadPixels(dst []byte, x int32, y int32, width int32,
|
||||
g.ctx.ReadPixels(dst, int(x), int(y), int(width), int(height), gl.Enum(format), gl.Enum(xtype))
|
||||
}
|
||||
|
||||
func (g *GomobileContext) Scissor(x, y, width, height int32) {
|
||||
g.ctx.Scissor(x, y, width, height)
|
||||
}
|
||||
|
||||
func (g *GomobileContext) ShaderSource(shader uint32, xstring string) {
|
||||
g.ctx.ShaderSource(gl.Shader{Value: shader}, xstring)
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ type Context interface {
|
||||
LinkProgram(program uint32)
|
||||
PixelStorei(pname uint32, param int32)
|
||||
ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32)
|
||||
Scissor(x, y, width, height int32)
|
||||
ShaderSource(shader uint32, xstring string)
|
||||
TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
|
||||
TexParameteri(target uint32, pname uint32, param int32)
|
||||
|
@ -148,7 +148,7 @@ func (g *Graphics) SetVertices(vertices []float32, indices []uint16) {
|
||||
g.context.elementArrayBufferSubData(indices)
|
||||
}
|
||||
|
||||
func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, sourceRegion driver.Region) error {
|
||||
func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region) error {
|
||||
destination := g.images[dst]
|
||||
source := g.images[src]
|
||||
|
||||
@ -157,6 +157,12 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
|
||||
if err := destination.setViewport(); err != nil {
|
||||
return err
|
||||
}
|
||||
g.context.scissor(
|
||||
int(dstRegion.X),
|
||||
int(dstRegion.Y),
|
||||
int(dstRegion.Width),
|
||||
int(dstRegion.Height),
|
||||
)
|
||||
g.context.blendFunc(mode)
|
||||
|
||||
program := g.state.programs[programKey{
|
||||
@ -176,10 +182,10 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
|
||||
}, uniformVariable{
|
||||
name: "source_region",
|
||||
value: []float32{
|
||||
sourceRegion.X,
|
||||
sourceRegion.Y,
|
||||
sourceRegion.X + sourceRegion.Width,
|
||||
sourceRegion.Y + sourceRegion.Height,
|
||||
srcRegion.X,
|
||||
srcRegion.Y,
|
||||
srcRegion.X + srcRegion.Width,
|
||||
srcRegion.Y + srcRegion.Height,
|
||||
},
|
||||
typ: shaderir.Type{Main: shaderir.Vec4},
|
||||
})
|
||||
@ -284,7 +290,7 @@ func (g *Graphics) removeShader(shader *Shader) {
|
||||
delete(g.shaders, shader.id)
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, sourceRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, dstRegion, srcRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
d := g.images[dst]
|
||||
s := g.shaders[shader]
|
||||
|
||||
@ -293,6 +299,12 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
||||
if err := d.setViewport(); err != nil {
|
||||
return err
|
||||
}
|
||||
g.context.scissor(
|
||||
int(dstRegion.X),
|
||||
int(dstRegion.Y),
|
||||
int(dstRegion.Width),
|
||||
int(dstRegion.Height),
|
||||
)
|
||||
g.context.blendFunc(mode)
|
||||
|
||||
us := make([]uniformVariable, graphics.PreservedUniformVariablesNum+len(uniforms))
|
||||
@ -331,14 +343,14 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
{
|
||||
origin := []float32{float32(sourceRegion.X), float32(sourceRegion.Y)}
|
||||
origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)}
|
||||
const idx = graphics.TextureSourceRegionOriginUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = origin
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
{
|
||||
size := []float32{float32(sourceRegion.Width), float32(sourceRegion.Height)}
|
||||
size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)}
|
||||
const idx = graphics.TextureSourceRegionSizeUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = size
|
||||
|
@ -91,7 +91,7 @@ func (m *Mipmap) Pixels(x, y, width, height int) ([]byte, error) {
|
||||
return m.orig.Pixels(x, y, width, height)
|
||||
}
|
||||
|
||||
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, canSkipMipmap bool) {
|
||||
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, canSkipMipmap bool) {
|
||||
if len(indices) == 0 {
|
||||
return
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices [
|
||||
imgs[i] = src.orig
|
||||
}
|
||||
|
||||
m.orig.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, sourceRegion, subimageOffsets, s, uniforms)
|
||||
m.orig.DrawTriangles(imgs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms)
|
||||
m.disposeMipmaps()
|
||||
}
|
||||
|
||||
@ -225,7 +225,14 @@ func (m *Mipmap) level(level int) *buffered.Image {
|
||||
}
|
||||
s := buffered.NewImage(w2, h2)
|
||||
s.SetVolatile(m.volatile)
|
||||
s.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{src}, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
|
||||
dstRegion := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: float32(w2),
|
||||
Height: float32(h2),
|
||||
}
|
||||
s.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{src}, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
m.imgs[level] = s
|
||||
|
||||
return m.imgs[level]
|
||||
|
@ -77,7 +77,8 @@ type drawTrianglesHistoryItem struct {
|
||||
mode driver.CompositeMode
|
||||
filter driver.Filter
|
||||
address driver.Address
|
||||
sourceRegion driver.Region
|
||||
dstRegion driver.Region
|
||||
srcRegion driver.Region
|
||||
shader *Shader
|
||||
uniforms []interface{}
|
||||
}
|
||||
@ -269,7 +270,13 @@ func fillImage(i *graphicscommand.Image, clr color.RGBA) {
|
||||
is := graphics.QuadIndices()
|
||||
srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}
|
||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||
i.DrawTriangles(srcs, offsets, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dstRegion := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: float32(dw),
|
||||
Height: float32(dh),
|
||||
}
|
||||
i.DrawTriangles(srcs, offsets, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil)
|
||||
}
|
||||
|
||||
// BasePixelsForTesting returns the image's basePixels for testing.
|
||||
@ -361,7 +368,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 7: Color Y
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
if i.priority {
|
||||
panic("restorable: DrawTriangles cannot be called on a priority image")
|
||||
}
|
||||
@ -385,7 +392,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
||||
if srcstale || i.screen || !needsRestoring() || i.volatile {
|
||||
i.makeStale()
|
||||
} else {
|
||||
i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms)
|
||||
i.appendDrawTrianglesHistory(srcs, offsets, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, shader, uniforms)
|
||||
}
|
||||
|
||||
var s *graphicscommand.Shader
|
||||
@ -402,11 +409,11 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
||||
}
|
||||
s = shader.shader
|
||||
}
|
||||
i.image.DrawTriangles(imgs, offsets, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||
i.image.DrawTriangles(imgs, offsets, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, s, uniforms)
|
||||
}
|
||||
|
||||
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
||||
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
if i.stale || i.volatile || i.screen {
|
||||
return
|
||||
}
|
||||
@ -433,7 +440,8 @@ func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image,
|
||||
mode: mode,
|
||||
filter: filter,
|
||||
address: address,
|
||||
sourceRegion: sourceRegion,
|
||||
dstRegion: dstRegion,
|
||||
srcRegion: srcRegion,
|
||||
shader: shader,
|
||||
uniforms: uniforms,
|
||||
}
|
||||
@ -625,7 +633,7 @@ func (i *Image) restore() error {
|
||||
}
|
||||
imgs[i] = img.image
|
||||
}
|
||||
gimg.DrawTriangles(imgs, c.offsets, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.sourceRegion, s, c.uniforms)
|
||||
gimg.DrawTriangles(imgs, c.offsets, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.dstRegion, c.srcRegion, s, c.uniforms)
|
||||
}
|
||||
|
||||
if len(i.drawTrianglesHistory) > 0 {
|
||||
|
@ -131,7 +131,13 @@ func TestRestoreChain(t *testing.T) {
|
||||
for i := 0; i < num-1; i++ {
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
}
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -173,10 +179,16 @@ func TestRestoreChain2(t *testing.T) {
|
||||
imgs[8].ReplacePixels([]byte{clr8.R, clr8.G, clr8.B, clr8.A}, 0, 0, w, h)
|
||||
|
||||
is := graphics.QuadIndices()
|
||||
imgs[8].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[9].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
imgs[8].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
imgs[9].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
for i := 0; i < 7; i++ {
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
}
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -216,10 +228,16 @@ func TestRestoreOverrideSource(t *testing.T) {
|
||||
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
||||
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
||||
is := graphics.QuadIndices()
|
||||
img2.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
img2.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -298,24 +316,30 @@ func TestRestoreComplexGraph(t *testing.T) {
|
||||
}()
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 2, 0)
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img5.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img5.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img4}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img4}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
vs = quadVertices(w, h, 2, 0)
|
||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -407,8 +431,14 @@ func TestRestoreRecursive(t *testing.T) {
|
||||
img0.Dispose()
|
||||
}()
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -502,7 +532,13 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
||||
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 2,
|
||||
Height: 1,
|
||||
}
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -539,8 +575,14 @@ func TestDispose(t *testing.T) {
|
||||
defer img2.Dispose()
|
||||
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img1.Dispose()
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -648,7 +690,13 @@ func TestReplacePixelsOnly(t *testing.T) {
|
||||
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||
|
||||
// BasePixelsForTesting is available without GPU accessing.
|
||||
@ -702,7 +750,13 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
||||
src.ReplacePixels(pix, 0, 0, w, h)
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
|
||||
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
||||
// stale.
|
||||
@ -723,7 +777,13 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||
// ReplacePixels for a whole image doesn't panic.
|
||||
}
|
||||
@ -741,7 +801,13 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
}
|
||||
|
||||
@ -830,7 +896,13 @@ func TestFill2(t *testing.T) {
|
||||
dst := NewImage(w, h)
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
|
||||
// Fill src with a different color. This should not affect dst.
|
||||
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
||||
@ -869,7 +941,13 @@ func TestMutateSlices(t *testing.T) {
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := make([]uint16, len(graphics.QuadIndices()))
|
||||
copy(is, graphics.QuadIndices())
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil)
|
||||
for i := range vs {
|
||||
vs[i] = 0
|
||||
}
|
||||
|
@ -30,7 +30,13 @@ func TestShader(t *testing.T) {
|
||||
|
||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||
s := NewShader(&ir)
|
||||
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -60,7 +66,13 @@ func TestShaderChain(t *testing.T) {
|
||||
ir := etesting.ShaderProgramImages(1)
|
||||
s := NewShader(&ir)
|
||||
for i := 0; i < num-1; i++ {
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
}
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -93,7 +105,13 @@ func TestShaderMultipleSources(t *testing.T) {
|
||||
ir := etesting.ShaderProgramImages(3)
|
||||
s := NewShader(&ir)
|
||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
|
||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||
srcs[0].Fill(color.RGBA{})
|
||||
@ -129,7 +147,13 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
}
|
||||
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
|
||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||
srcs[0].Fill(color.RGBA{})
|
||||
@ -154,7 +178,13 @@ func TestShaderDispose(t *testing.T) {
|
||||
|
||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||
s := NewShader(&ir)
|
||||
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}
|
||||
img.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil)
|
||||
|
||||
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
|
||||
// stale.
|
||||
|
@ -241,7 +241,13 @@ func (i *Image) ensureNotShared() {
|
||||
is := graphics.QuadIndices()
|
||||
srcs := [graphics.ShaderImageNum]*restorable.Image{i.backend.restorable}
|
||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||
newImg.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dstRegion := driver.Region{
|
||||
X: paddingSize,
|
||||
Y: paddingSize,
|
||||
Width: float32(w - 2*paddingSize),
|
||||
Height: float32(h - 2*paddingSize),
|
||||
}
|
||||
newImg.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil)
|
||||
|
||||
i.dispose(false)
|
||||
i.backend = &backend{
|
||||
@ -325,7 +331,7 @@ func (i *Image) processSrc(src *Image) {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 7: Color Y
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}) {
|
||||
backendsM.Lock()
|
||||
// Do not use defer for performance.
|
||||
|
||||
@ -345,6 +351,9 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
dy = paddingSize
|
||||
}
|
||||
|
||||
dstRegion.X += dx
|
||||
dstRegion.Y += dx
|
||||
|
||||
var oxf, oyf float32
|
||||
if srcs[0] != nil {
|
||||
ox, oy, _, _ := srcs[0].regionWithPadding()
|
||||
@ -358,11 +367,11 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
vertices[i*graphics.VertexFloatNum+2] += oxf
|
||||
vertices[i*graphics.VertexFloatNum+3] += oyf
|
||||
}
|
||||
// sourceRegion can be delibarately empty when this is not needed in order to avoid unexpected
|
||||
// srcRegion can be delibarately empty when this is not needed in order to avoid unexpected
|
||||
// performance issue (#1293).
|
||||
if sourceRegion.Width != 0 && sourceRegion.Height != 0 {
|
||||
sourceRegion.X += oxf
|
||||
sourceRegion.Y += oyf
|
||||
if srcRegion.Width != 0 && srcRegion.Height != 0 {
|
||||
srcRegion.X += oxf
|
||||
srcRegion.Y += oyf
|
||||
}
|
||||
} else {
|
||||
n := len(vertices) / graphics.VertexFloatNum
|
||||
@ -397,7 +406,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
}
|
||||
}
|
||||
|
||||
i.backend.restorable.DrawTriangles(imgs, offsets, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms)
|
||||
i.backend.restorable.DrawTriangles(imgs, offsets, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, s, uniforms)
|
||||
|
||||
for _, src := range srcs {
|
||||
if src == nil {
|
||||
@ -428,6 +437,7 @@ func (i *Image) Fill(clr color.RGBA) {
|
||||
i.ensureNotShared()
|
||||
|
||||
// As *restorable.Image is an independent image, it is fine to fill the entire image.
|
||||
// TODO: Is it OK not to consider paddings?
|
||||
i.backend.restorable.Fill(clr)
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,13 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
// img4.ensureNotShared() should be called.
|
||||
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: size,
|
||||
Height: size,
|
||||
}
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
want := false
|
||||
if got := img4.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
@ -126,7 +132,7 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
|
||||
// Check further drawing doesn't cause panic.
|
||||
// This bug was fixed by 03dcd948.
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
}
|
||||
|
||||
func TestReshared(t *testing.T) {
|
||||
@ -167,7 +173,13 @@ func TestReshared(t *testing.T) {
|
||||
// Use img1 as a render target.
|
||||
vs := quadVertices(size, size, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: size,
|
||||
Height: size,
|
||||
}
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -177,7 +189,7 @@ func TestReshared(t *testing.T) {
|
||||
if err := MakeImagesSharedForTesting(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -205,7 +217,7 @@ func TestReshared(t *testing.T) {
|
||||
}
|
||||
|
||||
// img1 is on a shared image again.
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -229,7 +241,7 @@ func TestReshared(t *testing.T) {
|
||||
}
|
||||
|
||||
// Use img1 as a render target again.
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -240,7 +252,7 @@ func TestReshared(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -250,7 +262,7 @@ func TestReshared(t *testing.T) {
|
||||
}
|
||||
|
||||
// img1 is not on a shared image due to ReplacePixels.
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -260,7 +272,7 @@ func TestReshared(t *testing.T) {
|
||||
if err := MakeImagesSharedForTesting(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -355,7 +367,13 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dst.ReplacePixels(pix)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, w, h)
|
||||
@ -397,7 +415,13 @@ func TestSmallImages(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, w, h)
|
||||
if err != nil {
|
||||
@ -439,7 +463,13 @@ func TestLongImages(t *testing.T) {
|
||||
const scale = 120
|
||||
vs := quadVertices(w, h, 0, 0, scale)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
dr := driver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: dstW,
|
||||
Height: dstH,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user