On 1/23/08, Andy Hefner ahefner@gmail.com wrote:
On Jan 22, 2008 6:28 PM, Nikodemus Siivola nikodemus@random-state.net wrote:
Below is what I have now, and it sucks royally: DRAW-PIXEL* calls take ~8 seconds on a 400*600 region, and everything else takes < 1 second... (on CLX backend.)
Switching from draw-point* to medium-draw-point* with (setf medium-ink) is likely to be a little faster, but still pretty hopeless.
What I would like (and what the above tries to do, but fails) is to get hold of a some sort of object onto which I can efficiently blast colors pixel by pixel, and then update the screen using a convenient-for-me interval.
The existing McCLIM image facilities can (I presume) efficiently transfer RGB images, but not in the incremental manner you require. Something analogous to xlib:put-image or xlib:put-raw-image seems ideal for filling stripes of your pixmap. As a quick and dirty solution, I have some old code at http://vintage-digital.com/hefner/mcclim/medium-draw-pixels.lisp which is a thin wrapper around xlib:put-image and will (probably) work with your pixmap, taking a two-dimensional '(unsigned-byte 32) array of packed RGB values as input. X11 being what it is, you might have to twiddle the :bits-per-pixel (some machines want 32, others 24).
Perfect -- this runs in < 1 second.
(defun render-scene (scene sheet) (let* ((region (sheet-region sheet)) (width (bounding-rectangle-width region)) (height (bounding-rectangle-height region)) (end (- width 1)) (image (make-array (list 1 width) :element-type '(unsigned-byte 32)))) (raylisp::render scene (raylisp::scene-default-camera scene) width height (lambda (color x y) (declare (type (simple-array single-float (3)) color) (type fixnum x y)) ;; FIXME: Gamma... (let ((r (floor (* 255 (aref color 0)))) (g (floor (* 255 (aref color 1)))) (b (floor (* 255 (aref color 2))))) (setf (aref image 0 x) (logior (ash r 16) (ash g 8) b)) (when (= x end) (with-sheet-medium (medium sheet) (medium-draw-pixels* medium image 0 y))))) :normalize-camera t)))
Apropos: while figuring out how use your code I came across RGB-IMAGE-DESIGN, and managed to make it work for usable well as well -- code below runs in < 2 seconds.
(defun render-scene (scene medium) (let* ((region (sheet-region medium)) (width (bounding-rectangle-width region)) (height (bounding-rectangle-height region)) (end (- width 1)) (data (make-array (list 1 width) :element-type '(unsigned-byte 32)))) (raylisp::render scene (raylisp::scene-default-camera scene) width height (lambda (color x y) (declare (type (simple-array single-float (3)) color) (type fixnum x y)) ;; FIXME: Gamma... (let ((r (floor (* 255 (aref color 0)))) (g (floor (* 255 (aref color 1)))) (b (floor (* 255 (aref color 2))))) (setf (aref data 0 x) (logior (ash b 16) (ash g 8) r)) (when (= x end) (let (design) (unwind-protect (progn (setf design (climi::make-rgb-image-design (make-instance 'climi::rgb-image :width width :height 1 :data data))) (draw-design medium design :y y)) (climi::free-image-design design)))))) :normalize-camera t)))
I can live with CLIMI:: prefixes, etc... but is either of these expected to land in CLIM-EXTENSIONS anytime soon?
If you can live without the incremental display, you could display the entire image using make-image and draw-image.
...unfortunately incremental display is the only real of having a GUI on this thing -- it doesn't matter for images that render fast, but ones that take longer I want to see in progress, so I can abort if there's something wrong without waiting the whole thing out.