@asman, post #241
// init
struct MsgPort* disp = CreateMsgPort();
struct MsgPort* safe = CreateMsgPort();
struct Bitmap* bm1 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct Bitmap* bm2 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct Bitmap* bm3 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct ScreenBuffer* sb1 = AllocScreenBuffer(APP_screen, 0, SB_COPY_BITMAP );
struct ScreenBuffer* sb2 = AllocScreenBuffer(APP_screen, 0,SB_COPY_BITMAP );
struct ScreenBuffer* sb3 = AllocScreenBuffer(APP_screen, 0,SB_COPY_BITMAP );
sb1->sb_BitMap = bm1;
sb2->sb_BitMap = bm2;
sb3->sb_BitMap = bm3;
sb1->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb1->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;
sb2->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb2->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;
sb3->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb3->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;
// loop
int frame = 0;
LOOP
{
switch (frame)
{
case 0:
{
ChangeScreenBuffer(APP_screen, sb1);
APTR handle = LockBitMapTags(sb2->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr2, TAG_DONE);
UnLockBitMap(handle);
// engine output buffer and render
EM_prefs.output_buffer_32 = x_FBAddr2;
EM_Update_And_Render();
}
break;
case 1:
{
ChangeScreenBuffer(APP_screen, sb2);
APTR handle = LockBitMapTags(sb3->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr3, TAG_DONE);
UnLockBitMap(handle);
// engine output buffer and render
EM_prefs.output_buffer_32 = x_FBAddr3;
EM_Update_And_Render(&APP_main_loop);
}
break;
case 2:
{
ChangeScreenBuffer(APP_screen, sb3);
APTR handle = LockBitMapTags(sb1->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr1, TAG_DONE);
UnLockBitMap(handle);
// engine output buffer and render
EM_prefs.output_buffer_32 = x_FBAddr1;
EM_Update_And_Render(&APP_main_loop);
}
break;
}
frame++;
if (frame> 2)
frame= 0;
}@mateusz_s, post #242
@mateusz_s, post #242
// INICJALIZACJA
// create two message ports
struct MsgPort* APP_port_disp = CreateMsgPort();
struct MsgPort* APP_port_safe = CreateMsgPort();
// declare Screen Buffer structure
struct ScreenBuffer* APP_screen_buffer[3];
// first buffer - the bitmap won't be allocated - it will use screens bitmap
APP_screen_buffer[0] = AllocScreenBuffer(APP_screen, NULL, SB_SCREEN_BITMAP);
// second and third buffer - the bitmaps will be allocated
APP_screen_buffer[1] = AllocScreenBuffer(APP_screen, NULL, 0);
APP_screen_buffer[2] = AllocScreenBuffer(APP_screen, NULL, 0);
// for some reason AllocScreenBuffer() doesn't want to correct allocate BitMap for it - so we doing this manually for Screen Buffers 1 and 2.
struct BitMap* bitmap_1 = AllocBitMap(320,200,32,BMF_DISPLAYABLE , &APP_screen->BitMap );
FreeBitMap(APP_screen_buffer[1]->sb_BitMap);
APP_screen_buffer[1]->sb_BitMap = bitmap_1;
struct BitMap* bitmap_2 = AllocBitMap(320,200,32,BMF_DISPLAYABLE , &APP_screen->BitMap );
FreeBitMap(APP_screen_buffer[2]->sb_BitMap);
APP_screen_buffer[2]->sb_BitMap = bitmap_2;
// link with message ports
for (int i = 0; i < 3; i++)
{
APP_screen_buffer[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = APP_port_disp;
APP_screen_buffer[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = APP_port_safe;
}
// init buffer switcher
int APP_current_frame_buffer = 1;
int APP_next_frame_buffer = 2;
// PETLA
while (APP_main_loop)
{
if (ChangeScreenBuffer(APP_screen, APP_screen_buffer[APP_current_frame_buffer]))
{
// increment APP_current_frame_buffer
APP_current_frame_buffer++;
if (APP_current_frame_buffer > 2) APP_current_frame_buffer = 0;
}
APTR handle = LockBitMapTags(APP_screen_buffer[APP_next_frame_buffer]->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&EM_prefs.output_buffer_32, TAG_DONE);
if (handle)
{
EM_Update_And_Render(&APP_main_loop);
// increment APP_next_frame_buffer
APP_next_frame_buffer++;
if (APP_next_frame_buffer > 2) APP_next_frame_buffer = 0;
}
UnLockBitMap(handle);
} @asman, post #241
@teh_KaiN, post #245
@Don_Adan, post #246
@asman, post #247
/* :ts=8
* doublebuffer.c - shows double-buffering, attached screens, menu lending
*
* (c) Copyright 1992 Commodore-Amiga, Inc. All rights reserved.
*
* This software is provided as-is and is subject to change; no warranties
* are made. All use is at your own risk. No liability or responsibility
* is assumed.
*
* Example shows use of V39 double-buffering functions to achieve
* 60 frame-per-second animation. Also shows use of menus in
* double-buffered screens, and the use of attached screens with
* menu-lending to achieve the appearance of slider gadgets in
* double-buffered screens.
*
*/
/*----------------------------------------------------------------------*/
#include <exec/types.h>
#include <graphics/displayinfo.h>
#include <intuition/intuition.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/Picasso96.h>
#include <stdio.h>
#include <stdlib.h>
/*----------------------------------------------------------------------*/
STRPTR init_all( void );
void error_exit( STRPTR errorstring );
BOOL handleIntuiMessage( struct IntuiMessage *imsg );
void handleDBufMessage( struct Message *dbmsg );
ULONG handleBufferSwap( void );
struct BitMap *makeImageBM( void );
void CloseWindowSafely( struct Window *win );
int CXBRK( void ) {return( 0 );}
/*----------------------------------------------------------------------*/
/* Some constants to handle the rendering of the animated face */
#define BM_WIDTH 80
#define BM_HEIGHT 80
#define BM_DEPTH 2
/* Odd numbers to give a non-repeating bounce */
ULONG SC_ID = INVALID_ID;
/*----------------------------------------------------------------------*/
UWORD pens[] =
{
0, /* DETAILPEN */
1, /* BLOCKPEN */
1, /* TEXTPEN */
2, /* SHINEPEN */
1, /* SHADOWPEN */
3, /* FILLPEN */
1, /* FILLTEXTPEN */
0, /* BACKGROUNDPEN */
2, /* HIGHLIGHTTEXTPEN */
1, /* BARDETAILPEN */
2, /* BARBLOCKPEN */
1, /* BARTRIMPEN */
(UWORD)~0,
};
struct Screen *canvassc = NULL;
struct Window *canvaswin = NULL;
/*----------------------------------------------------------------------*/
#define OK_REDRAW 1 /* Buffer fully detached, ready for redraw */
#define OK_SWAPIN 2 /* Buffer redrawn, ready for swap-in */
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct MsgPort *dbufport = NULL;
struct MsgPort *userport = NULL;
struct ScreenBuffer *scbuf[] = { NULL, NULL };
struct RastPort rport[2];
ULONG status[2];
LONG prevx[2] = { 50, 50 };
LONG prevy[2] = { 50, 50 };
ULONG buf_current, buf_nextdraw, buf_nextswap;
ULONG count;
struct BitMap *face = NULL;
LONG x, y, xstep, xdir, ystep, ydir;
/*----------------------------------------------------------------------*/
main()
{
STRPTR errorstring;
ULONG sigs;
BOOL terminated = FALSE;
SC_ID = p96RequestModeIDTags(TAG_DONE);
/* Let's get everything initialized */
if ( errorstring = init_all()){
error_exit( errorstring );
}
count = 0;
buf_current = 0;
buf_nextdraw = 1;
buf_nextswap = 1;
sigs = 0;
while ( !terminated )
{
/* Check for and handle any IntuiMessages */
if(sigs & (1 << userport->mp_SigBit)){
struct Message *imsg;
while(imsg = GetMsg(userport)){
terminated |= handleIntuiMessage((struct IntuiMessage *)imsg);
ReplyMsg(imsg);
}
}
/* Check for and handle any double-buffering messages.
* Note that double-buffering messages are "replied" to
* us, so we don't want to reply them to anyone.
*/
if(sigs & (1 << dbufport->mp_SigBit)){
struct Message *dbmsg;
while(dbmsg = GetMsg(dbufport)){
handleDBufMessage(dbmsg);
}
}
if ( !terminated )
{
ULONG held_off = 0;
/* Only handle swapping buffers if count is non-zero */
if ( count )
{
held_off = handleBufferSwap();
}
if ( held_off )
{
/* If were held-off at ChangeScreenBuffer() time, then we
* need to try ChangeScreenBuffer() again, without awaiting
* a signal. We WaitTOF() to avoid busy-looping.
*/
WaitTOF();
}
else
{
/* If we were not held-off, then we're all done
* with what we have to do. We'll have no work to do
* until some kind of signal arrives. This will normally
* be the arrival of the dbi_SafeMessage from the ROM
* double-buffering routines, but it might also be an
* IntuiMessage.
*/
sigs = Wait( ( 1 << dbufport->mp_SigBit ) | ( 1 << userport->mp_SigBit ) );
}
}
}
error_exit( NULL );
}
/*----------------------------------------------------------------------*/
/* Handle the rendering and swapping of the buffers */
ULONG handleBufferSwap( void )
{
ULONG held_off = 0;
/* 'buf_nextdraw' is the next buffer to draw into.
* The buffer is ready for drawing when we've received the
* dbi_SafeMessage for that buffer. Our routine to handle
* messaging from the double-buffering functions sets the
* OK_REDRAW flag when this message has appeared.
*
* Here, we set the OK_SWAPIN flag after we've redrawn
* the imagery, since the buffer is ready to be swapped in.
* We clear the OK_REDRAW flag, since we're done with redrawing
*/
if ( status[ buf_nextdraw ] == OK_REDRAW )
{
x += xstep*xdir;
if ( x < 0 )
{
x = 0;
xdir = 1;
}
else if ( x > canvassc->Width - BM_WIDTH )
{
x = canvassc->Width - BM_WIDTH - 1;
xdir = -1;
}
y += ystep*ydir;
if ( y < canvassc->BarLayer->Height )
{
y = canvassc->BarLayer->Height;
ydir = 1;
}
else if ( y >= canvassc->Height - BM_HEIGHT )
{
y = canvassc->Height - BM_HEIGHT - 1;
ydir = -1;
}
/*
SetAPen( &rport[ buf_nextdraw ], 0 );
RectFill( &rport[ buf_nextdraw ],
prevx[ buf_nextdraw ], prevy[ buf_nextdraw ],
prevx[ buf_nextdraw ] + BM_WIDTH - 1, prevy[ buf_nextdraw ] + BM_HEIGHT - 1 );
*/
prevx[ buf_nextdraw ] = x;
prevy[ buf_nextdraw ] = y;
BltBitMapRastPort(face, 0, 0, &rport[buf_nextdraw], x, y, BM_WIDTH, BM_HEIGHT, 0xc0);
// WaitBlit(); /* Gots to let the BBMRP finish */
status[ buf_nextdraw ] = OK_SWAPIN;
/* Toggle which the next buffer to draw is.
* If you're using multiple ( >2 ) buffering, you
* would use
*
* buf_nextdraw = ( buf_nextdraw+1 ) % NUMBUFFERS;
*
*/
buf_nextdraw ^= 1;
}
/* Let's make sure that the next frame is rendered before we swap...
*/
if ( status[ buf_nextswap ] == OK_SWAPIN )
{
scbuf[ buf_nextswap ]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = dbufport;
if ( ChangeScreenBuffer( canvassc, scbuf[ buf_nextswap ] ) )
{
status[ buf_nextswap ] = 0;
buf_current = buf_nextswap;
/* Toggle which the next buffer to swap in is.
* If you're using multiple ( >2 ) buffering, you
* would use
*
* buf_nextswap = ( buf_nextswap+1 ) % NUMBUFFERS;
*
*/
buf_nextswap ^= 1;
count--;
}
else
{
held_off = 1;
}
}
return( held_off );
}
/*----------------------------------------------------------------------*/
/* Handle Intuition messages */
BOOL handleIntuiMessage( struct IntuiMessage *imsg )
{
UWORD code = imsg->Code;
BOOL terminated = FALSE;
switch ( imsg->Class )
{
case IDCMP_VANILLAKEY:
switch ( code )
{
case 'S':
case 's':
count = 1;
break;
case 'R':
case 'r':
count = ~0;
break;
case 'Q':
case 'q':
count = 0;
terminated = TRUE;
break;
}
break;
}
return( terminated );
}
/*----------------------------------------------------------------------*/
void handleDBufMessage( struct Message *dbmsg )
{
ULONG buffer;
/* dbi_SafeMessage is followed by an APTR dbi_UserData1, which
* contains the buffer number. This is an easy way to extract
* it.
* The dbi_SafeMessage tells us that it's OK to redraw the
* in the previous buffer.
*/
buffer = ( ULONG ) *( ( APTR ** ) ( dbmsg+1 ) );
/* Mark the previous buffer as OK to redraw into.
* If you're using multiple ( >2 ) buffering, you
* would use
*
* ( buffer + NUMBUFFERS - 1 ) % NUMBUFFERS
*
*/
status[ buffer^1 ] = OK_REDRAW;
}
/*----------------------------------------------------------------------*/
/* Get the resources and objects we need */
STRPTR init_all( void )
{
if ( !( GfxBase = ( struct GfxBase * )
OpenLibrary( "graphics.library", 39L ) ) )
{
return( "Couldn't open Gfx V39\n" );
}
if ( !( IntuitionBase = ( struct IntuitionBase * )
OpenLibrary( "intuition.library", 39L ) ) )
{
return( "Couldn't open Intuition V39\n" );
}
if ( !( dbufport = CreateMsgPort() ) )
{
return( "Failed to create port\n" );
}
if ( !( userport = CreateMsgPort() ) )
{
return( "Failed to create port\n" );
}
if ( !( canvassc = OpenScreenTags( NULL,
SA_DisplayID, SC_ID,
SA_Overscan, OSCAN_TEXT,
SA_Depth, 2,
SA_AutoScroll, 1,
SA_Pens, pens,
SA_ShowTitle, TRUE,
SA_Title, "Intuition double-buffering example",
SA_SysFont, 1,
TAG_DONE ) ) )
{
return( "Couldn't open screen\n" );
}
if ( !( canvaswin = OpenWindowTags( NULL,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
WA_Borderless, TRUE,
WA_Backdrop, TRUE,
WA_CustomScreen, canvassc,
WA_NewLookMenus, TRUE,
TAG_DONE ) ) )
{
return( "Couldn't open window\n" );
}
canvaswin->UserPort = userport;
ModifyIDCMP( canvaswin, IDCMP_MENUPICK | IDCMP_VANILLAKEY );
if ( !( scbuf[ 0 ] = AllocScreenBuffer( canvassc, NULL, SB_SCREEN_BITMAP ) ) )
{
return( "Couldn't allocate ScreenBuffer 1\n" );
}
if ( !( scbuf[ 1 ] = AllocScreenBuffer( canvassc, NULL, SB_COPY_BITMAP ) ) )
{
return( "Couldn't allocate ScreenBuffer 2\n" );
}
/* Let's use the UserData to store the buffer number, for
* easy identification when the message comes back.
*/
scbuf[ 0 ]->sb_DBufInfo->dbi_UserData1 = ( APTR ) ( 0 );
scbuf[ 1 ]->sb_DBufInfo->dbi_UserData1 = ( APTR ) ( 1 );
status[ 0 ] = OK_REDRAW;
status[ 1 ] = OK_REDRAW;
if ( !( face = makeImageBM() ) )
{
return( "Couldn't allocate image bitmap\n" );
}
InitRastPort( &rport[ 0 ] );
InitRastPort( &rport[ 1 ] );
rport[ 0 ].BitMap = scbuf[ 0 ]->sb_BitMap;
rport[ 1 ].BitMap = scbuf[ 1 ]->sb_BitMap;
Move(&rport[0], canvassc->Width - 50, 9);
Text(&rport[0], "1", 1);
Move(&rport[1], canvassc->Width - 40, 9);
Text(&rport[1], "2", 1);
x = 50;
y = 70;
xstep = 1;
xdir = 1;
ystep = 1;
ydir = -1;
/* All is OK */
return( 0 );
}
/*----------------------------------------------------------------------*/
/* Draw a crude "face" for animation */
#define MAXVECTORS 10
struct BitMap *makeImageBM( void )
{
struct BitMap *bm;
struct RastPort rport;
struct AreaInfo area;
struct TmpRas tmpRas;
PLANEPTR planePtr;
BYTE areabuffer[ MAXVECTORS*5 ];
if(bm = (struct BitMap *)AllocBitMap(BM_WIDTH, BM_HEIGHT, BM_DEPTH, BMF_CLEAR, scbuf[ 0 ]->sb_BitMap)){
if(planePtr = AllocRaster(BM_WIDTH, BM_HEIGHT)){
InitRastPort(&rport);
rport.BitMap = bm;
InitArea(&area, areabuffer, MAXVECTORS);
rport.AreaInfo = &area;
InitTmpRas(&tmpRas, planePtr, RASSIZE(BM_WIDTH, BM_HEIGHT));
rport.TmpRas = &tmpRas;
SetABPenDrMd(&rport, 3, 0, JAM1);
AreaEllipse(&rport, BM_WIDTH/2, BM_HEIGHT/2, BM_WIDTH/2-4, BM_HEIGHT/2-4);
AreaEnd(&rport);
SetAPen(&rport, 2);
AreaEllipse(&rport, 5*BM_WIDTH/16, BM_HEIGHT/4, BM_WIDTH/9, BM_HEIGHT/9);
AreaEllipse(&rport, 11*BM_WIDTH/16, BM_HEIGHT/4, BM_WIDTH/9, BM_HEIGHT/9);
AreaEnd(&rport);
SetAPen(&rport, 1);
AreaEllipse(&rport, BM_WIDTH/2, 3*BM_HEIGHT/4, BM_WIDTH/3, BM_HEIGHT/9);
AreaEnd(&rport);
FreeRaster(planePtr, BM_WIDTH, BM_HEIGHT);
}else{
FreeBitMap(bm);
bm = NULL;
}
return(bm);
}
}
/*----------------------------------------------------------------------*/
/* Clean up everything and exit, printing the errorstring if any */
void error_exit(STRPTR errorstring)
{
if(canvaswin){
ClearMenuStrip(canvaswin);
CloseWindowSafely(canvaswin);
}
if(canvassc){
FreeScreenBuffer(canvassc, scbuf[1]);
FreeScreenBuffer(canvassc, scbuf[0]);
CloseScreen(canvassc);
}
if(dbufport) DeleteMsgPort(dbufport);
if(userport) DeleteMsgPort(userport);
if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if(face) FreeBitMap(face);
if(GfxBase) CloseLibrary((struct Library *)GfxBase);
if(errorstring){
printf(errorstring);
exit(20);
}
exit(0);
}
/*----------------------------------------------------------------------*/
void StripIntuiMessages( struct MsgPort *mp, struct Window *win );
/* these functions close an Intuition window
* that shares a port with other Intuition
* windows or IPC customers.
*
* We are careful to set the UserPort to
* null before closing, and to free
* any messages that it might have been
* sent.
*/
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/ports.h"
#include "intuition/intuition.h"
void
CloseWindowSafely( struct Window *win )
{
/* we forbid here to keep out of race conditions with Intuition */
Forbid();
/* send back any messages for this window
* that have not yet been processed
*/
StripIntuiMessages( win->UserPort, win );
/* clear UserPort so Intuition will not free it */
win->UserPort = NULL;
/* tell Intuition to stop sending more messages */
ModifyIDCMP( win, 0L );
/* turn multitasking back on */
Permit();
/* and really close the window */
CloseWindow( win );
}
/* remove and reply all IntuiMessages on a port that
* have been sent to a particular window
* ( note that we don't rely on the ln_Succ pointer
* of a message after we have replied it )
*/
void
StripIntuiMessages( mp, win )
struct MsgPort *mp;
struct Window *win;
{
struct IntuiMessage *msg;
struct Node *succ;
msg = ( struct IntuiMessage * ) mp->mp_MsgList.lh_Head;
while( succ = msg->ExecMessage.mn_Node.ln_Succ )
{
if( msg->IDCMPWindow == win )
{
/* Intuition is about to free this message.
* Make sure that we have politely sent it back.
*/
Remove( ( struct Node * )msg );
ReplyMsg( ( struct Message * )msg );
}
msg = ( struct IntuiMessage * ) succ;
}
}
/*----------------------------------------------------------------------*/ @mateusz_s, post #250


@jimiche, post #255
@mateusz_s, post #257
@arturB, post #258
@mateusz_s, post #259




@mateusz_s, post #260






@mateusz_s, post #261
@BULI, post #263
@mateusz_s, post #268