mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement this.
|
dstBounds := i.Bounds()
|
||||||
if i.isSubImage() {
|
dstRegion := driver.Region{
|
||||||
panic("ebiten: render to a sub-image is not implemented (DrawImage)")
|
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
|
// 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()
|
is := graphics.QuadIndices()
|
||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
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.
|
// Vertex represents a vertex passed to DrawTriangles.
|
||||||
@ -267,10 +270,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.isSubImage() {
|
|
||||||
panic("ebiten: render to a sub-image is not implemented (DrawTriangles)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(indices)%3 != 0 {
|
if len(indices)%3 != 0 {
|
||||||
panic("ebiten: len(indices) % 3 must be 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)?
|
// 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 {
|
if options == nil {
|
||||||
options = &DrawTrianglesOptions{}
|
options = &DrawTrianglesOptions{}
|
||||||
}
|
}
|
||||||
@ -315,7 +322,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
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.
|
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||||
@ -366,10 +373,6 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.isSubImage() {
|
|
||||||
panic("ebiten: render to a sub-image is not implemented (DrawTrianglesShader)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(indices)%3 != 0 {
|
if len(indices)%3 != 0 {
|
||||||
panic("ebiten: len(indices) % 3 must be 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)?
|
// 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 {
|
if options == nil {
|
||||||
options = &DrawTrianglesShaderOptions{}
|
options = &DrawTrianglesShaderOptions{}
|
||||||
}
|
}
|
||||||
@ -447,7 +458,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
}
|
}
|
||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
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.
|
// DrawRectShaderOptions represents options for DrawRectShader.
|
||||||
@ -498,9 +509,12 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement this.
|
dstBounds := i.Bounds()
|
||||||
if i.isSubImage() {
|
dstRegion := driver.Region{
|
||||||
panic("ebiten: rendering to a sub-image is not implemented (DrawRectShader)")
|
X: float32(dstBounds.Min.X),
|
||||||
|
Y: float32(dstBounds.Min.Y),
|
||||||
|
Width: float32(dstBounds.Dx()),
|
||||||
|
Height: float32(dstBounds.Dy()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if options == nil {
|
if options == nil {
|
||||||
@ -556,7 +570,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
}
|
}
|
||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
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.
|
// 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))
|
img := image.NewRGBA(image.Rect(0, 0, 0, 1))
|
||||||
_ = NewImageFromImage(img)
|
_ = 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.
|
// DrawTriangles draws the src image with the given vertices.
|
||||||
//
|
//
|
||||||
// Copying vertices and indices is the caller's responsibility.
|
// Copying vertices and indices is the caller's responsibility.
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.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 {
|
for _, src := range srcs {
|
||||||
if i == src {
|
if i == src {
|
||||||
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
||||||
@ -259,7 +259,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
|||||||
if maybeCanAddDelayedCommand() {
|
if maybeCanAddDelayedCommand() {
|
||||||
if tryAddDelayedCommand(func() error {
|
if tryAddDelayedCommand(func() error {
|
||||||
// Arguments are not copied. Copying is the caller's responsibility.
|
// Arguments are not copied. Copying is the caller's responsibility.
|
||||||
i.DrawTriangles(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 nil
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
||||||
@ -285,7 +285,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
|||||||
}
|
}
|
||||||
i.resolvePendingPixels(false)
|
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()
|
i.invalidatePendingPixels()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ type Graphics interface {
|
|||||||
// Draw draws an image onto another image.
|
// Draw draws an image onto another image.
|
||||||
//
|
//
|
||||||
// TODO: Merge this into DrawShader.
|
// 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.
|
// DrawShader draws the shader.
|
||||||
//
|
//
|
||||||
@ -58,7 +58,7 @@ type Graphics interface {
|
|||||||
//
|
//
|
||||||
// * float32
|
// * float32
|
||||||
// * []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.
|
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||||
|
@ -54,7 +54,7 @@ type command interface {
|
|||||||
NumIndices() int
|
NumIndices() int
|
||||||
AddNumVertices(n int)
|
AddNumVertices(n int)
|
||||||
AddNumIndices(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 {
|
type size struct {
|
||||||
@ -132,7 +132,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *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 {
|
if len(indices) > graphics.IndicesNum {
|
||||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
||||||
}
|
}
|
||||||
@ -153,10 +153,10 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
|||||||
|
|
||||||
if srcs[0] != nil {
|
if srcs[0] != nil {
|
||||||
w, h := srcs[0].InternalSize()
|
w, h := srcs[0].InternalSize()
|
||||||
sourceRegion.X /= float32(w)
|
srcRegion.X /= float32(w)
|
||||||
sourceRegion.Y /= float32(h)
|
srcRegion.Y /= float32(h)
|
||||||
sourceRegion.Width /= float32(w)
|
srcRegion.Width /= float32(w)
|
||||||
sourceRegion.Height /= float32(h)
|
srcRegion.Height /= float32(h)
|
||||||
for i := range offsets {
|
for i := range offsets {
|
||||||
offsets[i][0] /= float32(w)
|
offsets[i][0] /= float32(w)
|
||||||
offsets[i][1] /= float32(h)
|
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.
|
// TODO: If dst is the screen, reorder the command to be the last.
|
||||||
if !split && 0 < len(q.commands) {
|
if !split && 0 < len(q.commands) {
|
||||||
// TODO: Pass offsets and uniforms when merging considers the shader.
|
// 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.AddNumVertices(len(vertices))
|
||||||
last.AddNumIndices(len(indices))
|
last.AddNumIndices(len(indices))
|
||||||
return
|
return
|
||||||
@ -183,7 +183,8 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
|||||||
mode: mode,
|
mode: mode,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
address: address,
|
address: address,
|
||||||
sourceRegion: sourceRegion,
|
dstRegion: dstRegion,
|
||||||
|
srcRegion: srcRegion,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
uniforms: uniforms,
|
uniforms: uniforms,
|
||||||
}
|
}
|
||||||
@ -317,7 +318,8 @@ type drawTrianglesCommand struct {
|
|||||||
mode driver.CompositeMode
|
mode driver.CompositeMode
|
||||||
filter driver.Filter
|
filter driver.Filter
|
||||||
address driver.Address
|
address driver.Address
|
||||||
sourceRegion driver.Region
|
dstRegion driver.Region
|
||||||
|
srcRegion driver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
uniforms []interface{}
|
uniforms []interface{}
|
||||||
}
|
}
|
||||||
@ -420,9 +422,9 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
|||||||
imgs[i] = src.image.ID()
|
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 {
|
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
|
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
||||||
// with the drawTrianglesCommand c.
|
// with the drawTrianglesCommand c.
|
||||||
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.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.
|
// If a shader is used, commands are not merged.
|
||||||
//
|
//
|
||||||
// TODO: Merge shader commands considering uniform variables.
|
// TODO: Merge shader commands considering uniform variables.
|
||||||
@ -468,7 +470,10 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs
|
|||||||
if c.address != address {
|
if c.address != address {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if c.sourceRegion != sourceRegion {
|
if c.dstRegion != dstRegion {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.srcRegion != srcRegion {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -504,7 +509,7 @@ func (c *replacePixelsCommand) AddNumVertices(n int) {
|
|||||||
func (c *replacePixelsCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +537,7 @@ func (c *syncCommand) AddNumVertices(n int) {
|
|||||||
func (c *syncCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,7 +578,7 @@ func (c *pixelsCommand) AddNumVertices(n int) {
|
|||||||
func (c *pixelsCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +611,7 @@ func (c *disposeImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *disposeImageCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,7 +644,7 @@ func (c *disposeShaderCommand) AddNumVertices(n int) {
|
|||||||
func (c *disposeShaderCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +683,7 @@ func (c *newImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *newImageCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +719,7 @@ func (c *newScreenFramebufferImageCommand) AddNumVertices(n int) {
|
|||||||
func (c *newScreenFramebufferImageCommand) AddNumIndices(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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +754,7 @@ func (c *newShaderCommand) AddNumVertices(n int) {
|
|||||||
func (c *newShaderCommand) AddNumIndices(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
|
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
|
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
||||||
// elements for the source image are not used.
|
// elements for the source image are not used.
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.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.lastCommand == lastCommandNone {
|
||||||
if !i.screen && mode != driver.CompositeModeClear {
|
if !i.screen && mode != driver.CompositeModeClear {
|
||||||
panic("graphicscommand: the image must be cleared first")
|
panic("graphicscommand: the image must be cleared first")
|
||||||
@ -177,7 +177,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
|||||||
}
|
}
|
||||||
i.resolveBufferedReplacePixels()
|
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 {
|
if i.lastCommand == lastCommandNone && !i.screen {
|
||||||
i.lastCommand = lastCommandClear
|
i.lastCommand = lastCommandClear
|
||||||
|
@ -44,7 +44,13 @@ func TestClear(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w/2, h/2)
|
vs := quadVertices(w/2, h/2)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -74,8 +80,14 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
|||||||
dst := NewImage(w, h)
|
dst := NewImage(w, h)
|
||||||
vs := quadVertices(w/2, h/2)
|
vs := quadVertices(w/2, h/2)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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{
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
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)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +97,17 @@ func TestShader(t *testing.T) {
|
|||||||
dst := NewImage(w, h)
|
dst := NewImage(w, h)
|
||||||
vs := quadVertices(w, h)
|
vs := quadVertices(w, h)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
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()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -611,7 +611,7 @@ func (g *Graphics) Reset() error {
|
|||||||
return nil
|
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()
|
g.view.update()
|
||||||
|
|
||||||
rpd := mtl.RenderPassDescriptor{}
|
rpd := mtl.RenderPassDescriptor{}
|
||||||
@ -653,6 +653,12 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, srcs [graphics.
|
|||||||
ZNear: -1,
|
ZNear: -1,
|
||||||
ZFar: 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)
|
rce.SetVertexBuffer(g.vb, 0, 0)
|
||||||
|
|
||||||
for i, u := range uniforms {
|
for i, u := range uniforms {
|
||||||
@ -680,7 +686,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, srcs [graphics.
|
|||||||
return nil
|
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 := g.images[dstID]
|
||||||
dst.waitUntilSyncFinishes()
|
dst.waitUntilSyncFinishes()
|
||||||
|
|
||||||
@ -718,13 +724,13 @@ func (g *Graphics) Draw(dstID, srcID driver.ImageID, indexLen int, indexOffset i
|
|||||||
esTranslate,
|
esTranslate,
|
||||||
scale,
|
scale,
|
||||||
[]float32{
|
[]float32{
|
||||||
sourceRegion.X,
|
srcRegion.X,
|
||||||
sourceRegion.Y,
|
srcRegion.Y,
|
||||||
sourceRegion.X + sourceRegion.Width,
|
srcRegion.X + srcRegion.Width,
|
||||||
sourceRegion.Y + sourceRegion.Height,
|
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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -947,7 +953,7 @@ func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
|||||||
bce.EndEncoding()
|
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 := g.images[dstID]
|
||||||
dst.waitUntilSyncFinishes()
|
dst.waitUntilSyncFinishes()
|
||||||
|
|
||||||
@ -987,11 +993,11 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
|||||||
us[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
|
us[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
|
||||||
|
|
||||||
// Set the source region's origin of texture0.
|
// 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
|
us[graphics.TextureSourceRegionOriginUniformVariableIndex] = uorigin
|
||||||
|
|
||||||
// Set the source region's size of texture0.
|
// 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
|
us[graphics.TextureSourceRegionSizeUniformVariableIndex] = ussize
|
||||||
|
|
||||||
// Set the additional uniform variables.
|
// Set the additional uniform variables.
|
||||||
@ -1000,7 +1006,7 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
|||||||
us[offset+i] = v
|
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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -650,6 +650,13 @@ func (rce RenderCommandEncoder) SetViewport(viewport Viewport) {
|
|||||||
C.RenderCommandEncoder_SetViewport(rce.commandEncoder, viewport.c())
|
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
|
// 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.
|
// 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),
|
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;
|
double ZFar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ScissorRect {
|
||||||
|
uint_t X;
|
||||||
|
uint_t Y;
|
||||||
|
uint_t Width;
|
||||||
|
uint_t Height;
|
||||||
|
};
|
||||||
|
|
||||||
struct Device CreateSystemDefaultDevice();
|
struct Device CreateSystemDefaultDevice();
|
||||||
struct Devices CopyAllDevices();
|
struct Devices CopyAllDevices();
|
||||||
|
|
||||||
@ -139,6 +146,8 @@ void RenderCommandEncoder_SetRenderPipelineState(void *renderCommandEncoder,
|
|||||||
void *renderPipelineState);
|
void *renderPipelineState);
|
||||||
void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
||||||
struct Viewport viewport);
|
struct Viewport viewport);
|
||||||
|
void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
|
||||||
|
struct ScissorRect scissorRect);
|
||||||
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||||
void *buffer, uint_t offset,
|
void *buffer, uint_t offset,
|
||||||
uint_t index);
|
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 RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||||
void *buffer, uint_t offset,
|
void *buffer, uint_t offset,
|
||||||
uint_t index) {
|
uint_t index) {
|
||||||
|
@ -116,6 +116,7 @@ func (c *context) reset() error {
|
|||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = driver.CompositeModeUnknown
|
c.lastCompositeMode = driver.CompositeModeUnknown
|
||||||
gl.Enable(gl.BLEND)
|
gl.Enable(gl.BLEND)
|
||||||
|
gl.Enable(gl.SCISSOR_TEST)
|
||||||
|
|
||||||
c.blendFunc(driver.CompositeModeSourceOver)
|
c.blendFunc(driver.CompositeModeSourceOver)
|
||||||
|
|
||||||
@ -135,6 +136,10 @@ func (c *context) blendFunc(mode driver.CompositeMode) {
|
|||||||
gl.BlendFunc(uint32(s2), uint32(d2))
|
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) {
|
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||||
var t uint32
|
var t uint32
|
||||||
gl.GenTextures(1, &t)
|
gl.GenTextures(1, &t)
|
||||||
|
@ -104,6 +104,7 @@ var (
|
|||||||
nearest js.Value
|
nearest js.Value
|
||||||
noError js.Value
|
noError js.Value
|
||||||
rgba js.Value
|
rgba js.Value
|
||||||
|
scissorTest js.Value
|
||||||
texture2d js.Value
|
texture2d js.Value
|
||||||
textureMagFilter js.Value
|
textureMagFilter js.Value
|
||||||
textureMinFilter js.Value
|
textureMinFilter js.Value
|
||||||
@ -159,6 +160,7 @@ func init() {
|
|||||||
nearest = contextPrototype.Get("NEAREST")
|
nearest = contextPrototype.Get("NEAREST")
|
||||||
noError = contextPrototype.Get("NO_ERROR")
|
noError = contextPrototype.Get("NO_ERROR")
|
||||||
rgba = contextPrototype.Get("RGBA")
|
rgba = contextPrototype.Get("RGBA")
|
||||||
|
scissorTest = contextPrototype.Get("SCISSOR_TEST")
|
||||||
texture0 = contextPrototype.Get("TEXTURE0").Int()
|
texture0 = contextPrototype.Get("TEXTURE0").Int()
|
||||||
texture2d = contextPrototype.Get("TEXTURE_2D")
|
texture2d = contextPrototype.Get("TEXTURE_2D")
|
||||||
textureMagFilter = contextPrototype.Get("TEXTURE_MAG_FILTER")
|
textureMagFilter = contextPrototype.Get("TEXTURE_MAG_FILTER")
|
||||||
@ -222,6 +224,7 @@ func (c *context) reset() error {
|
|||||||
}
|
}
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("enable", blend)
|
gl.Call("enable", blend)
|
||||||
|
gl.Call("enable", scissorTest)
|
||||||
c.blendFunc(driver.CompositeModeSourceOver)
|
c.blendFunc(driver.CompositeModeSourceOver)
|
||||||
f := gl.Call("getParameter", framebufferBinding)
|
f := gl.Call("getParameter", framebufferBinding)
|
||||||
c.screenFramebuffer = framebufferNative(f)
|
c.screenFramebuffer = framebufferNative(f)
|
||||||
@ -240,6 +243,11 @@ func (c *context) blendFunc(mode driver.CompositeMode) {
|
|||||||
gl.Call("blendFunc", int(s2), int(d2))
|
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) {
|
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||||
c.ensureGL()
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
|
@ -106,6 +106,7 @@ func (c *context) reset() error {
|
|||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = driver.CompositeModeUnknown
|
c.lastCompositeMode = driver.CompositeModeUnknown
|
||||||
c.ctx.Enable(gles.BLEND)
|
c.ctx.Enable(gles.BLEND)
|
||||||
|
c.ctx.Enable(gles.SCISSOR_TEST)
|
||||||
c.blendFunc(driver.CompositeModeSourceOver)
|
c.blendFunc(driver.CompositeModeSourceOver)
|
||||||
f := make([]int32, 1)
|
f := make([]int32, 1)
|
||||||
c.ctx.GetIntegerv(f, gles.FRAMEBUFFER_BINDING)
|
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))
|
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) {
|
func (c *context) newTexture(width, height int) (textureNative, error) {
|
||||||
t := c.ctx.GenTextures(1)[0]
|
t := c.ctx.GenTextures(1)[0]
|
||||||
if t <= 0 {
|
if t <= 0 {
|
||||||
|
@ -57,6 +57,7 @@ const (
|
|||||||
TEXTURE_WRAP_S = 0x2802
|
TEXTURE_WRAP_S = 0x2802
|
||||||
TEXTURE_WRAP_T = 0x2803
|
TEXTURE_WRAP_T = 0x2803
|
||||||
TRIANGLES = 0x0004
|
TRIANGLES = 0x0004
|
||||||
|
SCISSOR_TEST = 0x0C11
|
||||||
UNPACK_ALIGNMENT = 0x0CF5
|
UNPACK_ALIGNMENT = 0x0CF5
|
||||||
UNSIGNED_BYTE = 0x1401
|
UNSIGNED_BYTE = 0x1401
|
||||||
UNSIGNED_SHORT = 0x1403
|
UNSIGNED_SHORT = 0x1403
|
||||||
|
@ -147,6 +147,7 @@ package gl
|
|||||||
// typedef void (APIENTRYP GPLINKPROGRAM)(GLuint program);
|
// typedef void (APIENTRYP GPLINKPROGRAM)(GLuint program);
|
||||||
// typedef void (APIENTRYP GPPIXELSTOREI)(GLenum pname, GLint param);
|
// 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 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 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 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);
|
// 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) {
|
// 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);
|
// (*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) {
|
// static void glowShaderSource(GPSHADERSOURCE fnptr, GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) {
|
||||||
// (*fnptr)(shader, count, string, length);
|
// (*fnptr)(shader, count, string, length);
|
||||||
// }
|
// }
|
||||||
@ -428,6 +432,7 @@ var (
|
|||||||
gpLinkProgram C.GPLINKPROGRAM
|
gpLinkProgram C.GPLINKPROGRAM
|
||||||
gpPixelStorei C.GPPIXELSTOREI
|
gpPixelStorei C.GPPIXELSTOREI
|
||||||
gpReadPixels C.GPREADPIXELS
|
gpReadPixels C.GPREADPIXELS
|
||||||
|
gpScissor C.GPSCISSOR
|
||||||
gpShaderSource C.GPSHADERSOURCE
|
gpShaderSource C.GPSHADERSOURCE
|
||||||
gpTexImage2D C.GPTEXIMAGE2D
|
gpTexImage2D C.GPTEXIMAGE2D
|
||||||
gpTexParameteri C.GPTEXPARAMETERI
|
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)
|
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) {
|
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)))
|
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 {
|
if gpReadPixels == nil {
|
||||||
return errors.New("glReadPixels")
|
return errors.New("glReadPixels")
|
||||||
}
|
}
|
||||||
|
gpScissor = (C.GPSCISSOR)(getProcAddr("glScissor"))
|
||||||
|
if gpScissor == nil {
|
||||||
|
return errors.New("glScissor")
|
||||||
|
}
|
||||||
gpShaderSource = (C.GPSHADERSOURCE)(getProcAddr("glShaderSource"))
|
gpShaderSource = (C.GPSHADERSOURCE)(getProcAddr("glShaderSource"))
|
||||||
if gpShaderSource == nil {
|
if gpShaderSource == nil {
|
||||||
return errors.New("glShaderSource")
|
return errors.New("glShaderSource")
|
||||||
|
@ -62,6 +62,7 @@ var (
|
|||||||
gpLinkProgram uintptr
|
gpLinkProgram uintptr
|
||||||
gpPixelStorei uintptr
|
gpPixelStorei uintptr
|
||||||
gpReadPixels uintptr
|
gpReadPixels uintptr
|
||||||
|
gpScissor uintptr
|
||||||
gpShaderSource uintptr
|
gpShaderSource uintptr
|
||||||
gpTexImage2D uintptr
|
gpTexImage2D uintptr
|
||||||
gpTexParameteri 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)
|
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) {
|
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)
|
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 {
|
if gpReadPixels == 0 {
|
||||||
return errors.New("glReadPixels")
|
return errors.New("glReadPixels")
|
||||||
}
|
}
|
||||||
|
gpScissor = getProcAddr("glScissor")
|
||||||
|
if gpScissor == 0 {
|
||||||
|
return errors.New("glScissor")
|
||||||
|
}
|
||||||
gpShaderSource = getProcAddr("glShaderSource")
|
gpShaderSource = getProcAddr("glShaderSource")
|
||||||
if gpShaderSource == 0 {
|
if gpShaderSource == 0 {
|
||||||
return errors.New("glShaderSource")
|
return errors.New("glShaderSource")
|
||||||
|
@ -54,6 +54,7 @@ const (
|
|||||||
NO_ERROR = 0
|
NO_ERROR = 0
|
||||||
READ_WRITE = 0x88BA
|
READ_WRITE = 0x88BA
|
||||||
RGBA = 0x1908
|
RGBA = 0x1908
|
||||||
|
SCISSOR_TEST = 0x0C11
|
||||||
TEXTURE0 = 0x84C0
|
TEXTURE0 = 0x84C0
|
||||||
TEXTURE_2D = 0x0DE1
|
TEXTURE_2D = 0x0DE1
|
||||||
TEXTURE_MAG_FILTER = 0x2800
|
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]))
|
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) {
|
func (DefaultContext) ShaderSource(shader uint32, xstring string) {
|
||||||
s, free := cStringPtr(xstring)
|
s, free := cStringPtr(xstring)
|
||||||
defer free()
|
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))
|
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) {
|
func (g *GomobileContext) ShaderSource(shader uint32, xstring string) {
|
||||||
g.ctx.ShaderSource(gl.Shader{Value: shader}, xstring)
|
g.ctx.ShaderSource(gl.Shader{Value: shader}, xstring)
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ type Context interface {
|
|||||||
LinkProgram(program uint32)
|
LinkProgram(program uint32)
|
||||||
PixelStorei(pname uint32, param int32)
|
PixelStorei(pname uint32, param int32)
|
||||||
ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32)
|
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)
|
ShaderSource(shader uint32, xstring string)
|
||||||
TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
|
TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
|
||||||
TexParameteri(target uint32, pname uint32, param int32)
|
TexParameteri(target uint32, pname uint32, param int32)
|
||||||
|
@ -148,7 +148,7 @@ func (g *Graphics) SetVertices(vertices []float32, indices []uint16) {
|
|||||||
g.context.elementArrayBufferSubData(indices)
|
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]
|
destination := g.images[dst]
|
||||||
source := g.images[src]
|
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 {
|
if err := destination.setViewport(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
g.context.scissor(
|
||||||
|
int(dstRegion.X),
|
||||||
|
int(dstRegion.Y),
|
||||||
|
int(dstRegion.Width),
|
||||||
|
int(dstRegion.Height),
|
||||||
|
)
|
||||||
g.context.blendFunc(mode)
|
g.context.blendFunc(mode)
|
||||||
|
|
||||||
program := g.state.programs[programKey{
|
program := g.state.programs[programKey{
|
||||||
@ -176,10 +182,10 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
|
|||||||
}, uniformVariable{
|
}, uniformVariable{
|
||||||
name: "source_region",
|
name: "source_region",
|
||||||
value: []float32{
|
value: []float32{
|
||||||
sourceRegion.X,
|
srcRegion.X,
|
||||||
sourceRegion.Y,
|
srcRegion.Y,
|
||||||
sourceRegion.X + sourceRegion.Width,
|
srcRegion.X + srcRegion.Width,
|
||||||
sourceRegion.Y + sourceRegion.Height,
|
srcRegion.Y + srcRegion.Height,
|
||||||
},
|
},
|
||||||
typ: shaderir.Type{Main: shaderir.Vec4},
|
typ: shaderir.Type{Main: shaderir.Vec4},
|
||||||
})
|
})
|
||||||
@ -284,7 +290,7 @@ func (g *Graphics) removeShader(shader *Shader) {
|
|||||||
delete(g.shaders, shader.id)
|
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]
|
d := g.images[dst]
|
||||||
s := g.shaders[shader]
|
s := g.shaders[shader]
|
||||||
|
|
||||||
@ -293,6 +299,12 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
|||||||
if err := d.setViewport(); err != nil {
|
if err := d.setViewport(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
g.context.scissor(
|
||||||
|
int(dstRegion.X),
|
||||||
|
int(dstRegion.Y),
|
||||||
|
int(dstRegion.Width),
|
||||||
|
int(dstRegion.Height),
|
||||||
|
)
|
||||||
g.context.blendFunc(mode)
|
g.context.blendFunc(mode)
|
||||||
|
|
||||||
us := make([]uniformVariable, graphics.PreservedUniformVariablesNum+len(uniforms))
|
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]
|
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
|
const idx = graphics.TextureSourceRegionOriginUniformVariableIndex
|
||||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||||
us[idx].value = origin
|
us[idx].value = origin
|
||||||
us[idx].typ = s.ir.Uniforms[idx]
|
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
|
const idx = graphics.TextureSourceRegionSizeUniformVariableIndex
|
||||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||||
us[idx].value = size
|
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)
|
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 {
|
if len(indices) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices [
|
|||||||
imgs[i] = src.orig
|
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()
|
m.disposeMipmaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +225,14 @@ func (m *Mipmap) level(level int) *buffered.Image {
|
|||||||
}
|
}
|
||||||
s := buffered.NewImage(w2, h2)
|
s := buffered.NewImage(w2, h2)
|
||||||
s.SetVolatile(m.volatile)
|
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
|
m.imgs[level] = s
|
||||||
|
|
||||||
return m.imgs[level]
|
return m.imgs[level]
|
||||||
|
@ -77,7 +77,8 @@ type drawTrianglesHistoryItem struct {
|
|||||||
mode driver.CompositeMode
|
mode driver.CompositeMode
|
||||||
filter driver.Filter
|
filter driver.Filter
|
||||||
address driver.Address
|
address driver.Address
|
||||||
sourceRegion driver.Region
|
dstRegion driver.Region
|
||||||
|
srcRegion driver.Region
|
||||||
shader *Shader
|
shader *Shader
|
||||||
uniforms []interface{}
|
uniforms []interface{}
|
||||||
}
|
}
|
||||||
@ -269,7 +270,13 @@ func fillImage(i *graphicscommand.Image, clr color.RGBA) {
|
|||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}
|
srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}
|
||||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
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.
|
// 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
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 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 {
|
if i.priority {
|
||||||
panic("restorable: DrawTriangles cannot be called on a priority image")
|
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 {
|
if srcstale || i.screen || !needsRestoring() || i.volatile {
|
||||||
i.makeStale()
|
i.makeStale()
|
||||||
} else {
|
} 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
|
var s *graphicscommand.Shader
|
||||||
@ -402,11 +409,11 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
|||||||
}
|
}
|
||||||
s = shader.shader
|
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.
|
// 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 {
|
if i.stale || i.volatile || i.screen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -433,7 +440,8 @@ func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image,
|
|||||||
mode: mode,
|
mode: mode,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
address: address,
|
address: address,
|
||||||
sourceRegion: sourceRegion,
|
dstRegion: dstRegion,
|
||||||
|
srcRegion: srcRegion,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
uniforms: uniforms,
|
uniforms: uniforms,
|
||||||
}
|
}
|
||||||
@ -625,7 +633,7 @@ func (i *Image) restore() error {
|
|||||||
}
|
}
|
||||||
imgs[i] = img.image
|
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 {
|
if len(i.drawTrianglesHistory) > 0 {
|
||||||
|
@ -131,7 +131,13 @@ func TestRestoreChain(t *testing.T) {
|
|||||||
for i := 0; i < num-1; i++ {
|
for i := 0; i < num-1; i++ {
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
imgs[i+1].DrawTriangles([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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
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)
|
imgs[8].ReplacePixels([]byte{clr8.R, clr8.G, clr8.B, clr8.A}, 0, 0, w, h)
|
||||||
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
imgs[8].DrawTriangles([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)
|
dr := driver.Region{
|
||||||
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)
|
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++ {
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -216,10 +228,16 @@ func TestRestoreOverrideSource(t *testing.T) {
|
|||||||
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
||||||
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img2.DrawTriangles([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)
|
dr := driver.Region{
|
||||||
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)
|
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)
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -298,24 +316,30 @@ func TestRestoreComplexGraph(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
|
dr := driver.Region{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Width: w,
|
||||||
|
Height: h,
|
||||||
|
}
|
||||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -407,8 +431,14 @@ func TestRestoreRecursive(t *testing.T) {
|
|||||||
img0.Dispose()
|
img0.Dispose()
|
||||||
}()
|
}()
|
||||||
is := graphics.QuadIndices()
|
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)
|
dr := driver.Region{
|
||||||
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)
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -502,7 +532,13 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles([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)
|
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -539,8 +575,14 @@ func TestDispose(t *testing.T) {
|
|||||||
defer img2.Dispose()
|
defer img2.Dispose()
|
||||||
|
|
||||||
is := graphics.QuadIndices()
|
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)
|
dr := driver.Region{
|
||||||
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)
|
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()
|
img1.Dispose()
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -648,7 +690,13 @@ func TestReplacePixelsOnly(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles([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)
|
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||||
|
|
||||||
// BasePixelsForTesting is available without GPU accessing.
|
// BasePixelsForTesting is available without GPU accessing.
|
||||||
@ -702,7 +750,13 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
|||||||
src.ReplacePixels(pix, 0, 0, w, h)
|
src.ReplacePixels(pix, 0, 0, w, h)
|
||||||
vs := quadVertices(1, 1, 0, 0)
|
vs := quadVertices(1, 1, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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
|
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
||||||
// stale.
|
// stale.
|
||||||
@ -723,7 +777,13 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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)
|
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||||
// ReplacePixels for a whole image doesn't panic.
|
// ReplacePixels for a whole image doesn't panic.
|
||||||
}
|
}
|
||||||
@ -741,7 +801,13 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,7 +896,13 @@ func TestFill2(t *testing.T) {
|
|||||||
dst := NewImage(w, h)
|
dst := NewImage(w, h)
|
||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := graphics.QuadIndices()
|
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.
|
// Fill src with a different color. This should not affect dst.
|
||||||
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
||||||
@ -869,7 +941,13 @@ func TestMutateSlices(t *testing.T) {
|
|||||||
vs := quadVertices(w, h, 0, 0)
|
vs := quadVertices(w, h, 0, 0)
|
||||||
is := make([]uint16, len(graphics.QuadIndices()))
|
is := make([]uint16, len(graphics.QuadIndices()))
|
||||||
copy(is, graphics.QuadIndices())
|
copy(is, graphics.QuadIndices())
|
||||||
dst.DrawTriangles([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 {
|
for i := range vs {
|
||||||
vs[i] = 0
|
vs[i] = 0
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,13 @@ func TestShader(t *testing.T) {
|
|||||||
|
|
||||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -60,7 +66,13 @@ func TestShaderChain(t *testing.T) {
|
|||||||
ir := etesting.ShaderProgramImages(1)
|
ir := etesting.ShaderProgramImages(1)
|
||||||
s := NewShader(&ir)
|
s := NewShader(&ir)
|
||||||
for i := 0; i < num-1; i++ {
|
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 {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -93,7 +105,13 @@ func TestShaderMultipleSources(t *testing.T) {
|
|||||||
ir := etesting.ShaderProgramImages(3)
|
ir := etesting.ShaderProgramImages(3)
|
||||||
s := NewShader(&ir)
|
s := NewShader(&ir)
|
||||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
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.
|
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||||
srcs[0].Fill(color.RGBA{})
|
srcs[0].Fill(color.RGBA{})
|
||||||
@ -129,7 +147,13 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
|
|||||||
{1, 0},
|
{1, 0},
|
||||||
{2, 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.
|
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||||
srcs[0].Fill(color.RGBA{})
|
srcs[0].Fill(color.RGBA{})
|
||||||
@ -154,7 +178,13 @@ func TestShaderDispose(t *testing.T) {
|
|||||||
|
|
||||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
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
|
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
|
||||||
// stale.
|
// stale.
|
||||||
|
@ -241,7 +241,13 @@ func (i *Image) ensureNotShared() {
|
|||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
srcs := [graphics.ShaderImageNum]*restorable.Image{i.backend.restorable}
|
srcs := [graphics.ShaderImageNum]*restorable.Image{i.backend.restorable}
|
||||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
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.dispose(false)
|
||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
@ -325,7 +331,7 @@ func (i *Image) processSrc(src *Image) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.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()
|
backendsM.Lock()
|
||||||
// Do not use defer for performance.
|
// Do not use defer for performance.
|
||||||
|
|
||||||
@ -345,6 +351,9 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
|||||||
dy = paddingSize
|
dy = paddingSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dstRegion.X += dx
|
||||||
|
dstRegion.Y += dx
|
||||||
|
|
||||||
var oxf, oyf float32
|
var oxf, oyf float32
|
||||||
if srcs[0] != nil {
|
if srcs[0] != nil {
|
||||||
ox, oy, _, _ := srcs[0].regionWithPadding()
|
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+2] += oxf
|
||||||
vertices[i*graphics.VertexFloatNum+3] += oyf
|
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).
|
// performance issue (#1293).
|
||||||
if sourceRegion.Width != 0 && sourceRegion.Height != 0 {
|
if srcRegion.Width != 0 && srcRegion.Height != 0 {
|
||||||
sourceRegion.X += oxf
|
srcRegion.X += oxf
|
||||||
sourceRegion.Y += oyf
|
srcRegion.Y += oyf
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n := len(vertices) / graphics.VertexFloatNum
|
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 {
|
for _, src := range srcs {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
@ -428,6 +437,7 @@ func (i *Image) Fill(clr color.RGBA) {
|
|||||||
i.ensureNotShared()
|
i.ensureNotShared()
|
||||||
|
|
||||||
// As *restorable.Image is an independent image, it is fine to fill the entire image.
|
// 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)
|
i.backend.restorable.Fill(clr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,13 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
// img4.ensureNotShared() should be called.
|
// img4.ensureNotShared() should be called.
|
||||||
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img4.DrawTriangles([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
|
want := false
|
||||||
if got := img4.IsSharedForTesting(); got != want {
|
if got := img4.IsSharedForTesting(); got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
@ -126,7 +132,7 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
|
|
||||||
// Check further drawing doesn't cause panic.
|
// Check further drawing doesn't cause panic.
|
||||||
// This bug was fixed by 03dcd948.
|
// This bug was fixed by 03dcd948.
|
||||||
img4.DrawTriangles([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) {
|
func TestReshared(t *testing.T) {
|
||||||
@ -167,7 +173,13 @@ func TestReshared(t *testing.T) {
|
|||||||
// Use img1 as a render target.
|
// Use img1 as a render target.
|
||||||
vs := quadVertices(size, size, 0, 0, 1)
|
vs := quadVertices(size, size, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
img1.DrawTriangles([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 {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -177,7 +189,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", 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.
|
// 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 {
|
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||||
t.Errorf("got: %v, want: %v", 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.
|
// 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 {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -240,7 +252,7 @@ func TestReshared(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
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 {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", 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.
|
// 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 {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -260,7 +272,7 @@ func TestReshared(t *testing.T) {
|
|||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", 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)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
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)
|
dst.ReplacePixels(pix)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
@ -397,7 +415,13 @@ func TestSmallImages(t *testing.T) {
|
|||||||
|
|
||||||
vs := quadVertices(w, h, 0, 0, 1)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -439,7 +463,13 @@ func TestLongImages(t *testing.T) {
|
|||||||
const scale = 120
|
const scale = 120
|
||||||
vs := quadVertices(w, h, 0, 0, scale)
|
vs := quadVertices(w, h, 0, 0, scale)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles([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)
|
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user