Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
82 user(s) are online (77 user(s) are browsing Forums)

Members: 1
Guests: 81

Primax, more...

Support us!

Headlines

 
  Register To Post  

Help with GUI programming
Just popping in
Just popping in


See User information
Hi all

I've got a few programming questions. I'm currently building a visualization app in C on OS 3.9 (and OS 4 once I get an X1000).

1. I've seen how you can double-buffer the screen's display using two bitmaps, can the same approach be used to double-buffer a window's display? If so, do the bitmaps need to be the size of the screen,

2. I'm currently using Reaction for the GUI and have installed a hook so that you can drag and drop files onto the window. These are then processed and loaded. I noticed that for MUI with a similar approach using hooks that you can't draw from this process, instead you use the MUIM_Draw method. Does Reaction have a similar restriction.

3. Since I'm using calls such as AreaEllipse () and Flood (), I'm setting up the TmpRas buffer. Will this work on both native and rtg displays or would it be better to have a completely separate set of routines that use Picasso96?

cheers

billy

Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
1. There are LOTS of ways to double-buffer a screen, so it is difficult to know which one you talk about. You can certainly draw to an off-screen buffer, and then copy that to the window... however I doubt that will work with Intuition-based GUIs.

Author of the PortablE programming language.
Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
Essentially I'm drawing a 3d diagram into the Window's RastPort and then the user can rotate, scale or translate the display. The code I had in mind was John Kennedy's from his Amiga Format tutorial where he has two bitmaps and flips between them

if (which_screen)
{
myscreen->RastPort.BitMap=bitmapA;
myscreen->ViewPort.RasInfo->BitMap=bitmapA;
}
else
{
myscreen->RastPort.BitMap=bitmapB;
myscreen->ViewPort.RasInfo->BitMap=bitmapB;
}

rastport=&myscreen->RastPort;
which_screen = !which_screen;

Would using similar code to above but replacing the Screen's RastPort with the Window's RPort instead?

Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
@ChrisH
Quote:

You can certainly draw to an off-screen buffer, and then copy that to the window... however I doubt that will work with Intuition-based GUIs.


why not?

Reserve an area of the window with a space.gadget and copy the render into that. Worked in AWeb (very well under OS3.x and with a few glitches that needed fixing in OS4)

If things get too complex you can always write your own gadget (sketchbook now uses a private class for this)



Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
@billyfish

Quote:

Would using similar code to above but replacing the Screen's RastPort with the Window's RPort instead?

No, for several reasons, you mustn't mess with the windows bit / rastport like that things will break very quickly!


You should allocate a friend bitmap that the same dimensions as the window (or the area of the window you want to draw into) then create a layer that mimics the window then render into that layers rastport, then blit from that rastport inot the windows rastport.

Here's the code from AWeb

static struct RastPort *Alloctemprp(struct RastPort *rp)

{

   
struct Layer_Info *li;
   
struct Layer *l;
   
struct BitMap *tempbm;
   
ULONG bmwidthbmheightbmdepth;

   
bmwidth  GetBitMapAttr(rp->BitMap,BMA_WIDTH);
   
bmheight GetBitMapAttr(rp->BitMap,BMA_HEIGHT);
   
bmdepth  GetBitMapAttr(rp->BitMap,BMA_DEPTH);

   if(
tempbm AllocBitMap(bmwidth,bmheight,bmdepth,BMF_MINPLANES,rp->BitMap))
   {
       if (
rp && rp->Layer)
       {
          if ((
li NewLayerInfo()) != NULL)
          {
              if ((
CreateUpfrontHookLayer(li,
                                             
tempbm,
                                             
rp->Layer->bounds.MinX,
                                             
rp->Layer->bounds.MinY,
                                             
rp->Layer->bounds.MaxX,
                                             
rp->Layer->bounds.MaxY,
                                             
LAYERSIMPLE,
                                             
LAYERS_NOBACKFILL,
                                             
NULL)) != NULL)
             {
                
InstallLayerHook(l,(struct Hook *)rp->Layer->BackFill);
                return (
l->rp);
             }
             
DisposeLayerInfo(li);
          }
       }
       
FreeBitMap(tempbm);
   }
   return (
NULL);
}

static 
void Freetemprp(struct RastPort *rp)
{
    
struct Layer_Info *li;
    
struct BitMap *bm NULL;
    if(
rp)
    {
        
bm rp->BitMap;
    }
    if (
rp && rp->Layer)
    {
       
li rp->Layer->LayerInfo;
//       InstallLayerInfoHook(li,LAYERS_NOBACKFILL);
       
InstallLayerHook(rp->Layer,LAYERS_NOBACKFILL);
       
DeleteLayer(0,rp->Layer);
       
DisposeLayerInfo(li);
    }
    if(
bm)
    {
        
FreeBitMap(bm);
    }
}


Then blit from the temp into the windows rastport using ClipBlit() check autodocs for more info.




Go to top
Re: Help with GUI programming
Amigans Defender
Amigans Defender


See User information
@billyfish

Quote:

2. I'm currently using Reaction for the GUI and have installed a hook so that you can drag and drop files onto the window. These are then processed and loaded. I noticed that for MUI with a similar approach using hooks that you can't draw from this process, instead you use the MUIM_Draw method. Does Reaction have a similar restriction.


Why are you using a hook for drag'n'drop? Just register the window as an AppWindow (window.class can even do this for you IIRC) and get events via the usual method. Definitely no problems with rendering this way. I didn't even know it was possible to create a hook for drop events...

Quote:

3. Since I'm using calls such as AreaEllipse () and Flood (), I'm setting up the TmpRas buffer. Will this work on both native and rtg displays or would it be better to have a completely separate set of routines that use Picasso96?


That will work fine, and it is recommended to use graphics.library rather than P96 directly.

@broadblues

Quote:
Reserve an area of the window with a space.gadget and copy the render into that. Worked in AWeb (very well under OS3.x and with a few glitches that needed fixing in OS4)


NetSurf does exactly the same thing, and I believe RA-OWB does too.

Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
@chris
Quote:

Why are you using a hook for drag'n'drop? Just register the window as an AppWindow (window.class can even do this for you IIRC) and get events via the usual method. Definitely no problems with rendering this way. I didn't even know it was possible to create a hook for drop events...


I probably explained it badly, I followed trixie's example from os4coding (http://www.os4coding.net/blog/trixie/ ... ppwindows-and-appmessages). I set WINDOW_AppMsgHook to a struct Hook pointer that had its h_Entry set to my function. Is there a better way of doing it?

@broadblues

Thanks for the code, that's really useful.

Thanks to both of you with the heads up about the space.gadget as well, I'll give it a look.

Go to top
Re: Help with GUI programming
Amigans Defender
Amigans Defender


See User information
@billyfish

Quote:
I probably explained it badly, I followed trixie's example from os4coding (http://www.os4coding.net/blog/trixie/ ... ppwindows-and-appmessages). I set WINDOW_AppMsgHook to a struct Hook pointer that had its h_Entry set to my function. Is there a better way of doing it?


That's a window.class specific, I've never used it and couldn't tell you whether it is safe to manipulate the window within that function (if I had to guess, I'd say it's probably OK)

The way I do it (and whether it is better or not is a matter of opinion; it's the old-fashioned way), is add the following two tags to the window.class object:

WINDOW_AppPort, appport
WINDOW_AppWindow,TRUE

Where "appport" is a pointer to a MsgPort.

You can collect messages arriving at appport in your main event loop, check for appmsg->am_Type == AMTYPE_APPWINDOW (exactly the same code as in the hook function, as far as I can tell)

Go to top
Re: Help with GUI programming
Amigans Defender
Amigans Defender


See User information
@billyfish

Quote:
I set WINDOW_AppMsgHook to a struct Hook pointer that had its h_Entry set to my function. Is there a better way of doing it?

My information is correct, this is the preferred way to handle AppMessages in windows created through window.class. I specifically asked Steven Solie about this one.

What Chris describes would require catching and processing the AppMessage before you call the WM_HANDLEINPUT method. Yes, this technique works, was used before and is found in at least one example in the OS4 SDK - the example is wrong on that, I was told.

Remember that drag'n'drop messages are not the only AppMessages the window can receive: uniconification also sends one. So if you decide to process AppMessages before you go into the WM_HANDLEINPUT loop, you must process all AppMessages there, including uniconification.

This creates mess, as window iconification is handled within the WM_HANDLEINPUT loop (after receiving WMHI_ICONIFY) and uniconification is processed elsewhere (WMHI_UNICONIFY cannot be used because the message never arrives when WM_HANDLEINPUT kicks in).

The idea is to process all "usual" window-related events (gadget selections, menu picks, keyboard presses, iconification/uniconification ...) in one place through WM_HANDLEINPUT, and all "extensions" (drag'n'drop messages, special IDCMP messages) through hooks.

The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
Quote:

billyfish wrote:
@chris

I probably explained it badly, I followed trixie's example from os4coding (http://www.os4coding.net/blog/trixie/ ... ppwindows-and-appmessages). I set WINDOW_AppMsgHook to a struct Hook pointer that had its h_Entry set to my function. Is there a better way of doing it?


Why not ask for help on os4coding.net? It is, after all, a website set up specifically for AmigaOS 4.x development.

Hans

Join Kea Campus' Amiga Corner and support Amiga content creation
https://keasigmadelta.com/ - see more of my work
Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
1 .Broadblues is right.

No, there is no such thing like double buffering for windows. And you also dont want to flip the bitmaps, that makes only sence if the bitmap pointers are exchanged synched with the vblank, like on OCS/AGA possible.

Nowadays, you still have 2 bitmaps, but one is for rendering, and once done, you blit it to the window. That kind of double buffering, but better called "off-screen" bitmap or "off-screen" rendering. The blit to the window should be fast. After some tests I came to the conclusion that P96 also does the same thing with screen bitmaps, even if you "think" you would swap the bitmaps, it actually copies the bitmaps.

So what you do is allocateing a friend bitmap, create a rastport and layer on it (CreateUpFrontLayer) and draw there, once done, blit it to the windows rastport.
Doing it that way, the window doesnt even need its own bitmap, it can be simple refresh, that saves you some memory.

2. You dont need hooks for that. You can get app events though a MessagePort.

3. I remember lots of trouble with Flood. I would write my own drawing routines. If you know the shape of the area you want to fill, you can do it faster with lines anyway.



Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
Quote:

Wanderer wrote:
... After some tests I came to the conclusion that P96 also does the same thing with screen bitmaps, even if you "think" you would swap the bitmaps, it actually copies the bitmaps.


That's not true. P96 does proper full-screen double-buffering. Using ChangeScreenBuffer() flips the surfaces by swapping screen bitmap pointers.

Hans

Join Kea Campus' Amiga Corner and support Amiga content creation
https://keasigmadelta.com/ - see more of my work
Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
This is my conclusion after extensive speed tests.

I have tried

#flip_scrollvp  = 0   ; use ScrollVP()
#flip_bltbmap   = 1   ; blit bitmaps via BltBmapRastPort()
#flip_none      = 2   ; no dbl
#flip_smart     = 3   ; use seletive blit via BltBmapRastPort and Queue()
#flip_changebmap= 4   ; use ChangeVPBitMap()
#flip_scrbuff   = 5   ; use ChangeScreenBuffer()


..and sadly enough, BlitBmapRastPort with an off-screen bitmap is the fastest (apart from single buffering of course), but all are in comparable ranges.
That lead me to the conclusion that P96 actually doesn't change pointers, but does a full-screen blit too. It might not be P96 directly, but at least the driver does it that way. I have tested WinUAE, Amithlon and Cyberision 64 3D on a Classic.
That doesnt mean that there is still a huge difference for OCS/AGA. But all RTG Systems I have tried are not faster than blitting the Bitmap, and even more sadly, they dont do vblank sync anyway.



Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
@Hans
Quote:

Why not ask for help on os4coding.net? It is, after all, a website set up specifically for AmigaOS 4.x development.


Although I aim to make an OS 4 native version once I've got an X1000, it's currently an OS 3 app.

cheers

Billy

Go to top
Re: Help with GUI programming
Amigans Defender
Amigans Defender


See User information
Quote:

trixie wrote:
@billyfish
What Chris describes would require catching and processing the AppMessage before you call the WM_HANDLEINPUT method.


Erm, why? The message port and signal is completely separate to the window's, there is no need to call WM_HANDLEINPUT until a message arrives at the window's message port.

Quote:

Remember that drag'n'drop messages are not the only AppMessages the window can receive: uniconification also sends one. So if you decide to process AppMessages before you go into the WM_HANDLEINPUT loop, you must process all AppMessages there, including uniconification.


Uniconification sends a message to the window's message port I believe, not the AppMessage port.

Due to implementation issues, I always find myself manually adding AppIcons and handling (un)iconification myself though.

Quote:
The idea is to process all "usual" window-related events (gadget selections, menu picks, keyboard presses, iconification/uniconification ...) in one place through WM_HANDLEINPUT, and all "extensions" (drag'n'drop messages, special IDCMP messages) through hooks.


Special IDCMP messages you have to do through hooks, same with mouse wheel events IIRC.

Go to top
Re: Help with GUI programming
Amigans Defender
Amigans Defender


See User information
@chris

Quote:

Uniconification sends a message to the window's message port I believe, not the AppMessage port.

No, it doesn't. This is why you need to create an AppPort and pass it in WINDOW_AppPort, to make iconification/uniconification work. (The window.class here merely wraps around the workbench.library AppMessage API, which also needs an AppPort.)

Quote:

I always find myself manually adding AppIcons and handling (un)iconification myself though.

Which works but is not recommened for ReAction-based windows - that's all I'm trying to say.

Quote:

Special IDCMP messages you have to do through hooks, same with mouse wheel events IIRC.

Yes, that's correct. All GUI events not "supported" by WM_HANDLEINPUT (ie. those that have no WMHI_XYZ defined) must be processed through hooks. Including AppMessages - to make event handling logical, consistent and transparent.

The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
Go to top
Re: Help with GUI programming
Home away from home
Home away from home


See User information
Quote:

Wanderer wrote:
This is my conclusion after extensive speed tests.

I have tried

#flip_scrollvp  = 0   ; use ScrollVP()
#flip_bltbmap   = 1   ; blit bitmaps via BltBmapRastPort()
#flip_none      = 2   ; no dbl
#flip_smart     = 3   ; use seletive blit via BltBmapRastPort and Queue()
#flip_changebmap= 4   ; use ChangeVPBitMap()
#flip_scrbuff   = 5   ; use ChangeScreenBuffer()


..and sadly enough, BlitBmapRastPort with an off-screen bitmap is the fastest (apart from single buffering of course), but all are in comparable ranges.
That lead me to the conclusion that P96 actually doesn't change pointers, but does a full-screen blit too. It might not be P96 directly, but at least the driver does it that way. I have tested WinUAE, Amithlon and Cyberision 64 3D on a Classic.


No, the driver doesn't do it that way. At least on AmigaOS 4 it doesn't. I can confirm this in two ways:
- Monitoring the calls made to my RadeonHD driver, Picasso96 tells the driver switch the screen bitmap pointers; and
- I have seen the code for Picasso96's patched ChangeVPBitMap() code, and it flips the buffers by switching the bitmap pointers.

I don't know how you're trying to measure this operation, but it true full-screen double-buffering is used.

Hans


Edited by Hans on 2012/1/31 20:23:45
Join Kea Campus' Amiga Corner and support Amiga content creation
https://keasigmadelta.com/ - see more of my work
Go to top
Re: Help with GUI programming
Just popping in
Just popping in


See User information
I have mesured it by observing the frames-per-second with various amounts of object moving on the screen.

I dont know exact numbers anymore, but the numbers were something like this: (using smart object refreshing, not full screen refresh, means I did not restore the background with a full screen blitbitmap, I restored only regions that have been damaged, which is very fast if there are only few and small objects)

0 Objects:
1. single buffering ~ >> 100000 FPS (hard to messure)
2. blitbitmap ~ 500 FPS
3. ChangeScreenBuffer ~ 490 FPS

100 Objects:
1. single buffering ~ 50 FPS
2. blitbitmap ~ 40 FPS
3. ChangeScreenBuffer ~ 40 FPS

The conculsion is, that single buffering has almost no overhead (obviously), while blitbitmap and ChangescreenBuffer have suspiciously similar overhead. If ChangeScreenBuffer would just change the pointer, one would asume an overhead close to single buffering, not close to a full-screen bitmap swap.

And as you see, I have not only tried ChangeScreenBuffer(), also the lower-leveled ChangeVPBitmap() and ScrollVP(), all have performance in a very similar range. I was even desperate enough to try an auto-scroll oversized screen with double height and scrolled it, but that was ridicously slow.

If this is interesting topic for anyone, I could provide a demo with all those methods and you can run this on your Amiga to see the performance. But I have done this before, I doubt you will generate different results.


Go to top

  Register To Post

 




Currently Active Users Viewing This Thread: 1 ( 0 members and 1 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2024 The XOOPS Project