nanogui: Thread: propose low-level line draw?


[<<] [<] Page 1 of 1 [>] [>>]
Subject: propose low-level line draw?
From: Kaben Nanlohy ####@####.####
Date: 18 Dec 2000 21:56:28 -0000
Message-Id: <Pine.NEB.4.21.0012181329430.14684-100000@kaben.frye.com>

I've been doing lots of real-time graphing of the results of signal
processing, and I've found that the bottleneck in my applications is the
high-level linedraw routine of nano-X.

GdLine() handles bresenham, and calls GdClipPoint() and psd->DrawPixel()
for each pixel.  It's the stack setup and takedown that's eating processor
time.

In the source for GdLine() is the comment:

/*
 * For size considerations, there's no low-level bresenham line draw, so
 * we've got to draw all non-vertical and non-horizontal lines with
 * per-point clipping for the time being.
 */

Does "for the time being" mean that someone has ideas for a faster
linedraw that either replaces per-point clipping with something more
efficient, or that makes use of low-level bresenham in the driver?

I've been giving thought to such a low-level driver routine, and it seems
to me that the center of the problem is starting bresenham at the start of
a clipping region instead of the start of the line, while still drawing
all points of the line at the same positions as are drawn by the current
GdLine() function.

All of the state in bresenham is carried pixel-to-pixel in the decision
variable "rem" in GdLine(), in the slope variables "xdelta" and "ydelta",
and in the oordinate variables "x1" and "y1".  GdLine() could, at least
for rectangular clipping regions, prepare those five state variables
after clipping, and pass them along with "x2" and "y2" (as the other
clipping bounds) and "psd" and "line_color" to a low-level linedraw once
for each clipped line segment.

***

Someone with experience in optimizing graphics engines has probably
thought of all of this before, and with respect to nano-X.  Since I don't
have that kind of experience, I'd like to know what other people have
thought along these lines.  In particular would this set-up per line
segment waste more time than would be saved, are these ideas counter to
the design of the drivers, etc.

***

Thanks much, merry xmas -- Kaben

Subject: Re: propose low-level line draw?
From: "Greg Haerr" ####@####.####
Date: 18 Dec 2000 22:12:05 -0000
Message-Id: <001901c06940$b5023ca0$6817dbd0@censoft.com>

: GdLine() handles bresenham, and calls GdClipPoint() and psd->DrawPixel()
: for each pixel.  It's the stack setup and takedown that's eating processor
: time.

Make sure you #define NDEBUG in the fblinX.c driver for final
production code, it will run without any of the assert()'s.  What
bpp are you running?


: Does "for the time being" mean that someone has ideas for a faster
: linedraw that either replaces per-point clipping with something more
: efficient, or that makes use of low-level bresenham in the driver?
:
: I've been giving thought to such a low-level driver routine, and it seems
: to me that the center of the problem is starting bresenham at the start of
: a clipping region instead of the start of the line, while still drawing
: all points of the line at the same positions as are drawn by the current
: GdLine() function.

Likely, your problem is that the bresenham drawing is too slow,
even when drawing to an unobscured window.  If this is the case,
then when GdClipArea returns VISIBLE, we should go directly to
a driver-level routine that draws w/o clipping.  This will remove
almost all the setup/takedown time that you're seeing hurt performance.
It's unlikely that recoding the upper level routine as you suggest below
will help much, since usually you'll have one clip rectangle - your
window border.



: Someone with experience in optimizing graphics engines has probably
: thought of all of this before, and with respect to nano-X.  Since I don't
: have that kind of experience, I'd like to know what other people have
: thought along these lines.  In particular would this set-up per line
: segment waste more time than would be saved, are these ideas counter to
: the design of the drivers, etc.

I have been working on just getting Microwindows basic draw capabilities
running, rather than getting it optimized.  The plan is to add either a
direct
low-level screen driver entry point or an upper-level non-clipped routine
for speed when needed.  The drawback to adding another screen driver
entry point is that then everybody needs to write the routine in order to
bring up Microwindows on a new platform.  I've purposely kept as
many routines out as possible - because I want Microwindows to
be easy to port and easy to understand...

Regards,

Greg



Subject: Re: propose low-level line draw?
From: Kaben Nanlohy ####@####.####
Date: 18 Dec 2000 23:22:49 -0000
Message-Id: <Pine.NEB.4.21.0012181450090.14954-100000@kaben.frye.com>

On Mon, 18 Dec 2000, Greg Haerr wrote:
> I have been working on just getting Microwindows basic draw
> capabilities running, rather than getting it optimized.  The plan is
> to add either a direct low-level screen driver entry point or an
> upper-level non-clipped routine for speed when needed.  The drawback
> to adding another screen driver entry point is that then everybody
> needs to write the routine in order to bring up Microwindows on a new
> platform.  I've purposely kept as many routines out as possible -
> because I want Microwindows to be easy to port and easy to
> understand...


How about putting a "gen_linedraw()" into genmem.c, where gen_linedraw()
draws pixel-by-pixel using psd->drawpixel()?  Then set_subdriver() or
select_fb_subdriver() can fill-in a low-level linedraw with something that
works in all cases in which psd->drawpixel() works, and where an optimized
psd->linedraw() routine hasn't yet been written.

This still requires hoop-jumping for clipping, tho.  Unless as a special
case clipping isn't needed.


> Make sure you #define NDEBUG in the fblinX.c driver for final
> production code, it will run without any of the assert()'s.  What
> bpp are you running?


4bpp.


> Likely, your problem is that the bresenham drawing is too slow,
> even when drawing to an unobscured window.  If this is the case,
> then when GdClipArea returns VISIBLE, we should go directly to
> a driver-level routine that draws w/o clipping.  This will remove
> almost all the setup/takedown time that you're seeing hurt performance.
> It's unlikely that recoding the upper level routine as you suggest below
> will help much, since usually you'll have one clip rectangle - your
> window border.


I'm double-buffering graphs at about eight frames per second, using a
linear4_blit() that has been messily optimized for double-word copies
except at boundaries of the rectangle.

I blit from a portion of the offscreen pixmap to the display window.  As
long as my pixmap has more height than the range of my graphs, clipped
linedraws to the pixmap are not required.

For my purposes, at least, calling an unclipped psd->linedraw() from
GdLine() would be wonderful.

***

As soon as I have something that works, I'll post it to the list.

Thanks -- Kaben Nanlohy

Subject: Re: propose low-level line draw?
From: Morten Rolland ####@####.####
Date: 19 Dec 2000 09:07:49 -0000
Message-Id: <3A3F1B08.2344D5EA@screenmedia.no>

Kaben Nanlohy wrote:
> 
> How about putting a "gen_linedraw()" into genmem.c, where gen_linedraw()
> draws pixel-by-pixel using psd->drawpixel()?  Then set_subdriver() or
> select_fb_subdriver() can fill-in a low-level linedraw with something that
> works in all cases in which psd->drawpixel() works, and where an optimized
> psd->linedraw() routine hasn't yet been written.
>

This is what should ultimately be done for all the drawing functions in
the low level driver that are more complex than get/set pixel (and maybe
hline and some sort of scanline for speeding up unoptimized GdArea/Image).
The benefits would be:

   1) The general functions would be regarded as the definition of a
      certain low level drawing operation and would help people
      understand the low level code and be a guide when writing
      optimized versions.  They could also be used to check the operation
      of an optimized version in a regression test setup.

   2) Move all the drawing stuff out of engine/devdraw.c - the way it is
      now is not exactly beautiful -- e.g. GrArea calls a low level
      driver to paint rectangles at a time (for clipping) when 16 bit
      colours is used (our setup), and falling through to a more general
      but much more slow version for other colour depths.
      All code in engine/devdraw.c that changes pixel values should be
      moved into a correspondingly (possibly new) low level operation,
      and care should be taken to make it possible to do clipping
      efficiently (e.g. big areas and multiple pixles at a time).

   3) Make it a requirement that all new drawing primitives be implemented
      as general low level drawing functions first so that their operation
      can be discussed and tested on all platforms and bit depths.
      This will greatly improve the tangled way of introducing new
      features into this part of the system.

Note: I haven't looked much at the code in the most recent versions.

> This still requires hoop-jumping for clipping, tho.  Unless as a special
> case clipping isn't needed.

Yes... Your situation is much similar to ours when we optimized the GdArea
function for 16 bit colours.  We implemented a low level painter that was
sufficiently flexible to paint only parts of the original image, thus
making it possible to walk the clipping rectangles for the area to be
painted and call the low level driver for the visible parts only.

This is easier for GdArea type of functions than linedrawing like you
explain, since it is important in which order you walk the rectangles,
and also not always knowing which rectangle will be next until after
a (possibly hidden) low level linedraw has been performed to update the
state of the "line draw".

For the low level GdArea we used a "hw_gc_t" struct to carry the
information to the low level driver in an easy to extend way, and
the same setup can be extended to hold the state of the line
draw operation and bring updated coordinates back to the devdraw.c
function for use when calculating the size of the next rectangle,
visible or not.  The optimized versions of the low level driver
should simply skip along when only updating the state.  This needs
more math but finishes hidden segments faster (watch this effect
in any good windowing system by hiding parts of a "line draw active"
window and watch the still visible lines speed up).

Have a look in driver/fblin16.c and engine/devdraw.c (GdArea) for
more info on how we did our optimizations.

Personally I think extending and optimizing nano-X will be
difficult unless a clean separation of the low level drawing and
the upper level clipping smarts is done, and although this is not
a prime concern for us in the short run, I see it as crucial to
make an effort in this area, and I'm prepeared to help.

Regards,
Morten Rolland, Screen Media
[<<] [<] Page 1 of 1 [>] [>>]


Powered by ezmlm-browse 0.20.