From e58ef20cf9c12e6a1e5c1ab4facd1dba840d5729 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 8 Sep 2023 19:44:03 -0400 Subject: WIP: Working on images. Can't set up during draw, need to refactor --- virtual-programs/images.folk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index ee3988ea..e9807b85 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -64,7 +64,7 @@ namespace eval ::image { image[i][j * 3 + 2] = data[(i * width + j) * 3 + 2]; } } - } + } else { exit(1); } struct jpeg_compress_struct compress; struct jpeg_error_mgr error; -- cgit v1.2.3 From b9e5187c1bbf267f0ec4fc899ce926cb2167247f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 11 Sep 2023 17:41:43 -0400 Subject: WIP: Images starting to work --- virtual-programs/images.folk | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'virtual-programs') diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index e9807b85..8af24aee 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -160,6 +160,27 @@ namespace eval ::image { // TODO: Free the JPEG. // ckfree(im.data); } + $cc proc rechannel {image_t im int components} image_t { + if (im.components == components) return im; + if (components != 4 || im.components != 3) exit(2); + + image_t ret = im; + ret.components = components; + ret.bytesPerRow = ret.width * ret.components; + ret.data = folkHeapAlloc(ret.bytesPerRow * ret.height); + + for(int i = 0; i < ret.width*ret.height; i++) { + int r = im.data[i*im.components+0], + g = im.data[i*im.components+1], + b = im.data[i*im.components+2]; + + ret.data[i*ret.components+0] = r; + ret.data[i*ret.components+1] = g; + ret.data[i*ret.components+2] = b; + ret.data[i*ret.components+3] = 255; + } + return ret; + } $cc compile variable imagesCache [dict create] -- cgit v1.2.3 From f2ac1aa99d4842585355cafac600d5bddd6716f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cuervo?= Date: Tue, 12 Sep 2023 11:15:54 -0400 Subject: Always cast swapChainBuffers and pushConstants, fix MacOS lib linking --- virtual-programs/images.folk | 3 +++ 1 file changed, 3 insertions(+) (limited to 'virtual-programs') diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index 8af24aee..18876944 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -27,6 +27,9 @@ namespace eval ::image { set cc [c create] c loadlib [expr {$tcl_platform(os) eq "Darwin" ? "/opt/homebrew/lib/libjpeg.dylib" : [lindex [exec /usr/sbin/ldconfig -p | grep libjpeg] end]}] + if {$tcl_platform(os) eq "Darwin"} { + $cc cflags -I/opt/homebrew/include -L/opt/homebrew/lib + } $cc cflags -ljpeg source "pi/cUtils.tcl" defineImageType $cc -- cgit v1.2.3 From 976f92f5faae252a6245b873800d56c44c8a2b05 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 15 Sep 2023 21:32:40 -0400 Subject: WIP: Stub in GPU into Folk. Doesn't draw yet --- virtual-programs/display.folk | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 674cf1f7..7d4f47b6 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -38,8 +38,25 @@ namespace eval ::Display { } On process { - source pi/Display.tcl - Display::init + source pi/Gpu.tcl + Gpu::init + + namespace eval Display { + proc start {} {} + + proc stroke {points width color} { + + } + proc circle {x y radius thickness color} {} + proc text {x y scale text radians} {} + proc fillTriangle {args} {} + proc fillQuad {args} {} + proc fillPolygon {args} {} + proc image {x y im radians {scale 1.0}} {} + + proc end {} {} + } + puts "Display tid: [getTid]" # TODO: Clean this up. We retract these so that we don't bounce @@ -77,11 +94,13 @@ On process { } set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] + set renderTime [baretime { + Display::start + foreach command $displayCommands { {*}$command } + Display::end + }] - set renderTime [baretime [list foreach command $displayCommands { {*}$command }]] - set commitTime [baretime commitThenClearStaging] - - Commit { Claim the display time is "render $renderTime us + commit $commitTime us ($::stepTime)" } + Commit { Claim the display time is "render $renderTime us ($::stepTime)" } Step } } -- cgit v1.2.3 From f7eb36e51fab7abd5ebc74dce9419d01e4a1dfa7 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 15 Sep 2023 21:36:42 -0400 Subject: display: Add basic stroke support --- virtual-programs/display.folk | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 7d4f47b6..c9c172cc 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -40,12 +40,29 @@ namespace eval ::Display { On process { source pi/Gpu.tcl Gpu::init + Gpu::ImageManager::imageManagerInit namespace eval Display { - proc start {} {} + variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { + float l = length(to - from); + vec2 d = (to - from) / l; + vec2 q = (gl_FragCoord.xy - (from + to)*0.5); + q = mat2(d.x, -d.y, d.y, d.x) * q; + q = abs(q) - vec2(l, thickness)*0.5; + float dist = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0); + + return dist < 0.0 ? vec4(1, 0, 1, 1) : vec4(0, 0, 0, 0); + }] - proc stroke {points width color} { + proc start {} { Gpu::drawStart } + proc stroke {points width color} { + variable line + for {set i 0} {$i < [expr {[llength $points] - 1}]} {incr i} { + set from [lindex $points $i] + set to [lindex $points [expr $i+1]] + Gpu::draw $line $from $to $width + } } proc circle {x y radius thickness color} {} proc text {x y scale text radians} {} @@ -54,7 +71,7 @@ On process { proc fillPolygon {args} {} proc image {x y im radians {scale 1.0}} {} - proc end {} {} + proc end {} { Gpu::drawEnd } } puts "Display tid: [getTid]" -- cgit v1.2.3 From 6b7305d5adb099291c3a8866a899963bf3abd8c3 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 17 Sep 2023 03:59:54 -0400 Subject: display: Add basic (wrong scale) text support, PT Sans --- virtual-programs/display.folk | 113 +++++++++++++++++++++++++++++++++++++++++- virtual-programs/images.folk | 4 +- 2 files changed, 113 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index c9c172cc..31dfdb2a 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -43,6 +43,98 @@ On process { Gpu::ImageManager::imageManagerInit namespace eval Display { + variable cross2d [Gpu::fn {vec2 a vec2 b} float { + return a.x*b.y - a.y*b.x; + }] + variable invBilinear [Gpu::fn {vec2 p vec2 a vec2 b vec2 c vec2 d} {cross2d} vec2 { + vec2 res = vec2(-1.0); + + vec2 e = b-a; + vec2 f = d-a; + vec2 g = a-b+c-d; + vec2 h = p-a; + + float k2 = cross2d( g, f ); + float k1 = cross2d( e, f ) + cross2d( h, g ); + float k0 = cross2d( h, e ); + + // if edges are parallel, this is a linear equation + if( abs(k2)<0.001 ) + { + res = vec2( (h.x*k1+f.x*k0)/(e.x*k1-g.x*k0), -k0/k1 ); + } + // otherwise, it's a quadratic + else + { + float w = k1*k1 - 4.0*k0*k2; + if( w<0.0 ) return vec2(-1.0); + w = sqrt( w ); + + float ik2 = 0.5/k2; + float v = (-k1 - w)*ik2; + float u = (h.x - f.x*v)/(e.x + g.x*v); + + if( u<0.0 || u>1.0 || v<0.0 || v>1.0 ) + { + v = (-k1 + w)*ik2; + u = (h.x - f.x*v)/(e.x + g.x*v); + } + res = vec2( u, v ); + } + return res; + }] + + namespace eval font { + proc load {name} { + set csvFd [open "vendor/fonts/$name.csv" r]; set csv [read $csvFd]; close $csvFd + set glyphInfos [dict create] + foreach line [split $csv "\n"] { + set info [lassign [split $line ,] glyph] + lassign $info advance \ + planeLeft planeBottom planeRight planeTop \ + atlasLeft atlasBottom atlasRight atlasTop + dict set glyphInfos $glyph \ + [list $advance \ + [list $planeLeft $planeBottom $planeRight $planeTop] \ + [list $atlasLeft $atlasBottom $atlasRight $atlasTop]] + } + + set im [image load "[pwd]/vendor/fonts/$name.png"] + set gim [Gpu::ImageManager::copyImageToGpu [image rechannel $im 4]] + + return [list $glyphInfos $im $gim] + } + proc glyphInfo {font char} { dict get [lindex $font 0] $char } + proc atlasImage {font} { lindex $font 1 } + proc gpuAtlasImage {font} { lindex $font 2 } + + namespace export * + namespace ensemble create + } + variable font [font load "PTSans-Regular"] + variable glyphMsd [Gpu::fn {sampler2D atlas vec4 atlasGlyphBounds vec2 glyphUv} vec4 { + vec2 atlasUv = mix(atlasGlyphBounds.xw, atlasGlyphBounds.zy, glyphUv); + return texture(atlas, vec2(atlasUv.x, 1.0-atlasUv.y)); + }] + variable median [Gpu::fn {float r float g float b} float { + return max(min(r, g), min(max(r, g), b)); + }] + variable glyph [Gpu::pipeline {sampler2D atlas vec2 atlasSize + vec4 atlasGlyphBounds + vec2 a vec2 b vec2 c vec2 d} \ + {invBilinear glyphMsd median} { + vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); + if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { + return vec4(0, 0, 0, 0); + } + + vec3 msd = glyphMsd(samplers[atlas], atlasGlyphBounds/atlasSize.xyxy, glyphUv).rgb; + float sd = median(msd.r, msd.g, msd.b); + float screenPxDistance = 4.5*(sd - 0.5); + float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); + return mix(vec4(0, 0, 0, 1), vec4(1, 1, 1, 1), opacity); + }] + variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { float l = length(to - from); vec2 d = (to - from) / l; @@ -65,7 +157,26 @@ On process { } } proc circle {x y radius thickness color} {} - proc text {x y scale text radians} {} + proc text {x0 y0 scale text radians} { + variable font + variable glyph + set fontAtlas [font gpuAtlasImage $font] + set fontAtlasSize [list [::image width [font atlasImage $font]] \ + [::image height [font atlasImage $font]]] + set x $x0; set y $y0 + for {set i 0} {$i < [string length $text]} {incr i} { + if {[string index $text $i] eq "\n"} { + set y [+ $y 100]; set x $x0; continue + } + try { + set glyphInfo [font glyphInfo $font [scan [string index $text $i] %c]] + Gpu::draw $glyph $fontAtlas $fontAtlasSize \ + [lindex $glyphInfo 2] \ + [list $x $y] [list [+ $x 100] $y] [list [+ $x 100] [+ $y 100]] [list $x [+ $y 100]] + set x [+ $x 100] + } on error e { puts stderr $e } + } + } proc fillTriangle {args} {} proc fillQuad {args} {} proc fillPolygon {args} {} diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index 6bfd9bb3..1d491eec 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -5,8 +5,6 @@ # Wish $this displays camera slice $slice # } -if {$::isLaptop} { return } - # Generic image class for sub-image manipulations namespace eval ::image { proc width {im} { dict get $im width } @@ -32,7 +30,7 @@ namespace eval ::image { $cc cflags -I/opt/homebrew/include -L/opt/homebrew/lib } - $cc cflags -ljpeg + $cc cflags -ljpeg -lpng source "pi/cUtils.tcl" defineImageType $cc $cc include -- cgit v1.2.3 From 4f6331641e3971370cac98c8fc8819d2270debe5 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 17 Sep 2023 18:22:13 -0400 Subject: display: Start using planeBounds to position characters properly Make display work on laptop --- virtual-programs/display.folk | 66 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 31dfdb2a..1991650a 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -1,10 +1,12 @@ -if {$::isLaptop} return - namespace eval ::Display { variable WIDTH variable HEIGHT variable LAYER 0 - regexp {mode "(\d+)x(\d+)"} [exec fbset] -> WIDTH HEIGHT + if {$::isLaptop} { + set WIDTH 640; set HEIGHT 480 + } else { + regexp {mode "(\d+)x(\d+)"} [exec fbset] -> WIDTH HEIGHT + } proc drawOnTop {func args} { set ::Display::LAYER 1 @@ -12,28 +14,14 @@ namespace eval ::Display { set ::Display::LAYER 0 } - proc stroke {points width color} { - uplevel [list Wish display runs [list Display::stroke $points $width $color] on layer $::Display::LAYER] - } - - proc circle {x y radius thickness color} { - uplevel [list Wish display runs [list Display::circle $x $y $radius $thickness $color] on layer $::Display::LAYER] - } - - proc text args { - uplevel [list Wish display runs [list Display::text {*}$args] on layer $::Display::LAYER] - } - - proc fillTriangle args { - uplevel [list Wish display runs [list Display::fillTriangle {*}$args] on layer $::Display::LAYER] - } - - proc fillQuad args { - uplevel [list Wish display runs [list Display::fillQuad {*}$args] on layer $::Display::LAYER] - } - - proc fillPolygon args { - uplevel [list Wish display runs [list Display::fillPolygon {*}$args] on layer $::Display::LAYER] + # Create proxy versions of drawing primitives for the main Folk + # process (that will forward those draw commands to the display + # subprocess). + foreach func {stroke circle text fillTriangle fillQuad fillPolygon} { + proc $func args { + set func [lindex [info level 0] 0] + uplevel [list Wish display runs [list $func {*}$args] on layer $::Display::LAYER] + } } } @@ -163,17 +151,26 @@ On process { set fontAtlas [font gpuAtlasImage $font] set fontAtlasSize [list [::image width [font atlasImage $font]] \ [::image height [font atlasImage $font]]] + set em [* $scale 40.0] set x $x0; set y $y0 for {set i 0} {$i < [string length $text]} {incr i} { - if {[string index $text $i] eq "\n"} { - set y [+ $y 100]; set x $x0; continue + set char [string index $text $i] + if {$char eq "\n"} { + set y [+ $y $em]; set x $x0; continue } try { - set glyphInfo [font glyphInfo $font [scan [string index $text $i] %c]] - Gpu::draw $glyph $fontAtlas $fontAtlasSize \ - [lindex $glyphInfo 2] \ - [list $x $y] [list [+ $x 100] $y] [list [+ $x 100] [+ $y 100]] [list $x [+ $y 100]] - set x [+ $x 100] + set glyphInfo [font glyphInfo $font [scan $char %c]] + lassign $glyphInfo advance planeBounds atlasBounds + if {$char ne " "} { + lassign [lmap v $planeBounds {* $v $em}] left bottom right top + Gpu::draw $glyph $fontAtlas $fontAtlasSize \ + $atlasBounds \ + [list [+ $x $left] [- $y $top]] \ + [list [+ $x $right] [- $y $top]] \ + [list [+ $x $right] [+ $y $bottom]] \ + [list [+ $x $left] [+ $y $bottom]] + } + set x [+ $x [* $advance $em]] } on error e { puts stderr $e } } } @@ -182,10 +179,10 @@ On process { proc fillPolygon {args} {} proc image {x y im radians {scale 1.0}} {} - proc end {} { Gpu::drawEnd } + proc end {} { Gpu::drawEnd; Gpu::poll } } - puts "Display tid: [getTid]" + puts "Display pid: [pid]" # TODO: Clean this up. We retract these so that we don't bounce # statements back to the main Folk process that it sends us. @@ -224,6 +221,7 @@ On process { set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] set renderTime [baretime { Display::start + Display::text 100 100 1.0 "Hello, world!" 0 foreach command $displayCommands { {*}$command } Display::end }] -- cgit v1.2.3 From 317eac5efea896aa1f214f72ba81ce43f84bb58f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 13:28:43 -0400 Subject: display: Fix text orientation, remove dupe code from Gpu --- virtual-programs/display.folk | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 1991650a..08d617c3 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -115,7 +115,6 @@ On process { if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { return vec4(0, 0, 0, 0); } - vec3 msd = glyphMsd(samplers[atlas], atlasGlyphBounds/atlasSize.xyxy, glyphUv).rgb; float sd = median(msd.r, msd.g, msd.b); float screenPxDistance = 4.5*(sd - 0.5); @@ -163,12 +162,14 @@ On process { lassign $glyphInfo advance planeBounds atlasBounds if {$char ne " "} { lassign [lmap v $planeBounds {* $v $em}] left bottom right top + set quad [list \ + [list [+ $x $left] [- $y $top]] \ + [list [+ $x $right] [- $y $top]] \ + [list [+ $x $right] [- $y $bottom]] \ + [list [+ $x $left] [- $y $bottom]]] + stroke $quad 10 red Gpu::draw $glyph $fontAtlas $fontAtlasSize \ - $atlasBounds \ - [list [+ $x $left] [- $y $top]] \ - [list [+ $x $right] [- $y $top]] \ - [list [+ $x $right] [+ $y $bottom]] \ - [list [+ $x $left] [+ $y $bottom]] + $atlasBounds {*}$quad } set x [+ $x [* $advance $em]] } on error e { puts stderr $e } @@ -221,7 +222,8 @@ On process { set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] set renderTime [baretime { Display::start - Display::text 100 100 1.0 "Hello, world!" 0 + Display::text 100 100 1.0 "Hello, pworld!" 0 + Display::stroke {{100 100} {400 100}} 4 red foreach command $displayCommands { {*}$command } Display::end }] -- cgit v1.2.3 From 80f3fc6efa21ddb8d8fc92bfaf6d6b9be1be66e6 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 13:31:34 -0400 Subject: display: debug cleanup --- virtual-programs/display.folk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 08d617c3..1a6246fe 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -167,7 +167,7 @@ On process { [list [+ $x $right] [- $y $top]] \ [list [+ $x $right] [- $y $bottom]] \ [list [+ $x $left] [- $y $bottom]]] - stroke $quad 10 red + # stroke $quad 10 red Gpu::draw $glyph $fontAtlas $fontAtlasSize \ $atlasBounds {*}$quad } @@ -223,7 +223,7 @@ On process { set renderTime [baretime { Display::start Display::text 100 100 1.0 "Hello, pworld!" 0 - Display::stroke {{100 100} {400 100}} 4 red + # Display::stroke {{100 100} {400 100}} 4 red foreach command $displayCommands { {*}$command } Display::end }] -- cgit v1.2.3 From 262234a1bbe30b48bfae3418162c104865a0a56a Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 15:53:56 -0400 Subject: Gpu: Pass quad into vertex shader as arg (Preparing for bounded drawing to speed things up.) Also derecommend not using `return`. --- virtual-programs/display.folk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 1a6246fe..b9dcfe84 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -168,7 +168,7 @@ On process { [list [+ $x $right] [- $y $bottom]] \ [list [+ $x $left] [- $y $bottom]]] # stroke $quad 10 red - Gpu::draw $glyph $fontAtlas $fontAtlasSize \ + Gpu::draw $glyph $quad $fontAtlas $fontAtlasSize \ $atlasBounds {*}$quad } set x [+ $x [* $advance $em]] -- cgit v1.2.3 From 8d96d1883fd2a476f2fa6aa0b7539166547aeaea Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 16:40:17 -0400 Subject: display: Add fullscreen vertex shaders to start --- virtual-programs/display.folk | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index b9dcfe84..a1aa9583 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -109,8 +109,10 @@ On process { }] variable glyph [Gpu::pipeline {sampler2D atlas vec2 atlasSize vec4 atlasGlyphBounds - vec2 a vec2 b vec2 c vec2 d} \ - {invBilinear glyphMsd median} { + vec2 a vec2 b vec2 c vec2 d} { + vec2 vertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1)); + return vec4(vertices[gl_VertexIndex], 0.0, 1.0); + } {invBilinear glyphMsd median} { vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { return vec4(0, 0, 0, 0); @@ -123,6 +125,9 @@ On process { }] variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { + vec2 vertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1)); + return vec4(vertices[gl_VertexIndex], 0.0, 1.0); + } { float l = length(to - from); vec2 d = (to - from) / l; vec2 q = (gl_FragCoord.xy - (from + to)*0.5); @@ -168,7 +173,7 @@ On process { [list [+ $x $right] [- $y $bottom]] \ [list [+ $x $left] [- $y $bottom]]] # stroke $quad 10 red - Gpu::draw $glyph $quad $fontAtlas $fontAtlasSize \ + Gpu::draw $glyph $fontAtlas $fontAtlasSize \ $atlasBounds {*}$quad } set x [+ $x [* $advance $em]] -- cgit v1.2.3 From 2cf8c2e68424d3deec758a417a490b4d13e6327f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 18:49:36 -0400 Subject: display: WIP: Move to clipped drawing using vertex shaders Letters/lines are clipped a bit wrong rn. --- virtual-programs/display.folk | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index a1aa9583..201c348e 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -110,8 +110,9 @@ On process { variable glyph [Gpu::pipeline {sampler2D atlas vec2 atlasSize vec4 atlasGlyphBounds vec2 a vec2 b vec2 c vec2 d} { - vec2 vertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1)); - return vec4(vertices[gl_VertexIndex], 0.0, 1.0); + vec2 vertices[4] = vec2[4](a, b, c, d); + vec2 v = (2.0*vertices[gl_VertexIndex] - _resolution)/_resolution; + return vec4(v, 0.0, 1.0); } {invBilinear glyphMsd median} { vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { @@ -125,8 +126,9 @@ On process { }] variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { - vec2 vertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1)); - return vec4(vertices[gl_VertexIndex], 0.0, 1.0); + vec2 vertices[4] = vec2[4](from - thickness, vec2(from.x - thickness, to.y + thickness), vec2(to.x + thickness, from.y - thickness), to + thickness); + vec2 v = (2.0*vertices[gl_VertexIndex] - _resolution)/_resolution; + return vec4(v, 0.0, 1.0); } { float l = length(to - from); vec2 d = (to - from) / l; -- cgit v1.2.3 From 1a234233662773204f85dfaad8cc99f13b16ad14 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 23:23:44 -0400 Subject: display: Text works on table! Use abdc draw order (because that's how to draw a quad w/ triangle strip topology) --- virtual-programs/display.folk | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 201c348e..6a703bce 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -110,7 +110,7 @@ On process { variable glyph [Gpu::pipeline {sampler2D atlas vec2 atlasSize vec4 atlasGlyphBounds vec2 a vec2 b vec2 c vec2 d} { - vec2 vertices[4] = vec2[4](a, b, c, d); + vec2 vertices[4] = vec2[4](a, b, d, c); vec2 v = (2.0*vertices[gl_VertexIndex] - _resolution)/_resolution; return vec4(v, 0.0, 1.0); } {invBilinear glyphMsd median} { @@ -122,7 +122,7 @@ On process { float sd = median(msd.r, msd.g, msd.b); float screenPxDistance = 4.5*(sd - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); - return mix(vec4(0, 0, 0, 1), vec4(1, 1, 1, 1), opacity); + return mix(vec4(0, 0, 0, 0), vec4(1, 1, 1, 1), opacity); }] variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { @@ -229,8 +229,6 @@ On process { set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] set renderTime [baretime { Display::start - Display::text 100 100 1.0 "Hello, pworld!" 0 - # Display::stroke {{100 100} {400 100}} 4 red foreach command $displayCommands { {*}$command } Display::end }] -- cgit v1.2.3 From 6fe7e9078e3f26a189781668449177a15c00c1cf Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 18 Sep 2023 23:52:14 -0400 Subject: Gpu: Vertex shader cleanup (do scaling to -1, 1 internally) --- virtual-programs/display.folk | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 6a703bce..ea8218c5 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -111,8 +111,7 @@ On process { vec4 atlasGlyphBounds vec2 a vec2 b vec2 c vec2 d} { vec2 vertices[4] = vec2[4](a, b, d, c); - vec2 v = (2.0*vertices[gl_VertexIndex] - _resolution)/_resolution; - return vec4(v, 0.0, 1.0); + return vertices[gl_VertexIndex]; } {invBilinear glyphMsd median} { vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { @@ -126,9 +125,13 @@ On process { }] variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { - vec2 vertices[4] = vec2[4](from - thickness, vec2(from.x - thickness, to.y + thickness), vec2(to.x + thickness, from.y - thickness), to + thickness); - vec2 v = (2.0*vertices[gl_VertexIndex] - _resolution)/_resolution; - return vec4(v, 0.0, 1.0); + vec2 vertices[4] = vec2[4]( + min(from, to) - thickness, + vec2(max(from.x, to.x) + thickness, min(from.y, to.y) - thickness), + vec2(min(from.y, to.y) - thickness, max(from.y, to.y) + thickness), + max(from, to) + thickness + ); + return vertices[gl_VertexIndex]; } { float l = length(to - from); vec2 d = (to - from) / l; -- cgit v1.2.3 From 8f65f6d3d91ed341fe0af016c6751335cb554333 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 19 Sep 2023 00:47:34 -0400 Subject: display: Text rotate works. Delete old code for lineclip/rotate --- virtual-programs/display.folk | 68 +++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index ea8218c5..f7c33ce3 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -92,7 +92,8 @@ On process { return [list $glyphInfos $im $gim] } - proc glyphInfo {font char} { dict get [lindex $font 0] $char } + proc hasGlyphInfo {font charCode} { dict exists [lindex $font 0] $charCode } + proc glyphInfo {font charCode} { dict get [lindex $font 0] $charCode } proc atlasImage {font} { lindex $font 1 } proc gpuAtlasImage {font} { lindex $font 2 } @@ -154,37 +155,66 @@ On process { } } proc circle {x y radius thickness color} {} + + proc textMetrics {text scale} { + set em [* $scale 30.0] + set x $x0; set y $y0 + for {set i 0} {$i < [string length $text]} {incr i} { + set char [string index $text $i] + if {$char eq "\n"} { + set y [+ $y $em]; set x $x0; continue + } + set charCode [scan $char %c] + if {[font hasGlyphInfo $font $charCode]} { + set glyphInfo [font glyphInfo $font $charCode] + } else { + set glyphInfo [font glyphInfo $font [scan ? %c]] + } + lassign $glyphInfo advance planeBounds atlasBounds + set x [+ $x [* $advance $em]] + } + return [list $x $y] + } proc text {x0 y0 scale text radians} { variable font variable glyph set fontAtlas [font gpuAtlasImage $font] set fontAtlasSize [list [::image width [font atlasImage $font]] \ [::image height [font atlasImage $font]]] - set em [* $scale 40.0] + set em [* $scale 30.0] set x $x0; set y $y0 + set lineNum 0 for {set i 0} {$i < [string length $text]} {incr i} { set char [string index $text $i] if {$char eq "\n"} { - set y [+ $y $em]; set x $x0; continue + incr lineNum + lassign [vec2 add [list $x0 $y0] \ + [vec2 rotate [list 0 [* $lineNum $em]] $radians]] x y + continue } - try { - set glyphInfo [font glyphInfo $font [scan $char %c]] - lassign $glyphInfo advance planeBounds atlasBounds - if {$char ne " "} { - lassign [lmap v $planeBounds {* $v $em}] left bottom right top - set quad [list \ - [list [+ $x $left] [- $y $top]] \ - [list [+ $x $right] [- $y $top]] \ - [list [+ $x $right] [- $y $bottom]] \ - [list [+ $x $left] [- $y $bottom]]] - # stroke $quad 10 red - Gpu::draw $glyph $fontAtlas $fontAtlasSize \ - $atlasBounds {*}$quad - } - set x [+ $x [* $advance $em]] - } on error e { puts stderr $e } + set charCode [scan $char %c] + if {[font hasGlyphInfo $font $charCode]} { + set glyphInfo [font glyphInfo $font $charCode] + } else { + set glyphInfo [font glyphInfo $font [scan ? %c]] + } + lassign $glyphInfo advance planeBounds atlasBounds + if {$char ne " "} { + lassign [lmap v $planeBounds {* $v $em}] left bottom right top + set quad [list \ + [vec2 add [list $x $y] [vec2 rotate [list $left [- $top]] $radians]] \ + [vec2 add [list $x $y] [vec2 rotate [list $right [- $top]] $radians]] \ + [vec2 add [list $x $y] [vec2 rotate [list $right [- $bottom]] $radians]] \ + [vec2 add [list $x $y] [vec2 rotate [list $left [- $bottom]] $radians]]] + # stroke $quad 10 red + Gpu::draw $glyph $fontAtlas $fontAtlasSize \ + $atlasBounds {*}$quad + } + lassign [vec2 add [list $x $y] \ + [vec2 rotate [list [* $advance $em] 0] $radians]] x y } } + proc fillTriangle {args} {} proc fillQuad {args} {} proc fillPolygon {args} {} -- cgit v1.2.3 From 370f2f88246233f721db7eb28416ec69e27f4ad2 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Wed, 20 Sep 2023 09:07:49 -0400 Subject: display: Fix textMetrics --- virtual-programs/display.folk | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index f7c33ce3..b0fe3ec1 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -26,6 +26,8 @@ namespace eval ::Display { } On process { + puts "Display pid: [pid]" + source pi/Gpu.tcl Gpu::init Gpu::ImageManager::imageManagerInit @@ -157,12 +159,13 @@ On process { proc circle {x y radius thickness color} {} proc textMetrics {text scale} { + variable font set em [* $scale 30.0] - set x $x0; set y $y0 + set x 0; set y 0 for {set i 0} {$i < [string length $text]} {incr i} { set char [string index $text $i] if {$char eq "\n"} { - set y [+ $y $em]; set x $x0; continue + set y [+ $y $em]; set x 0; continue } set charCode [scan $char %c] if {[font hasGlyphInfo $font $charCode]} { @@ -223,8 +226,6 @@ On process { proc end {} { Gpu::drawEnd; Gpu::poll } } - puts "Display pid: [pid]" - # TODO: Clean this up. We retract these so that we don't bounce # statements back to the main Folk process that it sends us. Retract /anyone/ wishes $::thisProcess shares all wishes -- cgit v1.2.3 From dca67964e03709237a888f97ff3481f5e1cd579c Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Wed, 20 Sep 2023 22:52:04 -0400 Subject: display: Fix line vertices --- virtual-programs/display.folk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index b0fe3ec1..dc0fb2ea 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -131,7 +131,7 @@ On process { vec2 vertices[4] = vec2[4]( min(from, to) - thickness, vec2(max(from.x, to.x) + thickness, min(from.y, to.y) - thickness), - vec2(min(from.y, to.y) - thickness, max(from.y, to.y) + thickness), + vec2(min(from.x, to.x) - thickness, max(from.y, to.y) + thickness), max(from, to) + thickness ); return vertices[gl_VertexIndex]; -- cgit v1.2.3 From cd63ce61470bf5c0a2a54f576dae3c3b68b4fb45 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 23 Sep 2023 05:41:38 -0400 Subject: Gpu/display: Unify fns and args; start on frag args Preparing to do more with vertex shaders (compute quads and pass to frag) to reduce CPU work and speed up Pi 4. --- virtual-programs/display.folk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index dc0fb2ea..211bfa0a 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -115,7 +115,7 @@ On process { vec2 a vec2 b vec2 c vec2 d} { vec2 vertices[4] = vec2[4](a, b, d, c); return vertices[gl_VertexIndex]; - } {invBilinear glyphMsd median} { + } {fn invBilinear fn glyphMsd fn median} { vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { return vec4(0, 0, 0, 0); -- cgit v1.2.3 From 11394db087397078f4ba2b87a1e9c2a9e35805e7 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 23 Sep 2023 06:22:05 -0400 Subject: Gpu/display: Move a lot of glyph logic into shader Make vertex fns work. Effect on Pi 4 performance is good (15fps) but not great. --- virtual-programs/display.folk | 44 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 211bfa0a..d508748a 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -33,6 +33,12 @@ On process { Gpu::ImageManager::imageManagerInit namespace eval Display { + variable rotate [Gpu::fn {vec2 v float a} vec2 { + float s = sin(a); + float c = cos(a); + mat2 m = mat2(c, s, -s, c); + return m * v; + }] variable cross2d [Gpu::fn {vec2 a vec2 b} float { return a.x*b.y - a.y*b.x; }] @@ -112,10 +118,30 @@ On process { }] variable glyph [Gpu::pipeline {sampler2D atlas vec2 atlasSize vec4 atlasGlyphBounds - vec2 a vec2 b vec2 c vec2 d} { + vec4 planeGlyphBounds + vec2 pos float radians float em + fn rotate} { + float left = planeGlyphBounds[0] * em; + float bottom = planeGlyphBounds[1] * em; + float right = planeGlyphBounds[2] * em; + float top = planeGlyphBounds[3] * em; + vec2 a = pos + rotate(vec2(left, -top), radians); + vec2 b = pos + rotate(vec2(right, -top), radians); + vec2 c = pos + rotate(vec2(right, -bottom), radians); + vec2 d = pos + rotate(vec2(left, -bottom), radians); + vec2 vertices[4] = vec2[4](a, b, d, c); return vertices[gl_VertexIndex]; - } {fn invBilinear fn glyphMsd fn median} { + } {fn rotate fn invBilinear fn glyphMsd fn median} { + float left = planeGlyphBounds[0] * em; + float bottom = planeGlyphBounds[1] * em; + float right = planeGlyphBounds[2] * em; + float top = planeGlyphBounds[3] * em; + vec2 a = pos + rotate(vec2(left, -top), radians); + vec2 b = pos + rotate(vec2(right, -top), radians); + vec2 c = pos + rotate(vec2(right, -bottom), radians); + vec2 d = pos + rotate(vec2(left, -bottom), radians); + vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { return vec4(0, 0, 0, 0); @@ -203,15 +229,15 @@ On process { } lassign $glyphInfo advance planeBounds atlasBounds if {$char ne " "} { - lassign [lmap v $planeBounds {* $v $em}] left bottom right top - set quad [list \ - [vec2 add [list $x $y] [vec2 rotate [list $left [- $top]] $radians]] \ - [vec2 add [list $x $y] [vec2 rotate [list $right [- $top]] $radians]] \ - [vec2 add [list $x $y] [vec2 rotate [list $right [- $bottom]] $radians]] \ - [vec2 add [list $x $y] [vec2 rotate [list $left [- $bottom]] $radians]]] + # lassign [lmap v $planeBounds {* $v $em}] left bottom right top + # set quad [list \ + # [vec2 add [list $x $y] [vec2 rotate [list $left [- $top]] $radians]] \ + # [vec2 add [list $x $y] [vec2 rotate [list $right [- $top]] $radians]] \ + # [vec2 add [list $x $y] [vec2 rotate [list $right [- $bottom]] $radians]] \ + # [vec2 add [list $x $y] [vec2 rotate [list $left [- $bottom]] $radians]]] # stroke $quad 10 red Gpu::draw $glyph $fontAtlas $fontAtlasSize \ - $atlasBounds {*}$quad + $atlasBounds $planeBounds [list $x $y] $radians $em } lassign [vec2 add [list $x $y] \ [vec2 rotate [list [* $advance $em] 0] $radians]] x y -- cgit v1.2.3 From ea152053ab9865991ef7b08cfbe67dc093210505 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 23 Sep 2023 06:30:22 -0400 Subject: display: Fix glyph angles --- virtual-programs/display.folk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index d508748a..67f12767 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -137,10 +137,10 @@ On process { float bottom = planeGlyphBounds[1] * em; float right = planeGlyphBounds[2] * em; float top = planeGlyphBounds[3] * em; - vec2 a = pos + rotate(vec2(left, -top), radians); - vec2 b = pos + rotate(vec2(right, -top), radians); - vec2 c = pos + rotate(vec2(right, -bottom), radians); - vec2 d = pos + rotate(vec2(left, -bottom), radians); + vec2 a = pos + rotate(vec2(left, -top), -radians); + vec2 b = pos + rotate(vec2(right, -top), -radians); + vec2 c = pos + rotate(vec2(right, -bottom), -radians); + vec2 d = pos + rotate(vec2(left, -bottom), -radians); vec2 glyphUv = invBilinear(gl_FragCoord.xy, a, b, c, d); if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { -- cgit v1.2.3 From 7e1e6278bf637c9e1295cb1297d99312f359acbd Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 23 Sep 2023 06:40:42 -0400 Subject: display: Fix more glyph angles --- virtual-programs/display.folk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 67f12767..3fc02d85 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -125,10 +125,10 @@ On process { float bottom = planeGlyphBounds[1] * em; float right = planeGlyphBounds[2] * em; float top = planeGlyphBounds[3] * em; - vec2 a = pos + rotate(vec2(left, -top), radians); - vec2 b = pos + rotate(vec2(right, -top), radians); - vec2 c = pos + rotate(vec2(right, -bottom), radians); - vec2 d = pos + rotate(vec2(left, -bottom), radians); + vec2 a = pos + rotate(vec2(left, -top), -radians); + vec2 b = pos + rotate(vec2(right, -top), -radians); + vec2 c = pos + rotate(vec2(right, -bottom), -radians); + vec2 d = pos + rotate(vec2(left, -bottom), -radians); vec2 vertices[4] = vec2[4](a, b, d, c); return vertices[gl_VertexIndex]; -- cgit v1.2.3 From ef73ec928b677f6c9ff3024cc09a926b48438964 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 19:07:27 -0400 Subject: display: Reintroduce stroke color support --- virtual-programs/display.folk | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 3fc02d85..cc31575d 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -33,6 +33,8 @@ On process { Gpu::ImageManager::imageManagerInit namespace eval Display { + namespace eval Colors { source "pi/Colors.tcl" } + variable rotate [Gpu::fn {vec2 v float a} vec2 { float s = sin(a); float c = cos(a); @@ -153,7 +155,7 @@ On process { return mix(vec4(0, 0, 0, 0), vec4(1, 1, 1, 1), opacity); }] - variable line [Gpu::pipeline {vec2 from vec2 to float thickness} { + variable line [Gpu::pipeline {vec2 from vec2 to float thickness vec4 color} { vec2 vertices[4] = vec2[4]( min(from, to) - thickness, vec2(max(from.x, to.x) + thickness, min(from.y, to.y) - thickness), @@ -169,17 +171,22 @@ On process { q = abs(q) - vec2(l, thickness)*0.5; float dist = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0); - return dist < 0.0 ? vec4(1, 0, 1, 1) : vec4(0, 0, 0, 0); + return dist < 0.0 ? color : vec4(0, 0, 0, 0); }] proc start {} { Gpu::drawStart } + proc getColor {color} { + if {[info exists Colors::$color]} { return [set Colors::$color] } \ + else { return $Colors::white } + } + proc stroke {points width color} { variable line for {set i 0} {$i < [expr {[llength $points] - 1}]} {incr i} { set from [lindex $points $i] set to [lindex $points [expr $i+1]] - Gpu::draw $line $from $to $width + Gpu::draw $line $from $to $width [getColor $color] } } proc circle {x y radius thickness color} {} -- cgit v1.2.3 From 731327e25249e75a442bef07696ec1f3a105c726 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 19:43:42 -0400 Subject: display: Add circle support. --- virtual-programs/display.folk | 46 ++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index cc31575d..fd30779b 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -155,6 +155,13 @@ On process { return mix(vec4(0, 0, 0, 0), vec4(1, 1, 1, 1), opacity); }] + proc start {} { Gpu::drawStart } + + proc getColor {color} { + if {[info exists Colors::$color]} { return [set Colors::$color] } \ + else { return $Colors::white } + } + variable line [Gpu::pipeline {vec2 from vec2 to float thickness vec4 color} { vec2 vertices[4] = vec2[4]( min(from, to) - thickness, @@ -173,14 +180,6 @@ On process { return dist < 0.0 ? color : vec4(0, 0, 0, 0); }] - - proc start {} { Gpu::drawStart } - - proc getColor {color} { - if {[info exists Colors::$color]} { return [set Colors::$color] } \ - else { return $Colors::white } - } - proc stroke {points width color} { variable line for {set i 0} {$i < [expr {[llength $points] - 1}]} {incr i} { @@ -189,7 +188,29 @@ On process { Gpu::draw $line $from $to $width [getColor $color] } } - proc circle {x y radius thickness color} {} + + # TODO: Fix bool support. + variable circle [Gpu::pipeline {vec2 center float radius float thickness vec4 color int filled} { + float r = radius + thickness; + vec2 vertices[4] = vec2[4]( + center - r, + vec2(center.x + r, center.y - r), + vec2(center.x - r, center.y + r), + center + r + ); + return vertices[gl_VertexIndex]; + } { + float dist = length(gl_FragCoord.xy - center) - radius; + if (filled == 1) { + return (dist < thickness) ? color : vec4(0, 0, 0, 0); + } else { + return (dist < thickness && dist > 0.0) ? color : vec4(0, 0, 0, 0); + } + }] + proc circle {x y radius thickness color {filled false}} { + variable circle + Gpu::draw $circle [list $x $y] $radius $thickness [getColor $color] [ne $filled "false"] + } proc textMetrics {text scale} { variable font @@ -236,13 +257,6 @@ On process { } lassign $glyphInfo advance planeBounds atlasBounds if {$char ne " "} { - # lassign [lmap v $planeBounds {* $v $em}] left bottom right top - # set quad [list \ - # [vec2 add [list $x $y] [vec2 rotate [list $left [- $top]] $radians]] \ - # [vec2 add [list $x $y] [vec2 rotate [list $right [- $top]] $radians]] \ - # [vec2 add [list $x $y] [vec2 rotate [list $right [- $bottom]] $radians]] \ - # [vec2 add [list $x $y] [vec2 rotate [list $left [- $bottom]] $radians]]] - # stroke $quad 10 red Gpu::draw $glyph $fontAtlas $fontAtlasSize \ $atlasBounds $planeBounds [list $x $y] $radians $em } -- cgit v1.2.3 From c1bac3003b74702eef36ecb123bb5cdd59d44657 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 20:13:48 -0400 Subject: display: Implement fillTriangle; fillPolygon also seems to work. --- virtual-programs/display.folk | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index fd30779b..fe0d883f 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -265,9 +265,42 @@ On process { } } - proc fillTriangle {args} {} - proc fillQuad {args} {} - proc fillPolygon {args} {} + variable fillTriangle [Gpu::pipeline {vec2 p0 vec2 p1 vec2 p2 vec4 color} { + vec2 vertices[4] = vec2[4](p0, p1, p2, p2); + return vertices[gl_VertexIndex]; + } { + return color; + }] + proc fillTriangle {p0 p1 p2 color} { + variable fillTriangle + Gpu::draw $fillTriangle $p0 $p1 $p2 [getColor $color] + } + + proc fillQuad {p0 p1 p2 p3 color} { + fillTriangle $p1 $p2 $p3 $color + fillTriangle $p0 $p1 $p3 $color + } + + proc fillPolygon {points color} { + set num_points [llength $points] + if {$num_points < 3} { + error "At least 3 points are required to form a polygon." + } elseif {$num_points == 3} { + eval fillTriangle $points $color + } elseif {$num_points == 4} { + eval fillQuad $points $color + } else { + # Get the first point in the list as the "base" point of the triangles + set p0 [lindex $points 0] + + for {set i 1} {$i < $num_points - 1} {incr i} { + set p1 [lindex $points $i] + set p2 [lindex $points [expr {$i+1}]] + fillTriangle $p0 $p1 $p2 $color + } + } + } + proc image {x y im radians {scale 1.0}} {} proc end {} { Gpu::drawEnd; Gpu::poll } -- cgit v1.2.3 From 482ae8f37976e4035845d2f596a0ec0af04827d7 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 20:15:57 -0400 Subject: display: This seems to fix fillQuad --- virtual-programs/display.folk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index fe0d883f..30b9e408 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -266,7 +266,7 @@ On process { } variable fillTriangle [Gpu::pipeline {vec2 p0 vec2 p1 vec2 p2 vec4 color} { - vec2 vertices[4] = vec2[4](p0, p1, p2, p2); + vec2 vertices[4] = vec2[4](p0, p1, p2, p0); return vertices[gl_VertexIndex]; } { return color; -- cgit v1.2.3 From 74fa2828cb7bee6a29931dcedcb9a06b2688d243 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 20:48:49 -0400 Subject: display: Basic image support (no rotation/scale yet + cache is hack) Fix various stride bugs with iamge copying/rechanneling. --- virtual-programs/display.folk | 34 +++++++++++++++++++++++++++++++++- virtual-programs/images.folk | 26 ++++++++++++++++---------- 2 files changed, 49 insertions(+), 11 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 30b9e408..ef24c9d8 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -301,7 +301,39 @@ On process { } } - proc image {x y im radians {scale 1.0}} {} + variable image [Gpu::pipeline {sampler2D image vec2 imageSize + vec2 pos float radians float scale} { + vec2 a = pos - imageSize/2; + vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2; + vec2 c = pos + imageSize/2; + vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2; + vec2 vertices[4] = vec2[4](a, b, d, c); + return vertices[gl_VertexIndex]; + } {fn invBilinear} { + vec2 a = pos - imageSize/2; + vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2; + vec2 c = pos + imageSize/2; + vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2; + vec2 p = gl_FragCoord.xy; + vec2 uv = invBilinear(p, a, b, c, d); + if( max( abs(uv.x-0.5), abs(uv.y-0.5))<0.5 ) { + return texture(samplers[image], uv); + } + return vec4(0.0, 0.0, 0.0, 0.0); + }] + variable imCache [dict create] + proc image {x y im radians {scale 1.0}} { + variable image + variable imCache + if {![dict exists $imCache $im]} { + set gim [Gpu::ImageManager::copyImageToGpu [::image rechannel $im 4]] + dict set imCache $im $gim + } + set gim [dict get $imCache $im] + puts $gim + Gpu::draw $image $gim [list [::image width $im] [::image height $im]] \ + [list $x $y] $radians $scale + } proc end {} { Gpu::drawEnd; Gpu::poll } } diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index 1d491eec..120b340a 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -262,6 +262,8 @@ namespace eval ::image { // TODO: Free the PNG. } + # Allocates(!) a copy of `im` with `components` channels. Up to + # the caller to free it. $cc proc rechannel {image_t im int components} image_t { if (im.components == components) return im; if (components != 4 || im.components != 3) exit(2); @@ -270,16 +272,20 @@ namespace eval ::image { ret.components = components; ret.bytesPerRow = ret.width * ret.components; ret.data = folkHeapAlloc(ret.bytesPerRow * ret.height); - - for(int i = 0; i < ret.width*ret.height; i++) { - int r = im.data[i*im.components+0], - g = im.data[i*im.components+1], - b = im.data[i*im.components+2]; - - ret.data[i*ret.components+0] = r; - ret.data[i*ret.components+1] = g; - ret.data[i*ret.components+2] = b; - ret.data[i*ret.components+3] = 255; + + for (int y = 0; y < im.height; y++) { + for (int x = 0; x < im.width; x++) { + int imidx = y*im.bytesPerRow + x*im.components; + int r = im.data[imidx+0], + g = im.data[imidx+1], + b = im.data[imidx+2]; + + int ridx = y*ret.bytesPerRow + x*ret.components; + ret.data[ridx+0] = r; + ret.data[ridx+1] = g; + ret.data[ridx+2] = b; + ret.data[ridx+3] = 255; + } } return ret; } -- cgit v1.2.3 From 254f53f31d45232428f703324a518a9bb48fad67 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 26 Sep 2023 21:14:22 -0400 Subject: display: Image rotation works. Also fix text rotation issues? Use fix from shadertoy comment to remove invBilinear instability on rotation. --- virtual-programs/display.folk | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index ef24c9d8..369e962a 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -44,6 +44,7 @@ On process { variable cross2d [Gpu::fn {vec2 a vec2 b} float { return a.x*b.y - a.y*b.x; }] + # See https://www.shadertoy.com/view/lsBSDm variable invBilinear [Gpu::fn {vec2 p vec2 a vec2 b vec2 c vec2 d} {cross2d} vec2 { vec2 res = vec2(-1.0); @@ -57,7 +58,8 @@ On process { float k0 = cross2d( h, e ); // if edges are parallel, this is a linear equation - if( abs(k2)<0.001 ) + k2 /= k0; k1 /= k0; k0 = 1.0; + if( abs(k2)<0.001*abs(k0) ) { res = vec2( (h.x*k1+f.x*k0)/(e.x*k1-g.x*k0), -k0/k1 ); } @@ -302,18 +304,19 @@ On process { } variable image [Gpu::pipeline {sampler2D image vec2 imageSize - vec2 pos float radians float scale} { - vec2 a = pos - imageSize/2; - vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2; - vec2 c = pos + imageSize/2; - vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2; + vec2 pos float radians float scale + fn rotate} { + vec2 a = pos + rotate(-imageSize/2, -radians); + vec2 b = pos + rotate(vec2(imageSize.x, -imageSize.y)/2, -radians); + vec2 c = pos + rotate(imageSize/2, -radians); + vec2 d = pos + rotate(vec2(-imageSize.x, imageSize.y)/2, -radians); vec2 vertices[4] = vec2[4](a, b, d, c); return vertices[gl_VertexIndex]; - } {fn invBilinear} { - vec2 a = pos - imageSize/2; - vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2; - vec2 c = pos + imageSize/2; - vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2; + } {fn invBilinear fn rotate} { + vec2 a = pos + rotate(-imageSize/2, -radians); + vec2 b = pos + rotate(vec2(imageSize.x, -imageSize.y)/2, -radians); + vec2 c = pos + rotate(imageSize/2, -radians); + vec2 d = pos + rotate(vec2(-imageSize.x, imageSize.y)/2, -radians); vec2 p = gl_FragCoord.xy; vec2 uv = invBilinear(p, a, b, c, d); if( max( abs(uv.x-0.5), abs(uv.y-0.5))<0.5 ) { @@ -323,6 +326,8 @@ On process { }] variable imCache [dict create] proc image {x y im radians {scale 1.0}} { + # TODO: Implement scale. + # TODO: Free images from cache. variable image variable imCache if {![dict exists $imCache $im]} { @@ -330,7 +335,6 @@ On process { dict set imCache $im $gim } set gim [dict get $imCache $im] - puts $gim Gpu::draw $image $gim [list [::image width $im] [::image height $im]] \ [list $x $y] $radians $scale } -- cgit v1.2.3 From 2f44373e4e04ce0b726948acc715ff925b061254 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 15:02:52 -0400 Subject: Gpu: Clean up sampler2D accesses. Clean up dep fns for fns. No more arbitrary samplers array -- you can just use the argname directly as a parameter to texture(). --- virtual-programs/display.folk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 369e962a..adc1ec04 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -45,7 +45,7 @@ On process { return a.x*b.y - a.y*b.x; }] # See https://www.shadertoy.com/view/lsBSDm - variable invBilinear [Gpu::fn {vec2 p vec2 a vec2 b vec2 c vec2 d} {cross2d} vec2 { + variable invBilinear [Gpu::fn {vec2 p vec2 a vec2 b vec2 c vec2 d fn cross2d} vec2 { vec2 res = vec2(-1.0); vec2 e = b-a; @@ -115,7 +115,7 @@ On process { variable font [font load "PTSans-Regular"] variable glyphMsd [Gpu::fn {sampler2D atlas vec4 atlasGlyphBounds vec2 glyphUv} vec4 { vec2 atlasUv = mix(atlasGlyphBounds.xw, atlasGlyphBounds.zy, glyphUv); - return texture(atlas, vec2(atlasUv.x, 1.0-atlasUv.y)); + return texture(atlas, vec2(atlasUv.x, 1.0-atlasUv.y)); }] variable median [Gpu::fn {float r float g float b} float { return max(min(r, g), min(max(r, g), b)); @@ -150,7 +150,7 @@ On process { if( max( abs(glyphUv.x-0.5), abs(glyphUv.y-0.5))>=0.5 ) { return vec4(0, 0, 0, 0); } - vec3 msd = glyphMsd(samplers[atlas], atlasGlyphBounds/atlasSize.xyxy, glyphUv).rgb; + vec3 msd = glyphMsd(atlas, atlasGlyphBounds/atlasSize.xyxy, glyphUv).rgb; float sd = median(msd.r, msd.g, msd.b); float screenPxDistance = 4.5*(sd - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); @@ -320,7 +320,7 @@ On process { vec2 p = gl_FragCoord.xy; vec2 uv = invBilinear(p, a, b, c, d); if( max( abs(uv.x-0.5), abs(uv.y-0.5))<0.5 ) { - return texture(samplers[image], uv); + return texture(image, uv); } return vec4(0.0, 0.0, 0.0, 0.0); }] -- cgit v1.2.3 From 471b7beb6e9ed19c6b432405528ffc781655bb6e Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 15:24:09 -0400 Subject: Gpu: Convert 1 & 3-channel images at callee. Start fixing cam slice. Removes rechannel! --- virtual-programs/display.folk | 4 ++-- virtual-programs/images.folk | 28 ---------------------------- 2 files changed, 2 insertions(+), 30 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index adc1ec04..4d4a1e09 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -100,7 +100,7 @@ On process { } set im [image load "[pwd]/vendor/fonts/$name.png"] - set gim [Gpu::ImageManager::copyImageToGpu [image rechannel $im 4]] + set gim [Gpu::ImageManager::copyImageToGpu $im] return [list $glyphInfos $im $gim] } @@ -331,7 +331,7 @@ On process { variable image variable imCache if {![dict exists $imCache $im]} { - set gim [Gpu::ImageManager::copyImageToGpu [::image rechannel $im 4]] + set gim [Gpu::ImageManager::copyImageToGpu $im] dict set imCache $im $gim } set gim [dict get $imCache $im] diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index 120b340a..ae793bc8 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -262,34 +262,6 @@ namespace eval ::image { // TODO: Free the PNG. } - # Allocates(!) a copy of `im` with `components` channels. Up to - # the caller to free it. - $cc proc rechannel {image_t im int components} image_t { - if (im.components == components) return im; - if (components != 4 || im.components != 3) exit(2); - - image_t ret = im; - ret.components = components; - ret.bytesPerRow = ret.width * ret.components; - ret.data = folkHeapAlloc(ret.bytesPerRow * ret.height); - - for (int y = 0; y < im.height; y++) { - for (int x = 0; x < im.width; x++) { - int imidx = y*im.bytesPerRow + x*im.components; - int r = im.data[imidx+0], - g = im.data[imidx+1], - b = im.data[imidx+2]; - - int ridx = y*ret.bytesPerRow + x*ret.components; - ret.data[ridx+0] = r; - ret.data[ridx+1] = g; - ret.data[ridx+2] = b; - ret.data[ridx+3] = 255; - } - } - return ret; - } - $cc compile variable imagesCache [dict create] -- cgit v1.2.3 From 038cf3b20327c1a983d5b29340704838b88d93c6 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 15:36:16 -0400 Subject: display: Center text again, shrink it a bit --- virtual-programs/display.folk | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 4d4a1e09..0bb0b88e 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -214,9 +214,9 @@ On process { Gpu::draw $circle [list $x $y] $radius $thickness [getColor $color] [ne $filled "false"] } - proc textMetrics {text scale} { + proc textExtent {text scale} { variable font - set em [* $scale 30.0] + set em [* $scale 25.0] set x 0; set y 0 for {set i 0} {$i < [string length $text]} {incr i} { set char [string index $text $i] @@ -240,8 +240,17 @@ On process { set fontAtlas [font gpuAtlasImage $font] set fontAtlasSize [list [::image width [font atlasImage $font]] \ [::image height [font atlasImage $font]]] - set em [* $scale 30.0] + + set extent [vec2 rotate [textExtent $text $scale] $radians] + + set em [* $scale 25.0] + + # TODO: Add text alignment/anchor options (right now, this + # setup centers the text). + set x0 [expr {$x0 - [lindex $extent 0]/2}] + set y0 [expr {$y0 - [lindex $extent 1]/2}] set x $x0; set y $y0 + set lineNum 0 for {set i 0} {$i < [string length $text]} {incr i} { set char [string index $text $i] -- cgit v1.2.3 From 66ffc532b2b7f476ee1e3e6a76aaf66f30194ee1 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 17:05:34 -0400 Subject: calibrate: WIP: Port to Vulkan. It kind of works but is unreliable (might just be general calibration problems, though). --- virtual-programs/images.folk | 6 +++++- virtual-programs/tags-and-calibration.folk | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index ae793bc8..5523e0a0 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -35,7 +35,11 @@ namespace eval ::image { defineImageType $cc $cc include $cc include - $cc import ::Heap::cc folkHeapAlloc as folkHeapAlloc + if {[namespace exists ::Heap]} { + $cc import ::Heap::cc folkHeapAlloc as folkHeapAlloc + } else { + $cc code { #define folkHeapAlloc malloc } + } $cc code { #undef EXTERN diff --git a/virtual-programs/tags-and-calibration.folk b/virtual-programs/tags-and-calibration.folk index b219b541..8bfa067c 100644 --- a/virtual-programs/tags-and-calibration.folk +++ b/virtual-programs/tags-and-calibration.folk @@ -33,6 +33,10 @@ When camera /camera/ has width /cameraWidth/ height /cameraHeight/ { [expr {double($dy)/$generatedCalibration::displayHeight*$Display::HEIGHT}]] } } + if {[llength $points] < 4} { + puts stderr "tags-and-calibration: Calibration isn't valid (not enough points). Stopping Folk." + exit 1 + } for {set i 0} {$i < [llength $points]} {incr i} { lassign [lindex $points $i] x$i y$i u$i v$i } -- cgit v1.2.3 From 75403d327b82d10e62e3c32a47b98cc23ea095c8 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 17:44:20 -0400 Subject: display: Load images before starting Gpu frame --- virtual-programs/display.folk | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 0bb0b88e..268e462d 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -334,15 +334,18 @@ On process { return vec4(0.0, 0.0, 0.0, 0.0); }] variable imCache [dict create] - proc image {x y im radians {scale 1.0}} { - # TODO: Implement scale. - # TODO: Free images from cache. - variable image + proc checkImCacheAndCopyIfNeeded {im} { variable imCache if {![dict exists $imCache $im]} { set gim [Gpu::ImageManager::copyImageToGpu $im] dict set imCache $im $gim } + } + proc image {x y im radians {scale 1.0}} { + # TODO: Implement scale. + # TODO: Free images from cache. + variable image + variable imCache set gim [dict get $imCache $im] Gpu::draw $image $gim [list [::image width $im] [::image height $im]] \ [list $x $y] $radians $scale @@ -386,6 +389,12 @@ On process { } set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] + foreach command $displayCommands { + if {[lindex $command 0] eq "Display::image"} { + set im [lindex $command 3] + Display::checkImCacheAndCopyIfNeeded $im + } + } set renderTime [baretime { Display::start foreach command $displayCommands { {*}$command } -- cgit v1.2.3 From e27ada832c5249724674500b44d21616c0c2407f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Thu, 28 Sep 2023 20:51:54 -0400 Subject: main,camera: Can now free things from Folk interprocess heap Finish switch to dlmalloc. Get rid of hacky mempool in camera and just use the heap. --- virtual-programs/camera.folk | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/camera.folk b/virtual-programs/camera.folk index 428c4195..8f49393d 100644 --- a/virtual-programs/camera.folk +++ b/virtual-programs/camera.folk @@ -16,15 +16,37 @@ set height $::Camera::HEIGHT On process { source pi/Camera.tcl - Camera::init $width $height - puts "Camera tid: [getTid] booting at [clock milliseconds]" + set camera [Camera::cameraOpen "/dev/video0" $width $height] + Camera::cameraInit $camera + Camera::cameraStart $camera + # skip 5 frames for booting a cam + for {set i 0} {$i < 5} {incr i} { + Camera::cameraFrame $camera + } + + puts "Camera tid: [getTid] booted at [clock milliseconds]" + + fn grayFrame {} { + if {![Camera::cameraFrame $camera]} { + error "Failed to capture from camera" + } + set image [Camera::newImage $width $height 1] + Camera::cameraDecompressGray $camera $image + return $image + } + set ::oldFrames [list] When $::thisProcess has step count /c/ { - set grayFrame [Camera::grayFrame] + set frame [grayFrame] Commit { Claim the camera time is $::stepTime - Claim the camera frame is $grayFrame at [clock milliseconds] + Claim the camera frame is $frame at [clock milliseconds] + } + lappend ::oldFrames $frame + if {[llength $::oldFrames] >= 10} { + set ::oldFrames [lassign $::oldFrames oldestFrame] + Camera::freeImage $oldestFrame } } } -- cgit v1.2.3 From 0dbceb76d14382a0eab62f4c6c3bb5eb7e4d06eb Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 29 Sep 2023 07:02:06 -0400 Subject: display: Fix text extent computation / centering --- virtual-programs/display.folk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 268e462d..e42ea621 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -218,6 +218,7 @@ On process { variable font set em [* $scale 25.0] set x 0; set y 0 + set width 0 for {set i 0} {$i < [string length $text]} {incr i} { set char [string index $text $i] if {$char eq "\n"} { @@ -231,8 +232,9 @@ On process { } lassign $glyphInfo advance planeBounds atlasBounds set x [+ $x [* $advance $em]] + if {$x > $width} { set width $x } } - return [list $x $y] + return [list $width [+ $y $em]] } proc text {x0 y0 scale text radians} { variable font -- cgit v1.2.3 From b0c3e190aad5f948f041a9d3fd6929e2892dea17 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 29 Sep 2023 07:05:22 -0400 Subject: Use c struct for image_t Preparing to invent managed references --- virtual-programs/apriltags.folk | 22 +++++++++++----------- virtual-programs/images.folk | 23 +++++++++++------------ 2 files changed, 22 insertions(+), 23 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/apriltags.folk b/virtual-programs/apriltags.folk index 69fcf51c..7e190a5b 100644 --- a/virtual-programs/apriltags.folk +++ b/virtual-programs/apriltags.folk @@ -53,17 +53,17 @@ On process { [list /someone/ wishes /something/ displays camera slice /slice/] proc subimage {im x y subwidth subheight} { - dict with im { - set x [expr {int($x)}] - set y [expr {int($y)}] - set subdata [expr {$data + ($y*$width + $x) * $components}] - dict create \ - width [int $subwidth] \ - height [int $subheight] \ - components $components \ - bytesPerRow $bytesPerRow \ - data [format 0x%x $subdata] - } + dict with im { + set x [expr {int($x)}] + set y [expr {int($y)}] + set subdata [expr {[lindex $data 1] + ($y*$width + $x) * $components}] + dict create \ + width [int $subwidth] \ + height [int $subheight] \ + components $components \ + bytesPerRow $bytesPerRow \ + data [format "(uint8_t*) 0x%x" $subdata] + } } set detector [AprilTags new $tagfamily] diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk index 5523e0a0..bfa5daef 100644 --- a/virtual-programs/images.folk +++ b/virtual-programs/images.folk @@ -1,4 +1,3 @@ - # Example program, i.e the public API # # When $this has camera slice /slice/ { @@ -10,17 +9,17 @@ namespace eval ::image { proc width {im} { dict get $im width } proc height {im} { dict get $im height } proc subimage {im x y subwidth subheight} { - dict with im { - set x [expr {int($x)}] - set y [expr {int($y)}] - set subdata [expr {$data + ($y*$width + $x) * $components}] - dict create \ - width $subwidth \ - height $subheight \ - components $components \ - bytesPerRow $bytesPerRow \ - data [format 0x%x $subdata] - } + dict with im { + set x [expr {int($x)}] + set y [expr {int($y)}] + set subdata [expr {[lindex $data 1] + ($y*$width + $x) * $components}] + dict create \ + width $subwidth \ + height $subheight \ + components $components \ + bytesPerRow $bytesPerRow \ + data [format "(uint8_t*) 0x%x" $subdata] + } } set cc [c create] -- cgit v1.2.3 From 0514980d249fd72e23532c93c3615c1d52ce0c9d Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 30 Sep 2023 12:04:14 -0400 Subject: main,display: Version the Folk heap; evict stale/unused images. This at least keeps camera slices from crashing the system. TODO: Don't draw stale images. --- virtual-programs/display.folk | 55 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index e42ea621..222813a1 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -336,19 +336,56 @@ On process { return vec4(0.0, 0.0, 0.0, 0.0); }] variable imCache [dict create] - proc checkImCacheAndCopyIfNeeded {im} { + variable IMCACHE_MAX_IMAGES [- $Gpu::ImageManager::GPU_MAX_IMAGES 1] + proc checkImCacheAndCopyIfNeeded {imDrawSet} { variable imCache - if {![dict exists $imCache $im]} { - set gim [Gpu::ImageManager::copyImageToGpu $im] - dict set imCache $im $gim + variable IMCACHE_MAX_IMAGES + set notInCache [dictset difference $imDrawSet $imCache] + set notInDrawSet [dictset difference $imCache $imDrawSet] + + set numImagesToCopy [dictset size $notInCache] + if {$numImagesToCopy > 0} { + if {[dictset size $imCache] + $numImagesToCopy > $IMCACHE_MAX_IMAGES} { + set numImagesToEvict \ + [expr {[dictset size $imCache] + $numImagesToCopy - $IMCACHE_MAX_IMAGES}] + + # What can we safely evict? + # - Anything that's stale + # - Anything that's not in use + set numImagesEvicted 0 + dict for {im v} $imCache { + if {$numImagesEvicted == $numImagesToEvict} { break } + + lassign $v gim expectedVersion + set version [Heap::folkHeapGetVersion [string map {uint8_t void} [::image_t data_ptr $im]]] + if {$expectedVersion != $version} { + Gpu::ImageManager::freeGpuImage $gim + dict unset imCache $im + incr numImagesEvicted + continue + } + if {![dict exists $imDrawSet $im]} { + Gpu::ImageManager::freeGpuImage $gim + dict unset imCache $im + incr numImagesEvicted + } + } + } + + dict for {im _} $notInCache { + # TODO: This is unsafe (has a race condition) -- we're + # not locking the image, so version and gim may diverge. + set version [Heap::folkHeapGetVersion [string map {uint8_t void} [::image_t data_ptr $im]]] + set gim [Gpu::ImageManager::copyImageToGpu $im] + dict set imCache $im [list $gim $version] + } } } proc image {x y im radians {scale 1.0}} { # TODO: Implement scale. - # TODO: Free images from cache. variable image variable imCache - set gim [dict get $imCache $im] + lassign [dict get $imCache $im] gim Gpu::draw $image $gim [list [::image width $im] [::image height $im]] \ [list $x $y] $radians $scale } @@ -391,12 +428,16 @@ On process { } set displayCommands [lmap sublist [lsort -command lcomp $displayList] {lindex $sublist 1}] + + set imDrawSet [dictset create] foreach command $displayCommands { if {[lindex $command 0] eq "Display::image"} { set im [lindex $command 3] - Display::checkImCacheAndCopyIfNeeded $im + dictset add imDrawSet $im } } + Display::checkImCacheAndCopyIfNeeded $imDrawSet + set renderTime [baretime { Display::start foreach command $displayCommands { {*}$command } -- cgit v1.2.3 From b4fe442a55d200fc682a7ca4f202274458ec5f12 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 30 Sep 2023 12:12:48 -0400 Subject: display: Camera slice works! Always evict stale draw set images --- virtual-programs/display.folk | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'virtual-programs') diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk index 222813a1..f7b70959 100644 --- a/virtual-programs/display.folk +++ b/virtual-programs/display.folk @@ -340,6 +340,18 @@ On process { proc checkImCacheAndCopyIfNeeded {imDrawSet} { variable imCache variable IMCACHE_MAX_IMAGES + + dict for {im v} $imDrawSet { + if {![dict exists $imCache $im]} { continue } + # Check for staleness and remove from cache if so. + lassign [dict get $imCache $im] gim expectedVersion + set version [Heap::folkHeapGetVersion [string map {uint8_t void} [::image_t data_ptr $im]]] + if {$expectedVersion != $version} { + Gpu::ImageManager::freeGpuImage $gim + dict unset imCache $im + } + } + set notInCache [dictset difference $imDrawSet $imCache] set notInDrawSet [dictset difference $imCache $imDrawSet] -- cgit v1.2.3 From 82b53f173a6f08c5ee952eaa97def3cff61c92f1 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 2 Oct 2023 16:56:20 -0400 Subject: camera,calibrate: Fixing really bad breakage from refactors (mostly undoing refactor; also pointer fix in calibrate) --- virtual-programs/camera.folk | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/camera.folk b/virtual-programs/camera.folk index 8f49393d..0e1710e7 100644 --- a/virtual-programs/camera.folk +++ b/virtual-programs/camera.folk @@ -17,28 +17,13 @@ set height $::Camera::HEIGHT On process { source pi/Camera.tcl - set camera [Camera::cameraOpen "/dev/video0" $width $height] - Camera::cameraInit $camera - Camera::cameraStart $camera - # skip 5 frames for booting a cam - for {set i 0} {$i < 5} {incr i} { - Camera::cameraFrame $camera - } + Camera::init $width $height puts "Camera tid: [getTid] booted at [clock milliseconds]" - fn grayFrame {} { - if {![Camera::cameraFrame $camera]} { - error "Failed to capture from camera" - } - set image [Camera::newImage $width $height 1] - Camera::cameraDecompressGray $camera $image - return $image - } - set ::oldFrames [list] When $::thisProcess has step count /c/ { - set frame [grayFrame] + set frame [Camera::grayFrame] Commit { Claim the camera time is $::stepTime Claim the camera frame is $frame at [clock milliseconds] -- cgit v1.2.3