Просмотр исходного кода

Unhardcode demo resolution for WASM_PLATFORM

rexim 3 лет назад
Родитель
Сommit
1123f1a32d
9 измененных файлов с 45 добавлено и 18 удалено
  1. 1 1
      build.sh
  2. 2 5
      demos/3d.c
  3. 2 2
      demos/squish.c
  4. 2 2
      demos/triangle.c
  5. 5 4
      demos/vc.c
  6. 33 4
      js/vc.js
  7. BIN
      wasm/3d.wasm
  8. BIN
      wasm/squish.wasm
  9. BIN
      wasm/triangle.wasm

+ 1 - 1
build.sh

@@ -7,7 +7,7 @@ COMMON_CFLAGS="-Wall -Wextra -ggdb -I. -I./build/ -I./thirdparty/"
 build_vc_demo() {
     NAME=$1
 
-    clang $COMMON_CFLAGS -Os -fno-builtin --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--allow-undefined -o ./build/$NAME.wasm -DPLATFORM=WASM_PLATFORM ./demos/$NAME.c
+    clang $COMMON_CFLAGS -Os -fno-builtin --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--export=__heap_base -Wl,--allow-undefined -o ./build/$NAME.wasm -DPLATFORM=WASM_PLATFORM ./demos/$NAME.c
     cp ./build/$NAME.wasm ./wasm/
     clang $COMMON_CFLAGS -o ./build/$NAME.sdl -DPLATFORM=SDL_PLATFORM ./demos/$NAME.c -lm -lSDL2
     clang $COMMON_CFLAGS -o ./build/$NAME.term -DPLATFORM=TERM_PLATFORM ./demos/$NAME.c -lm

+ 2 - 5
demos/3d.c

@@ -11,11 +11,8 @@ float cosf(float x);
 
 #define PI 3.14159265359
 
-// #define FACTOR 100
-// #define WIDTH (16*FACTOR)
-// #define HEIGHT (9*FACTOR)
-#define WIDTH 800
-#define HEIGHT 600
+#define WIDTH 960
+#define HEIGHT 720
 #define SCALE_DOWN_FACTOR 10
 #define BACKGROUND_COLOR 0xFF181818
 #define GRID_COUNT 10

+ 2 - 2
demos/squish.c

@@ -3,8 +3,8 @@
 
 #include "./assets/tsodinPog.c"
 
-#define WIDTH 800
-#define HEIGHT 600
+#define WIDTH 960
+#define HEIGHT 720
 #define SCALE_DOWN_FACTOR 10
 
 float sinf(float);

+ 2 - 2
demos/triangle.c

@@ -4,8 +4,8 @@
 #define OLIVEC_IMPLEMENTATION
 #include "olive.c"
 
-#define WIDTH 800
-#define HEIGHT 600
+#define WIDTH 960
+#define HEIGHT 720
 #define SCALE_DOWN_FACTOR 20
 #define BACKGROUND_COLOR 0xFF181818
 #define CIRCLE_RADIUS 100

+ 5 - 4
demos/vc.c

@@ -63,7 +63,7 @@ int main(void)
     {
         if (SDL_Init(SDL_INIT_VIDEO) < 0) return_defer(1);
 
-        window = SDL_CreateWindow("Olivec", 0, 0, WIDTH, HEIGHT, 0);
+        window = SDL_CreateWindow("Olivec", 0, 0, 0, 0, 0);
         if (window == NULL) return_defer(1);
 
         renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
@@ -81,18 +81,19 @@ int main(void)
             while (SDL_PollEvent(&event)) if (event.type == SDL_QUIT) return_defer(0);
 
             // Render the texture
-            SDL_Rect window_rect = {0, 0, WIDTH, HEIGHT};
             Olivec_Canvas oc_src = render(dt);
             if (oc_src.width != actual_width || oc_src.height != actual_height) {
                 if (!resize_texture(renderer, oc_src.width, oc_src.height)) return_defer(1);
+                SDL_SetWindowSize(window, actual_width, actual_height);
             }
             void *pixels_dst;
             int pitch;
+            SDL_Rect window_rect = {0, 0, actual_width, actual_height};
             if (SDL_LockTexture(texture, &window_rect, &pixels_dst, &pitch) < 0) return_defer(1);
-            for (size_t y = 0; y < HEIGHT; ++y) {
+            for (size_t y = 0; y < actual_height; ++y) {
                 // TODO: it would be call if Olivec_Canvas support pitch in bytes instead of pixels
                 // It would be more flexible
-                memcpy(pixels_dst + y*pitch, oc_src.pixels + y*WIDTH, WIDTH*sizeof(uint32_t));
+                memcpy(pixels_dst + y*pitch, oc_src.pixels + y*actual_width, actual_width*sizeof(uint32_t));
             }
             SDL_UnlockTexture(texture);
 

+ 33 - 4
js/vc.js

@@ -1,3 +1,4 @@
+// Browser runtime for the Demo Virtual Console
 function make_environment(...envs) {
     return new Proxy(envs, {
         get(target, prop, receiver) {
@@ -18,6 +19,26 @@ const libm = {
     "sqrtf": Math.sqrt,
 };
 
+let iota = 0;
+// TODO: nothing in this Canvas "declaration" states that iota's measure units are Uint32
+// Which is not useful for all kinds of structures. A more general approach would be to use Uint8 as the measure units.
+const CANVAS_PIXELS = iota++;
+const CANVAS_WIDTH  = iota++;
+const CANVAS_HEIGHT = iota++;
+const CANVAS_STRIDE = iota++;
+const CANVAS_SIZE   = iota++;
+
+function readCanvasFromMemory(memory_buffer, canvas_ptr)
+{
+    const canvas_memory = new Uint32Array(memory_buffer, canvas_ptr, CANVAS_SIZE);
+    return {
+        pixels: canvas_memory[CANVAS_PIXELS],
+        width: canvas_memory[CANVAS_WIDTH],
+        height: canvas_memory[CANVAS_HEIGHT],
+        stride: canvas_memory[CANVAS_STRIDE],
+    };
+}
+
 async function startDemo(elementId, wasmPath) {
     const app = document.getElementById(elementId);
     if (app === null) {
@@ -25,13 +46,13 @@ async function startDemo(elementId, wasmPath) {
         return;
     }
 
-    app.width = 800;
-    app.height = 600;
     const ctx = app.getContext("2d");
     const w = await WebAssembly.instantiateStreaming(fetch(wasmPath), {
         "env": make_environment(libm)
     });
 
+    const heap_base = w.instance.exports.__heap_base.value;
+
     let prev = null;
     function first(timestamp) {
         prev = timestamp;
@@ -41,9 +62,17 @@ async function startDemo(elementId, wasmPath) {
         const dt = timestamp - prev;
         prev = timestamp;
 
-        const pixels = w.instance.exports.render(dt*0.001);
         const buffer = w.instance.exports.memory.buffer;
-        const image = new ImageData(new Uint8ClampedArray(buffer, pixels, app.width*app.height*4), app.width);
+        w.instance.exports.render(heap_base, dt*0.001);
+        const canvas = readCanvasFromMemory(buffer, heap_base);
+        if (canvas.width != canvas.stride) {
+            // TODO: maybe we can preallocate a Uint8ClampedArray on JavaScript side and just copy the canvas data there to bring width and stride to the same value?
+            console.error(`Canvas width (${canvas.width}) is not equal to its stride (${canvas.stride}). Unfortunately we can't easily support that in a browser because ImageData simply does not accept stride. Welcome to 2022.`);
+            return;
+        }
+        const image = new ImageData(new Uint8ClampedArray(buffer, canvas.pixels, canvas.width*canvas.height*4), canvas.width);
+        app.width = canvas.width;
+        app.height = canvas.height;
         ctx.putImageData(image, 0, 0);
         window.requestAnimationFrame(loop);
     }


BIN
wasm/squish.wasm


BIN
wasm/triangle.wasm