| Give jvui a picture from somewhere else, and a clock 32fae8d nandi 9d ago | 1 | (ns glimmer-jvui.video-check |
| Take the eight tags a client still had nowhere to put d5dfd53 nandi 9d ago | 2 | "An :image node with a live :feed, painted, and the pixels checked. |
| 3 | |
| 4 | :image and not a :video tag of its own, because that is how libvidya has |
| 5 | it and how frq writes it: a feed and a file differ in where the pixels |
| 6 | come from and in nothing downstream of that. |
| Give jvui a picture from somewhere else, and a clock 32fae8d nandi 9d ago | 7 | |
| 8 | The layout tests run headless and cannot see this: with no renderer every |
| 9 | frame is dropped and a video tile is an empty rectangle that lays out |
| 10 | correctly. What is actually at stake is the CHANNEL ORDER — a buffer whose |
| 11 | bytes run R,G,B,A is the 32-bit word 0xAABBGGRR, so SDL wants ABGR8888 and |
| 12 | the obvious-looking ARGB8888 rotates every channel and turns skin blue. A |
| 13 | test that only asked whether a texture existed would pass either way. |
| 14 | |
| 15 | So: a window under SDL's dummy driver, a frame with a RED left half and a |
| 16 | BLUE right half, a screenshot, and a look at what came out." |
| 17 | (:require [glimmer.core :as ui] |
| 18 | [glimmer.ratom :as ra] |
| 19 | [glimmer-jvui.core :as backend] |
| 20 | [jvui.sdl :as sdl] |
| 21 | [jolt.ffi :as ffi])) |
| 22 | |
| 23 | (defn- red-blue |
| 24 | "w by h RGBA: red left, blue right, opaque." |
| 25 | [w h] |
| 26 | (let [p (ffi/alloc (* 4 w h))] |
| 27 | (dotimes [y h] |
| 28 | (dotimes [x w] |
| 29 | (let [o (* 4 (+ (* y w) x)) |
| 30 | left? (< x (quot w 2))] |
| 31 | (ffi/write (+ p o 0) :uint8 (if left? 230 10)) ; R |
| 32 | (ffi/write (+ p o 1) :uint8 10) ; G |
| 33 | (ffi/write (+ p o 2) :uint8 (if left? 10 230)) ; B |
| 34 | (ffi/write (+ p o 3) :uint8 255)))) ; A |
| 35 | p)) |
| 36 | |
| 37 | ;; A BMP from SDL is bottom-up and 24bpp, with rows padded to a four-byte |
| 38 | ;; boundary and the pixel array offset in the header at byte 10. Every one of |
| 39 | ;; those was got wrong first time round — 32bpp and no padding — and the |
| 40 | ;; result was not an error but plausible-looking numbers from the wrong |
| 41 | ;; addresses, which is exactly how a pixel test lies to you. |
| 42 | (defn- bmp-pixel [path x y] |
| 43 | (let [b (java.nio.file.Files/readAllBytes (java.nio.file.Path/of path (into-array String []))) |
| 44 | u (fn [i] (bit-and (int (aget b i)) 255)) |
| 45 | le (fn [i] (+ (u i) (bit-shift-left (u (+ i 1)) 8) |
| 46 | (bit-shift-left (u (+ i 2)) 16) (bit-shift-left (u (+ i 3)) 24))) |
| 47 | off (le 10) |
| 48 | w (le 18) |
| 49 | h (le 22) |
| 50 | stride (* 4 (quot (+ (* w 3) 3) 4)) |
| 51 | i (+ off (* (- h 1 y) stride) (* 3 x))] |
| 52 | {:b (u i) :g (u (+ i 1)) :r (u (+ i 2))})) |
| 53 | |
| 54 | (defn -main [& _] |
| 55 | (let [px (red-blue 64 64) |
| 56 | shot (str (System/getProperty "java.io.tmpdir") "/jvui-video-check.bmp") |
| 57 | n (ra/atom 0)] |
| 58 | (try |
| 59 | ;; Pushed from a TIMER, which is how frq does it — av.clj drives its |
| 60 | ;; whole media plane from (every! 16 pump!). Pushing from the |
| 61 | ;; component body instead is what the first version of this test did, |
| 62 | ;; and it silently proved nothing: a component with no state renders |
| 63 | ;; once, at mount, before the window exists — so the frame was |
| 64 | ;; dropped for want of a renderer and the tile was empty for a |
| 65 | ;; reason that had nothing to do with the picture. |
| 66 | (backend/every! 16 (fn [] (backend/frame-rgba! "peer" 64 64 px))) |
| Take the eight tags a client still had nowhere to put d5dfd53 nandi 9d ago | 67 | (ui/run (fn [] [:image {:feed "peer" :size [120.0 120.0]}]) |
| Give jvui a picture from somewhere else, and a clock 32fae8d nandi 9d ago | 68 | {:title "video" :width 160 :height 160 :frames 6 :shot shot}) |
| 69 | (finally (ffi/free px))) |
| 70 | (let [left (bmp-pixel shot 40 80) |
| 71 | right (bmp-pixel shot 120 80) |
| 72 | ok-l (and (> (:r left) 150) (< (:b left) 100)) |
| 73 | ok-r (and (> (:b right) 150) (< (:r right) 100))] |
| 74 | (println " left pixel " (pr-str left)) |
| 75 | (println " right pixel" (pr-str right)) |
| 76 | (println (if ok-l "- the red half is red" "FAIL the red half is not red")) |
| 77 | (println (if ok-r "- the blue half is blue" "FAIL the blue half is not blue")) |
| 78 | (if (and ok-l ok-r) |
| 79 | (println "all 2 checks passed") |
| 80 | (do (println "channel order is wrong — see the ABGR note in jvui.sdl") |
| 81 | (System/exit 1)))))) |