mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-03 08:25:34 +00:00
gpu/headless,gpu/internal: rename "backend" files and names to "driver"
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package headless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"gioui.org/gpu/internal/driver"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/internal/unsafe"
|
||||
)
|
||||
|
||||
var dumpImages = flag.Bool("saveimages", false, "save test images")
|
||||
|
||||
var clearCol = color.NRGBA{A: 0xff, R: 0xde, G: 0xad, B: 0xbe}
|
||||
var clearColExpect = f32color.NRGBAToRGBA(clearCol)
|
||||
|
||||
func TestFramebufferClear(t *testing.T) {
|
||||
b := newDriver(t)
|
||||
sz := image.Point{X: 800, Y: 600}
|
||||
fbo := setupFBO(t, b, sz)
|
||||
img := screenshot(t, b, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleShader(t *testing.T) {
|
||||
b := newDriver(t)
|
||||
sz := image.Point{X: 800, Y: 600}
|
||||
fbo := setupFBO(t, b, sz)
|
||||
p, err := b.NewProgram(shader_simple_vert, shader_simple_frag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.Release()
|
||||
b.BindProgram(p)
|
||||
b.DrawArrays(driver.DrawModeTriangles, 0, 3)
|
||||
img := screenshot(t, b, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
// Just off the center to catch inverted triangles.
|
||||
cx, cy := 300, 400
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(exp))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputShader(t *testing.T) {
|
||||
b := newDriver(t)
|
||||
sz := image.Point{X: 800, Y: 600}
|
||||
fbo := setupFBO(t, b, sz)
|
||||
p, err := b.NewProgram(shader_input_vert, shader_simple_frag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.Release()
|
||||
b.BindProgram(p)
|
||||
buf, err := b.NewImmutableBuffer(driver.BufferBindingVertices,
|
||||
unsafe.BytesView([]float32{
|
||||
0, .5, .5, 1,
|
||||
-.5, -.5, .5, 1,
|
||||
.5, -.5, .5, 1,
|
||||
}),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer buf.Release()
|
||||
b.BindVertexBuffer(buf, 4*4, 0)
|
||||
layout, err := b.NewInputLayout(shader_input_vert, []driver.InputDesc{
|
||||
{
|
||||
Type: driver.DataTypeFloat,
|
||||
Size: 4,
|
||||
Offset: 0,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer layout.Release()
|
||||
b.BindInputLayout(layout)
|
||||
b.DrawArrays(driver.DrawModeTriangles, 0, 3)
|
||||
img := screenshot(t, b, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
cx, cy := 300, 400
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(exp))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebuffers(t *testing.T) {
|
||||
b := newDriver(t)
|
||||
sz := image.Point{X: 800, Y: 600}
|
||||
fbo1 := newFBO(t, b, sz)
|
||||
fbo2 := newFBO(t, b, sz)
|
||||
var (
|
||||
col1 = color.NRGBA{R: 0xac, G: 0xbd, B: 0xef, A: 0xde}
|
||||
col2 = color.NRGBA{R: 0xfe, G: 0xba, B: 0xbe, A: 0xca}
|
||||
)
|
||||
fcol1, fcol2 := f32color.LinearFromSRGB(col1), f32color.LinearFromSRGB(col2)
|
||||
b.BindFramebuffer(fbo1)
|
||||
b.Clear(fcol1.Float32())
|
||||
b.BindFramebuffer(fbo2)
|
||||
b.Clear(fcol2.Float32())
|
||||
img := screenshot(t, b, fbo1, sz)
|
||||
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col1) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col1))
|
||||
}
|
||||
img = screenshot(t, b, fbo2, sz)
|
||||
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col2) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col2))
|
||||
}
|
||||
}
|
||||
|
||||
func setupFBO(t *testing.T, b driver.Device, size image.Point) driver.Framebuffer {
|
||||
fbo := newFBO(t, b, size)
|
||||
b.BindFramebuffer(fbo)
|
||||
// ClearColor accepts linear RGBA colors, while 8-bit colors
|
||||
// are in the sRGB color space.
|
||||
col := f32color.LinearFromSRGB(clearCol)
|
||||
b.Clear(col.Float32())
|
||||
b.ClearDepth(0.0)
|
||||
b.Viewport(0, 0, size.X, size.Y)
|
||||
return fbo
|
||||
}
|
||||
|
||||
func newFBO(t *testing.T, b driver.Device, size image.Point) driver.Framebuffer {
|
||||
fboTex, err := b.NewTexture(
|
||||
driver.TextureFormatSRGB,
|
||||
size.X, size.Y,
|
||||
driver.FilterNearest, driver.FilterNearest,
|
||||
driver.BufferBindingFramebuffer,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
fboTex.Release()
|
||||
})
|
||||
const depthBits = 16
|
||||
fbo, err := b.NewFramebuffer(fboTex, depthBits)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
fbo.Release()
|
||||
})
|
||||
return fbo
|
||||
}
|
||||
|
||||
func newDriver(t *testing.T) driver.Device {
|
||||
ctx, err := newContext()
|
||||
if err != nil {
|
||||
t.Skipf("no context available: %v", err)
|
||||
}
|
||||
runtime.LockOSThread()
|
||||
if err := ctx.MakeCurrent(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err := driver.NewDevice(ctx.API())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b.BeginFrame()
|
||||
t.Cleanup(func() {
|
||||
b.EndFrame()
|
||||
ctx.ReleaseCurrent()
|
||||
runtime.UnlockOSThread()
|
||||
ctx.Release()
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
func screenshot(t *testing.T, d driver.Device, fbo driver.Framebuffer, size image.Point) *image.RGBA {
|
||||
img, err := driver.DownloadImage(d, fbo, image.Rectangle{Max: size})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if *dumpImages {
|
||||
if err := saveImage(t.Name()+".png", img); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
return img
|
||||
}
|
||||
|
||||
func saveImage(file string, img image.Image) error {
|
||||
var buf bytes.Buffer
|
||||
if err := png.Encode(&buf, img); err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(file, buf.Bytes(), 0666)
|
||||
}
|
||||
Reference in New Issue
Block a user