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