mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
@@ -9,11 +9,11 @@ import (
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"gioui.org/gpu/backend"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/internal/unsafe"
|
||||
)
|
||||
|
||||
@@ -48,8 +48,8 @@ func TestSimpleShader(t *testing.T) {
|
||||
}
|
||||
// Just off the center to catch inverted triangles.
|
||||
cx, cy := 300, 400
|
||||
shaderCol := [4]float32{.25, .55, .75, 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), tosRGB(shaderCol); got != exp {
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
||||
t.Errorf("got color %v, expected %v", got, exp)
|
||||
}
|
||||
}
|
||||
@@ -94,8 +94,8 @@ func TestInputShader(t *testing.T) {
|
||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
||||
}
|
||||
cx, cy := 300, 400
|
||||
shaderCol := [4]float32{.25, .55, .75, 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), tosRGB(shaderCol); got != exp {
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
||||
t.Errorf("got color %v, expected %v", got, exp)
|
||||
}
|
||||
}
|
||||
@@ -109,11 +109,11 @@ func TestFramebuffers(t *testing.T) {
|
||||
col1 = color.RGBA{R: 0xad, G: 0xbe, B: 0xef, A: 0xde}
|
||||
col2 = color.RGBA{R: 0xfe, G: 0xba, B: 0xbe, A: 0xca}
|
||||
)
|
||||
fcol1, fcol2 := fromsRGB(col1), fromsRGB(col2)
|
||||
b.ClearColor(fcol1[0], fcol1[1], fcol1[2], fcol1[3])
|
||||
fcol1, fcol2 := f32color.RGBAFromSRGB(col1), f32color.RGBAFromSRGB(col2)
|
||||
b.ClearColor(fcol1.Float32())
|
||||
b.BindFramebuffer(fbo1)
|
||||
b.Clear(backend.BufferAttachmentColor)
|
||||
b.ClearColor(fcol2[0], fcol2[1], fcol2[2], fcol2[3])
|
||||
b.ClearColor(fcol2.Float32())
|
||||
b.BindFramebuffer(fbo2)
|
||||
b.Clear(backend.BufferAttachmentColor)
|
||||
img := screenshot(t, fbo1, sz)
|
||||
@@ -174,8 +174,8 @@ func newBackend(t *testing.T) backend.Device {
|
||||
b.BeginFrame()
|
||||
// ClearColor accepts linear RGBA colors, while 8-bit colors
|
||||
// are in the sRGB color space.
|
||||
col := fromsRGB(clearCol)
|
||||
b.ClearColor(col[0], col[1], col[2], col[3])
|
||||
col := f32color.RGBAFromSRGB(clearCol)
|
||||
b.ClearColor(col.Float32())
|
||||
t.Cleanup(func() {
|
||||
b.EndFrame()
|
||||
ctx.ReleaseCurrent()
|
||||
@@ -209,38 +209,3 @@ func saveImage(file string, img image.Image) error {
|
||||
}
|
||||
return ioutil.WriteFile(file, buf.Bytes(), 0666)
|
||||
}
|
||||
|
||||
func tosRGB(col [4]float32) color.RGBA {
|
||||
for i := 0; i <= 2; i++ {
|
||||
c := col[i]
|
||||
// Use the formula from EXT_sRGB.
|
||||
switch {
|
||||
case c <= 0:
|
||||
c = 0
|
||||
case 0 < c && c < 0.0031308:
|
||||
c = 12.92 * c
|
||||
case 0.0031308 <= c && c < 1:
|
||||
c = 1.055*float32(math.Pow(float64(c), 0.41666)) - 0.055
|
||||
case c >= 1:
|
||||
c = 1
|
||||
}
|
||||
col[i] = c
|
||||
}
|
||||
return color.RGBA{R: uint8(col[0]*255 + .5), G: uint8(col[1]*255 + .5), B: uint8(col[2]*255 + .5), A: uint8(col[3]*255 + .5)}
|
||||
}
|
||||
|
||||
func fromsRGB(col color.Color) [4]float32 {
|
||||
r, g, b, a := col.RGBA()
|
||||
color := [4]float32{float32(r) / 0xffff, float32(g) / 0xffff, float32(b) / 0xffff, float32(a) / 0xffff}
|
||||
for i := 0; i <= 2; i++ {
|
||||
c := color[i]
|
||||
// Use the formula from EXT_sRGB.
|
||||
if c <= 0.04045 {
|
||||
c = c / 12.92
|
||||
} else {
|
||||
c = float32(math.Pow(float64((c+0.055)/1.055), 2.4))
|
||||
}
|
||||
color[i] = c
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"gioui.org/gpu/backend"
|
||||
"gioui.org/internal/f32color"
|
||||
gunsafe "gioui.org/internal/unsafe"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
@@ -26,7 +27,7 @@ type Device struct {
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
clearColor [4]float32
|
||||
clearColor f32color.RGBA
|
||||
clearDepth float32
|
||||
viewport _D3D11_VIEWPORT
|
||||
depthState depthState
|
||||
@@ -539,7 +540,7 @@ func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources)
|
||||
}
|
||||
|
||||
func (b *Backend) ClearColor(colr, colg, colb, cola float32) {
|
||||
b.clearColor = [...]float32{colr, colg, colb, cola}
|
||||
b.clearColor = f32color.RGBA{R: colr, G: colg, B: colb, A: cola}
|
||||
}
|
||||
|
||||
func (b *Backend) Clear(buffers backend.BufferAttachments) {
|
||||
|
||||
@@ -5,9 +5,10 @@ package d3d11
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"syscall"
|
||||
"gioui.org/internal/f32color"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
@@ -1033,7 +1034,7 @@ func (c *_ID3D11DeviceContext) ClearDepthStencilView(target *_ID3D11DepthStencil
|
||||
)
|
||||
}
|
||||
|
||||
func (c *_ID3D11DeviceContext) ClearRenderTargetView(target *_ID3D11RenderTargetView, color *[4]float32) {
|
||||
func (c *_ID3D11DeviceContext) ClearRenderTargetView(target *_ID3D11RenderTargetView, color *f32color.RGBA) {
|
||||
syscall.Syscall(
|
||||
c.vtbl.ClearRenderTargetView,
|
||||
3,
|
||||
@@ -1243,7 +1244,7 @@ func (c *_ID3D11DeviceContext) DrawIndexed(count, start uint32, base int32) {
|
||||
)
|
||||
}
|
||||
|
||||
func (c *_ID3D11DeviceContext) OMSetBlendState(state *_ID3D11BlendState, factor *[4]float32, sampleMask uint32) {
|
||||
func (c *_ID3D11DeviceContext) OMSetBlendState(state *_ID3D11BlendState, factor *f32color.RGBA, sampleMask uint32) {
|
||||
syscall.Syscall6(
|
||||
c.vtbl.OMSetBlendState,
|
||||
4,
|
||||
|
||||
+10
-25
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/gpu/backend"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/internal/opconst"
|
||||
"gioui.org/internal/ops"
|
||||
"gioui.org/internal/path"
|
||||
@@ -54,7 +55,7 @@ type drawOps struct {
|
||||
reader ops.Reader
|
||||
cache *resourceCache
|
||||
viewport image.Point
|
||||
clearColor [3]float32
|
||||
clearColor f32color.RGBA
|
||||
imageOps []imageOp
|
||||
// zimageOps are the rectangle clipped opaque images
|
||||
// that can use fast front-to-back rendering with z-test
|
||||
@@ -104,7 +105,7 @@ type material struct {
|
||||
material materialType
|
||||
opaque bool
|
||||
// For materialTypeColor.
|
||||
color [4]float32
|
||||
color f32color.RGBA
|
||||
// For materialTypeTexture.
|
||||
texture *texture
|
||||
uvScale f32.Point
|
||||
@@ -256,7 +257,7 @@ type blitUniforms struct {
|
||||
}
|
||||
|
||||
type colorUniforms struct {
|
||||
color [4]float32
|
||||
color f32color.RGBA
|
||||
}
|
||||
|
||||
type materialType uint8
|
||||
@@ -334,7 +335,7 @@ func (g *GPU) BeginFrame() {
|
||||
}
|
||||
g.ctx.BindFramebuffer(g.defFBO)
|
||||
g.ctx.DepthFunc(backend.DepthFuncGreater)
|
||||
g.ctx.ClearColor(g.drawOps.clearColor[0], g.drawOps.clearColor[1], g.drawOps.clearColor[2], 1.0)
|
||||
g.ctx.ClearColor(g.drawOps.clearColor.Float32())
|
||||
g.ctx.ClearDepth(0.0)
|
||||
g.ctx.Clear(backend.BufferAttachmentColor | backend.BufferAttachmentDepth)
|
||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||
@@ -650,7 +651,7 @@ func floor(v float32) int {
|
||||
|
||||
func (d *drawOps) reset(cache *resourceCache, viewport image.Point) {
|
||||
d.profile = false
|
||||
d.clearColor = [3]float32{1.0, 1.0, 1.0}
|
||||
d.clearColor = f32color.RGBA{R: 1.0, G: 1.0, B: 1.0, A: 1.0}
|
||||
d.cache = cache
|
||||
d.viewport = viewport
|
||||
d.imageOps = d.imageOps[:0]
|
||||
@@ -744,7 +745,7 @@ loop:
|
||||
d.zimageOps = d.zimageOps[:0]
|
||||
d.imageOps = d.imageOps[:0]
|
||||
state.z = 0
|
||||
copy(d.clearColor[:], mat.color[:3])
|
||||
d.clearColor = mat.color.Opaque()
|
||||
continue
|
||||
}
|
||||
state.z++
|
||||
@@ -789,8 +790,8 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
|
||||
switch d.matType {
|
||||
case materialColor:
|
||||
m.material = materialColor
|
||||
m.color = gamma(d.color.RGBA())
|
||||
m.opaque = m.color[3] == 1.0
|
||||
m.color = f32color.RGBAFromSRGB(d.color)
|
||||
m.opaque = m.color.A == 1.0
|
||||
case materialTexture:
|
||||
m.material = materialTexture
|
||||
dr := boundRectF(rect.Add(off))
|
||||
@@ -883,23 +884,7 @@ func (r *renderer) drawOps(ops []imageOp) {
|
||||
r.ctx.SetDepthTest(false)
|
||||
}
|
||||
|
||||
func gamma(r, g, b, a uint32) [4]float32 {
|
||||
color := [4]float32{float32(r) / 0xffff, float32(g) / 0xffff, float32(b) / 0xffff, float32(a) / 0xffff}
|
||||
// Assume that image.Uniform colors are in sRGB space. Linearize.
|
||||
for i := 0; i <= 2; i++ {
|
||||
c := color[i]
|
||||
// Use the formula from EXT_sRGB.
|
||||
if c <= 0.04045 {
|
||||
c = c / 12.92
|
||||
} else {
|
||||
c = float32(math.Pow(float64((c+0.055)/1.055), 2.4))
|
||||
}
|
||||
color[i] = c
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
func (b *blitter) blit(z float32, mat materialType, col [4]float32, scale, off, uvScale, uvOff f32.Point) {
|
||||
func (b *blitter) blit(z float32, mat materialType, col f32color.RGBA, scale, off, uvScale, uvOff f32.Point) {
|
||||
p := b.prog[mat]
|
||||
b.ctx.BindProgram(p.prog)
|
||||
var uniforms *blitUniforms
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/gpu/backend"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/internal/path"
|
||||
gunsafe "gioui.org/internal/unsafe"
|
||||
)
|
||||
@@ -337,11 +338,11 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pather) cover(z float32, mat materialType, col [4]float32, scale, off, uvScale, uvOff, coverScale, coverOff f32.Point) {
|
||||
func (p *pather) cover(z float32, mat materialType, col f32color.RGBA, scale, off, uvScale, uvOff, coverScale, coverOff f32.Point) {
|
||||
p.coverer.cover(z, mat, col, scale, off, uvScale, uvOff, coverScale, coverOff)
|
||||
}
|
||||
|
||||
func (c *coverer) cover(z float32, mat materialType, col [4]float32, scale, off, uvScale, uvOff, coverScale, coverOff f32.Point) {
|
||||
func (c *coverer) cover(z float32, mat materialType, col f32color.RGBA, scale, off, uvScale, uvOff, coverScale, coverOff f32.Point) {
|
||||
p := c.prog[mat]
|
||||
c.ctx.BindProgram(p.prog)
|
||||
var uniforms *coverUniforms
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package f32color
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
// RGBA is a 32 bit floating point linear space color.
|
||||
type RGBA struct {
|
||||
R, G, B, A float32
|
||||
}
|
||||
|
||||
// Array returns rgba values in a [4]float32 array.
|
||||
func (rgba RGBA) Array() [4]float32 {
|
||||
return [4]float32{rgba.R, rgba.G, rgba.B, rgba.A}
|
||||
}
|
||||
|
||||
// Float32 returns r, g, b, a values.
|
||||
func (col RGBA) Float32() (r, g, b, a float32) {
|
||||
return col.R, col.G, col.B, col.A
|
||||
}
|
||||
|
||||
// SRGBA converts from linear to sRGB color space.
|
||||
func (col RGBA) SRGB() color.RGBA {
|
||||
return color.RGBA{
|
||||
R: uint8(linearTosRGB(col.R)*255 + .5),
|
||||
G: uint8(linearTosRGB(col.G)*255 + .5),
|
||||
B: uint8(linearTosRGB(col.B)*255 + .5),
|
||||
A: uint8(col.A*255 + .5),
|
||||
}
|
||||
}
|
||||
|
||||
// Opaque returns the color without alpha component.
|
||||
func (col RGBA) Opaque() RGBA {
|
||||
col.A = 1.0
|
||||
return col
|
||||
}
|
||||
|
||||
// RGBAFromSRGB converts color.Color to RGBA.
|
||||
func RGBAFromSRGB(col color.Color) RGBA {
|
||||
r, g, b, a := col.RGBA()
|
||||
return RGBA{
|
||||
R: sRGBToLinear(float32(r) / 0xffff),
|
||||
G: sRGBToLinear(float32(g) / 0xffff),
|
||||
B: sRGBToLinear(float32(b) / 0xffff),
|
||||
A: float32(a) / 0xFFFF,
|
||||
}
|
||||
}
|
||||
|
||||
// linearTosRGB transforms color value from linear to sRGB.
|
||||
func linearTosRGB(c float32) float32 {
|
||||
// Formula from EXT_sRGB.
|
||||
switch {
|
||||
case c <= 0:
|
||||
return 0
|
||||
case 0 < c && c < 0.0031308:
|
||||
return 12.92 * c
|
||||
case 0.0031308 <= c && c < 1:
|
||||
return 1.055*float32(math.Pow(float64(c), 0.41666)) - 0.055
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// sRGBToLinear transforms color value from sRGB to linear.
|
||||
func sRGBToLinear(c float32) float32 {
|
||||
// Formula from EXT_sRGB.
|
||||
if c <= 0.04045 {
|
||||
return c / 12.92
|
||||
} else {
|
||||
return float32(math.Pow(float64((c+0.055)/1.055), 2.4))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user