LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: cfmdobbie on August 23, 2003, 10:18:32

Poll
Question: Are you using hardware cursors?
Option 1: Yes votes: 4
Option 2: No votes: 4
Option 3: Wha? votes: 7
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 10:18:32
I'm a little confused as to how hardware cursors are used, and unfortunately the example doesn't help much!  Stuff like:

int color_scale = 255/Mouse.getMaxCursorSize();
int bit_mask = 0x81000000;
for (int j = 0; j < image_size; j++) {
   if (j % 4 == 0)
       bit_mask = (~bit_mask) & 0x81000000;
   int color = (j*color_scale/Mouse.getMaxCursorSize()) << 16;
   cursor_images.put(0*image_size + j, 0x00000020 | color | bit_mask);
}


From what I can tell this is doing funky graphical effects, which is great for a demo but sucks as an example! :P  Does anyone have a *simple* example - black and white, one bit transparency, three-line arrow kind of thing?


And now a few questions: The constructor takes an IntBuffer, and as far as I can tell it contains RGBA bytes packed into ints.  Why is this done, as opposed to using a ByteBuffer? *confused*

The hardware cursor starts at (0, 0), and you then track state by polling and storing your own opinion as to where the mouse is.  Doesn't this allow for cursor drift - i.e. getting out of sync with reality?  I understand in the world of dx/dy that you keep track of the position yourself, but in that situation you're drawing the cursor and acting on its position yourself.  If you relinquish control of the first bit, you really need help with the second, don't you?

Is there any way of repositioning the native cursor?


Right, enough whinging, back to the coal face...
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 23, 2003, 10:57:32
I might be the only one really using the native cursor (and the implementor), so here goes (there is some information in the Cursor javadocs too):

1. The IntBuffer thing was the most convenient for me, seeing that I only wanted to support that one pixle format (RGBA)

2. The native layer will not allow for drifting because it knows which (dx, dy) to return to get you to match the native cursor position. So as long as you start in (0, 0) everything will be fine

3. No repositioning (yet?).

Sorry about the cryptic "example", which is more precisely described as a stress test to check if everything is working correctly, without an accompanying image. Creating your own should be relatively easy, in fact the pixel format matches that of RGBA textures, and 0, 0 is the lower left corner of the cursor. Be sure to bug me about confusing details, though.

NOTE: If translucency is unsupported (win32), use 0xFF for opaque pixels, and 0x00 for transparent pixels. That way it will work on linux too.

- elias
Title: Hardware Cursors (0.7-pre2)
Post by: spasi on August 23, 2003, 11:44:53
Besides no repositioning, there's no way you can hide the native cursor, am I right? That would be the second reason why I'm not using it.
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 11:51:34
Quote from: "elias"1. The IntBuffer thing was the most convenient for me, seeing that I only wanted to support that one pixle format (RGBA)
Ah, hokay.  (Sorry, my mistake - it's ARGB format, not RGBA :oops:)

Quote from: "elias"2. The native layer will not allow for drifting because it knows which (dx, dy) to return to get you to match the native cursor position. So as long as you start in (0, 0) everything will be fine
Hrm.  God forbid you ever forget an update.

Missing a keyboard event is one thing - the user can just press the key again (harder this time :wink:), missing a mouse click isn't a disaster either.  But if you ever forget a movement update (e.g. bad code path) you'll spend the rest of the application with the user clicking half an inch below the mouse cursor.  With no way of knowing... :?  I guess if you're careful it shouldn't be a problem, but it'd be a git to debug! :D

Quote from: "elias"3. No repositioning (yet?).
It's probably no biggie, but always starting the cursor at (0, 0) is a bit icky - it's initially not visible and I've seen people never realise there's mouse support because they couldn't see a cursor...  :roll: :wink:  But you gotta choose somewhere and that's as good as any.

Quote from: "elias"Sorry about the cryptic "example", which is more precisely described as a stress test to check if everything is working correctly, without an accompanying image. Creating your own should be relatively easy, in fact the pixel format matches that of RGBA textures, and 0, 0 is the lower left corner of the cursor. Be sure to bug me about confusing details, though.
Righto, after a bit of playing I'm sure I'll get it working.

...But which leads me on to another question - is there a "nice" way of converting ByteBuffers into packed IntBuffers, RGB into RGBA, RGBA into ARGB etc?  I just can't think of any way of converting pixel formats that doesn't involve the kind of thing I've already got, which is similar to:

if(oldFormat == GL.GL_RGB && newFormat == GL.GL_RGBA) {
 ...
} else if(oldFormat == GL.GL_RGB && newFormat == GL.GL_LUMINANCE) {
 ...
} else if(...


Quote from: "elias"NOTE: If translucency is unsupported (win32), use 0xFF for opaque pixels, and 0x00 for transparent pixels. That way it will work on linux too.
Righto - a good tip!  As for other general guidelines for doing this sort of thing, are hardware cursors well supported - is it a graphics card thing or an operating system thing?  Should we worry "too much" about the native maximum cursor sizes, or is an assumption that 32x32 is supported for most people fair?

Thanks for your response.
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 11:52:28
Quote from: "spasi"Besides no repositioning, there's no way you can hide the native cursor, am I right? That would be the second reason why I'm not using it.

Hmmm.  Aside from a transparent Cursor? :?:  Should work fine.
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 11:55:58
Quick thought on "cursor drift" - if you know you're in full-screen using native cursors, then you can take advantage of the fact that the cursor keeps within the screen and if your tracking coordinates go out of bounds just adjust them a little.  Voila!  Instant calibration! :D

If a user's cursor starts behaving oddly, the first thing most of them will probably do is waggle it violently anyway. ;)
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 23, 2003, 12:21:25
32*32 is a good assumption, because that's the only size win32 supports... Regarding hardware support, I'm not really the authority here. I use Geforce and it just works. And I've seen many main stream games use it (C&C Generals is the latest). My guess is that with reasonably recent hw you'll be allright. However, on linux you'll need a recent X server (>4.3) to display native cursors, as the capabilities field will tell you. In any case a software fallback is a must.

Packing a ByteBuffer into an IntBuffer should be as easy as an asIntBuffer() if you have the pixel data in native byte ordering. Other than that, I'm not really sure if it can be done easier.

Yes, a fully transparent cursor is the way to hide it (even AWT does it that way).

Yeah, missing an update is catastrophic, and has caught me more than once... I'm not sure how to make it more robust without having a query for the absolute cursor position.

- elias
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 13:18:36
Quote from: "elias"In any case a software fallback is a must.
Ah well, I was hoping I'd be able to do away with all that nastiness.  Well, the advantages are such that it's worth including anyway, just in case.

QuotePacking a ByteBuffer into an IntBuffer should be as easy as an asIntBuffer() if you have the pixel data in native byte ordering. Other than that, I'm not really sure if it can be done easier.
Funny you should say that.  When I tried it with an already existing filled ByteBuffer it seemed to return me a 0-length IntBuffer (not much use).  I'm not totally sure of that, as I haven't explored it further, but that's what it seemed. :?

QuoteYes, a fully transparent cursor is the way to hide it (even AWT does it that way).
And from the javadocs you can disable the hardware cursor (sorry, should be calling it a native cursor!) by calling setNativeCursor(null).

QuoteYeah, missing an update is catastrophic, and has caught me more than once... I'm not sure how to make it more robust without having a query for the absolute cursor position.
Nothing apart from that! :wink:

Hrm.  A little worrying entry in the javadoc for setNativeCursor:

* NOTE: The native cursor is not constrained to the window, but
* relative events will not be generated if the cursor is outside.


Are they practically unusuable in windowed mode then?  Or do you automatically catch up by virtue of the fact that the first mouse update you receive after the mouse reenters the window is the difference from the last known position, not the last actual position?

EDIT: Hrm, it's gotta be that hasn't it?  What else can Mouse.poll() do? :roll:  Ignore me!
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 23, 2003, 13:36:19
Did you remember to rewind to ByteBuffer before you converted it to an IntBuffer?

- elias
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 13:44:06
Hmm.  Possibly not!  I guess a lot of Buffer ops depend on position and limit then?
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 23, 2003, 13:53:11
If that's the case, you might be in a few more surprises - LWJGL noW uses position() and limit() where applicable.

- elias
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 23, 2003, 14:12:57
Yeah, I've picked up on them (see the "Prerelease 2 of LWJGL 0.7" thread), but I didn't think about things like asIntBuffer() using them.

Time for revising Buffer usage methinks!
Title: Hardware Cursors (0.7-pre2)
Post by: spasi on August 23, 2003, 14:55:07
When I set a hardware cursor there's a nasty bug when I have dual displays enabled. I've seen it in many commercial games too (e.g. Age of Mythology). When you move the mouse to the screen edge it gets out of the main display and moves to the secondary. After that many BAD things can happen. This doesn't happen without a native cursor. So I wouldn't recommend using it, if possible. There are a lot of users with dual displays nowadays.
Title: Arrgh!
Post by: cfmdobbie on August 28, 2003, 20:56:58
Arrgh!  Okay, well I think I have a nice, simple native cursor implementation in my toolkit now, but it don't work. :(

My min and max cursor sizes are both 32 pixels, getNativeCursorCaps() includes CURSOR_ONE_BIT_TRANSPARANCY.  My image is the correct size (32x32), contains only 0x00 or 0xff alpha, and is loading and being converted to ARGB correctly.  However, the cursor as displayed contains no transparent sections and flickers once every frame, as if single-buffered.  (It is beautifully frame-rate independent though!)

Now, is this going to be due to LWJGL, WinME or my S3 Savage?  I would guess the Savage.  Ah well, another part of my toolkit to put aside for now.


By the way, CURSOR_ONE_BIT_TRANSPARANCY should be CURSOR_ONE_BIT_TRANSPARENCY.
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 29, 2003, 07:57:07
Could you test if the cursor works correctly in windowed mode? And does the lwjgl example work?

Fixed the spelling error, thnx.

- elias
Title: Hardware Cursors (0.7-pre2)
Post by: cfmdobbie on August 29, 2003, 10:33:55
Quote from: "elias"Could you test if the cursor works correctly in windowed mode? And does the lwjgl example work?

Nope, and nope!  In windowed mode I'm seeing exactly the same cursor as fullscreen - my white arrow, outlined in black and surrounded by a red square.  The example flickers madly in the same way as my own test - I don't know whether any of the example cursor is supposed to be transparent, but none of it appears to be, as far as I can tell.

Also, CURSOR_8_BIT_ALPHA and CURSOR_ANIMATION are not returned from getNativeCursorCaps() - is this expected?
Title: Hardware Cursors (0.7-pre2)
Post by: elias on August 29, 2003, 12:52:32
Yes, that is expected. Only linux supports real translucency and animation. I haven't found a way to load animated cursors from memory objects (an .ani file is needed(!)). I'm not happy about your cursor problem though. It really should work, especially in windowed mode.

Does AWT custom cursors work?

- elias