How do I use XDrawLine() on the SDL window in my program?

Hi.

How do I use XDrawLine() on the SDL window in my program?

( XDrawLine is Xlib function )

// ---------------------------------------------------------------------------
#include “SDL_syswm.h”

void Draw_Line(int x1, int y1, int x2, int y2)
{
SDL_SysWMinfo info;
GC gc;

SDL_VERSION(&info.version);
if ( SDL_GetWMInfo(&info) > 0 ) {
    if ( info.subsystem == SDL_SYSWM_X11 ) {
        info.info.x11.lock_func();

        gc = XCreateGC(info.info.x11.display, info.info.x11.wmwindow, 0,

0); // ???
XSetForeground(info.info.x11.display, gc,
WhitePixel(info.info.x11.display, 0)); // ???
XDrawLine(info.info.x11.display, info.info.x11.wmwindow, x1, y1,
x2, y2); // ???

        info.info.x11.unlock_func();
    }
}

}
// -------------------------------------------------------------------------

How do I use XDrawLine() on the SDL window in my program?

This sort of question tends to come up now and then: How do I get
low-level access to feature F that SDL uses? SDL is cross-platform but
this should not be interpreted in a fascist way. If the user really wants
the Window XID then he should get it.

So, I propose the following general API:

int SDL_GetParam(void *object, int param, void *var)

where
object points to the SDL object whose parameter you want
param is in a list of predefined constants
var is where the result is placed
and the return value is zero if succeeded, or -1 if failed.

Basically, this works like the catch-all ioctl() in Unix, and it has the
advantage that you can add things later and keep binary compatibility.

For example:

Window mywindow;
if(SDL_GetParam(screen, SDL_X11_WINDOW_ID, &mywindow) < 0)
die(“Not running X11!”);

or

BillGatesWindowHandle bgwhMyWindow;
if(SDL_GetParam(screen, SDL_WIN32_WINDOW_HANDLE, &bgwhMyWindow) < 0)
die(“You lucky, lucky bastard”);

For X11, the interesting parameters could be:

Window ID
GC ID
Colormap ID
Visual ID
X11 Connection (Display *)
X11 Connection (file descriptor)

For Mac, Win32, BeOS etc there are of course similar parameters.

What do you think? Implementation of this is quite trivial, we just have
to agree on the design (s/we/Sam/ :slight_smile:

Hi.

How do I use XDrawLine() on the SDL window in my program?

This is what we use in Sid Meier’s Alpha Centauri:

#include “SDL_video.h”
#include “SDL_syswm.h”

extern SDL_Surface *sdl_screen;

bool X11_line(int x_to, int y_to, int x_from, int y_from, int color, int thickness, int style)
{
SDL_SysWMinfo info;

SDL_VERSION(&info.version);
if ( SDL_GetWMInfo(&info) > 0 ) {
if ( info.subsystem == SDL_SYSWM_X11 ) {
Display *dpy;
Window win;
XWindowAttributes attributes;
GC gc;
int do_colorfree;
XColor xcolor;
XGCValues values;
unsigned long valuemask;

  info.info.x11.lock_func();
  dpy = info.info.x11.display;
  win = info.info.x11.window;

  /* Allocate the color we want in the window colormap */
  XGetWindowAttributes(dpy, win, &attributes);
  xcolor.pixel = color;
  xcolor.red = sdl_screen->format->palette->colors[color].r << 8;
  xcolor.green = sdl_screen->format->palette->colors[color].g << 8;
  xcolor.blue = sdl_screen->format->palette->colors[color].b << 8;
  xcolor.flags = (DoRed|DoGreen|DoBlue);
  do_colorfree = XAllocColor(dpy, attributes.colormap, &xcolor);

  /* Set the values for the graphic context */
  valuemask = 0;
  valuemask |= GCForeground;
  values.foreground = xcolor.pixel;
  valuemask |= GCLineWidth;
  values.line_width = thickness;
  valuemask |= GCLineStyle;
  values.line_style = LineSolid;
  gc = XCreateGC(dpy,RootWindow(dpy, DefaultScreen(dpy)),valuemask,&values);
  /* Finally draw the line */
  XDrawLine(dpy, win, gc, x_from, y_from, x_to, y_to);

  XFreeGC(dpy, gc);
  if ( do_colorfree ) {
    XFreeColors(dpy, attributes.colormap, &xcolor.pixel, 1, 0);
  }
  info.info.x11.unlock_func();
  return true;
}

}
return false;
}

However, I don’t recommend that you do this unless you absolutely have to.
This code won’t draw lines on the Linux console (or any other environment),
and breaks some Win32 X server implementations.

It would be better to find a general line implementation for the framebuffer.

See ya! :slight_smile:
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Sam Lantinga writes:

Hi.

How do I use XDrawLine() on the SDL window in my program?

This is what we use in Sid Meier’s Alpha Centauri:

However, I don’t recommend that you do this unless you absolutely have to.
This code won’t draw lines on the Linux console (or any other environment),
and breaks some Win32 X server implementations.

It would be better to find a general line implementation for the framebuffer.

Does the above gain you noticeable speed? I have been spending some
time thinking about this and think that it would be nice if SDL did
implement support for some low-level drawing routines using
accelerated functions like XDrawLine(s), XDrawRectable(s) in X, and
other such funcs on other OSs.

Of course it would only be worth implementing if it actually did
increase drawing speed. Looking at your code it seems like it might
not require a major backend rewrite. I thought, from looking at the
X11 backend code, that the below would cause a problem since you don’t
update the SDL pixmap. Is that incorrect?

Finally, I think that it would make sense to have hw accel primitives
like this with software fallbacks in SDL (I don’t think it’s outside
the scope of the lib).–
[ Below is a random fortune, which is unrelated to the above message. ]
micro:
Thinker toys.

Does the above gain you noticeable speed? I have been spending some
time thinking about this and think that it would be nice if SDL did
implement support for some low-level drawing routines using
accelerated functions like XDrawLine(s), XDrawRectable(s) in X, and
other such funcs on other OSs.

If thin lines are hardware accelerated, they are probably a fair bit
faster. XFillRectangle() even more so.

I doubt it is faster if you just want to draw a couple of thin lines,
but if you are doing vector graphics on a big scale it might pay off.
Also keep in mind that the lines are of low quality (no sub-pixel
placement, no anti-aliasing). If you render your own lines you can do
better, and today’s cpus are usually fast enough for that.

I thought, from looking at the
X11 backend code, that the below would cause a problem since you don’t
update the SDL pixmap. Is that incorrect?

No, that is right. Another problem is flicker (no double buffering).
So you have to know what you are doing or it won’t work well.

Finally, I think that it would make sense to have hw accel primitives
like this with software fallbacks in SDL (I don’t think it’s outside
the scope of the lib).

The above problems makes it tricky to do what you propose. Personally
I’d prefer a high-quality vector library that can render to any SDL
surface instead.

“Mattias Engdeg?rd” writes:

The above problems makes it tricky to do what you propose. Personally
I’d prefer a high-quality vector library that can render to any SDL
surface instead.

This would certainly be nicer. I will look at xmame sometime. an
anti-aliased vector graphics lib would be very nice. :slight_smile:

And yes, the flickering would be a potential problem that you don’t
get with todays SDL.–
[ Below is a random fortune, which is unrelated to the above message. ]
If you teach your children to like computers and to know how to gamble
then they’ll always be interested in something and won’t come to no real harm.

The above problems makes it tricky to do what you propose. Personally
I’d prefer a high-quality vector library that can render to any SDL
surface instead.
This would certainly be nicer. I will look at xmame sometime. an
anti-aliased vector graphics lib would be very nice. :slight_smile:

i have just recently started working with sdl, and am quite impressed!

we have been working on a small antialiased graphics primitive library for
sdl (but it is sufficiently generic to be used with any framebuffer system
without significant modification). currently it only does antialiased
line segments and (standard) box outlines and fills. it also
theoretically calculates alpha correctly.

it has so far been used internally, though i can release it under gpl and
write more routines for it as requested, if anyone is interested. please
let me know and i’ll do this as soon as possible.

i do not have a particularly large amount of time to code this, though i
would be glad to manage and host the project and contribute what i can. i
just don’t want to be redundant (do any such libraries currently exist?
freshmeat and the libsdl.org don’t seem to list any…).

thanks,
steve