[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

;/*  RGBBoxes.c simple ViewPort example -- works with 1.3 and Release 2
LC -b1 -cfistq -v -y -j73 RGBBoxes.c
Blink FROM LIB:c.o,RGBBoxes.o TO RGBBoxes LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example creates a View consisting of one ViewPort set
** to an NTSC, high-resolution, interlaced display mode of nominal
** dimensions.  This example shows both the old 1.3 way of setting up
** the ViewPort and the new method used in Release 2.
*/

#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxnodes.h>
#include <graphics/videocontrol.h>
#include <libraries/dos.h>
#include <utility/tagitem.h>

#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>
#include <stdlib.h>

#define DEPTH 2     /*  The number of bitplanes.  */
#define WIDTH 640   /*  Nominal width and height  */
#define HEIGHT 400  /*  used in 1.3.              */

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID drawFilledBox(WORD , WORD );  /* Function prototypes */
VOID cleanup(int );
VOID fail(STRPTR);

struct GfxBase *GfxBase = NULL;

/*  Construct a simple display.  These are global to make freeing easier.   */
struct View view, *oldview=NULL;  /*  Pointer to old View we can restore it.*/
struct ViewPort viewPort = { 0 };
struct BitMap bitMap = { 0 };
struct ColorMap *cm=NULL;

struct ViewExtra *vextra=NULL;      /* Extended structures used in Release 2 */
struct MonitorSpec *monspec=NULL;
struct ViewPortExtra *vpextra=NULL;
struct DimensionInfo dimquery = { 0 };

UBYTE *displaymem = NULL;     /*  Pointer for writing to BitMap memory.  */

#define BLACK 0x000           /*  RGB values for the four colors used.   */
#define RED   0xf00
#define GREEN 0x0f0
#define BLUE  0x00f

/*
 * main():  create a custom display; works under either 1.3 or Release 2
 */
VOID main(VOID)
{
WORD depth, box;
struct RasInfo rasInfo;
ULONG modeID;

struct TagItem vcTags[] =
{
    {VTAG_ATTACH_CM_SET, NULL },
    {VTAG_VIEWPORTEXTRA_SET, NULL },
    {VTAG_NORMAL_DISP_SET, NULL },
    {VTAG_END_CM, NULL }
};

/*  Offsets in BitMap where boxes will be drawn.  */
static SHORT boxoffsets[] = { 802, 2010, 3218 };

static UWORD colortable[] = { BLACK, RED, GREEN, BLUE };

/* Open the graphics library */
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33L);
if(GfxBase == NULL)
    fail("Could not open graphics library\n");

/*  Example steals screen from Intuition if Intuition is around.      */
oldview = GfxBase->ActiView;   /* Save current View to restore later. */

InitView(&view);           /*  Initialize the View and set View.Modes.     */
view.Modes |= LACE;        /*  This is the old 1.3 way (only LACE counts). */

if(GfxBase->LibNode.lib_Version >= 36)
    {
    /* Form the ModeID from values in <displayinfo.h> */
    modeID=DEFAULT_MONITOR_ID | HIRESLACE_KEY;

    /*  Make the ViewExtra structure   */
    if( vextra=GfxNew(VIEW_EXTRA_TYPE) )
        {
        /* Attach the ViewExtra to the View */
        GfxAssociate(&view , vextra);
        view.Modes |= EXTEND_VSTRUCT;

        /* Create and attach a MonitorSpec to the ViewExtra */
        if( monspec=OpenMonitor(NULL,modeID) )
            vextra->Monitor=monspec;
        else
            fail("Could not get MonitorSpec\n");
        }
     else fail("Could not get ViewExtra\n");
     }


/*  Initialize the BitMap for RasInfo.  */
InitBitMap(&bitMap, DEPTH, WIDTH, HEIGHT);

/* Set the plane pointers to NULL so the cleanup routine */
/* will know if they were used.                          */
for(depth=0; depth<DEPTH; depth++)
    bitMap.Planes[depth] = NULL;

/*  Allocate space for BitMap.             */
for (depth=0; depth<DEPTH; depth++)
    {
    bitMap.Planes[depth] = (PLANEPTR)AllocRaster(WIDTH, HEIGHT);
    if (bitMap.Planes[depth] == NULL)
        fail("Could not get BitPlanes\n");
    }

rasInfo.BitMap = &bitMap;       /*  Initialize the RasInfo.  */
rasInfo.RxOffset = 0;
rasInfo.RyOffset = 0;
rasInfo.Next = NULL;

InitVPort(&viewPort);           /*  Initialize the ViewPort.  */
view.ViewPort = &viewPort;      /*  Link the ViewPort into the View.  */
viewPort.RasInfo = &rasInfo;
viewPort.DWidth = WIDTH;
viewPort.DHeight = HEIGHT;

/* Set the display mode the old-fashioned way */
viewPort.Modes=HIRES | LACE;

if(GfxBase->LibNode.lib_Version >= 36)
{
    /* Make a ViewPortExtra and get ready to attach it */
    if( vpextra = GfxNew(VIEWPORT_EXTRA_TYPE) )
        {
        vcTags[1].ti_Data = (ULONG) vpextra;

        /* Initialize the DisplayClip field of the ViewPortExtra */
        if( GetDisplayInfoData( NULL , (UBYTE *) &dimquery ,
                                sizeof(dimquery) , DTAG_DIMS, modeID) )
            {
            vpextra->DisplayClip = dimquery.Nominal;

            /* Make a DisplayInfo and get ready to attach it */
            if( !(vcTags[2].ti_Data = (ULONG) FindDisplayInfo(modeID)) )
                fail("Could not get DisplayInfo\n");
             }
        else fail("Could not get DimensionInfo \n");
        }
    else fail("Could not get ViewPortExtra\n");

    /* This is for backwards compatibility with, for example,   */
    /* a 1.3 screen saver utility that looks at the Modes field */
    viewPort.Modes = (UWORD) (modeID & 0x0000ffff);
    }

/*  Initialize the ColorMap.  */
/*  2 planes deep, so 4 entries (2 raised to the #_planes power).  */
cm = GetColorMap(4L);
if(cm == NULL)
    fail("Could not get ColorMap\n");

if(GfxBase->LibNode.lib_Version >= 36)
    {
    /* Get ready to attach the ColorMap, Release 2-style */
    vcTags[0].ti_Data = (ULONG) &viewPort;

    /* Attach the color map and Release 2 extended structures */
    if( VideoControl(cm,vcTags) )
        fail("Could not attach extended structures\n");
    }
else
    /* Attach the ColorMap, old 1.3-style */
    viewPort.ColorMap = cm;

LoadRGB4(&viewPort, colortable, 4);  /* Change colors to those in colortable. */

MakeVPort( &view, &viewPort ); /* Construct preliminary Copper instruction list.    */

/* Merge preliminary lists into a real Copper list in the View structure. */
MrgCop( &view );

/* Clear the ViewPort */
for(depth=0; depth<DEPTH; depth++)
    {
    displaymem = (UBYTE *)bitMap.Planes[depth];
    BltClear(displaymem, (bitMap.BytesPerRow * bitMap.Rows), 1L);
    }

LoadView(&view);

/*  Now fill some boxes so that user can see something.          */
/*  Always draw into both planes to assure true colors.          */
for (box=1; box<=3; box++)  /* Three boxes; red, green and blue. */
    {
    for (depth=0; depth<DEPTH; depth++)        /*  Two planes.   */
        {
        displaymem = bitMap.Planes[depth] + boxoffsets[box-1];
        drawFilledBox(box, depth);
        }
    }

Delay(10L * TICKS_PER_SECOND);   /*  Pause for 10 seconds.                */
LoadView(oldview);               /*  Put back the old View.               */
WaitTOF();                       /*  Wait until the the View is being     */
                                 /*    rendered to free memory.           */
FreeCprList(view.LOFCprList);    /*  Deallocate the hardware Copper list  */
if(view.SHFCprList)              /*    created by MrgCop().  Since this   */
    FreeCprList(view.SHFCprList);/*    is interlace, also check for a     */
                                 /*    short frame copper list to free.   */
FreeVPortCopLists(&viewPort);    /*  Free all intermediate Copper lists   */
                                 /*    from created by MakeVPort().       */
cleanup(RETURN_OK);              /*  Success.                             */
}


/*
 * fail():  print the error string and call cleanup() to exit
 */
void fail(STRPTR errorstring)
{
printf(errorstring);
cleanup(RETURN_FAIL);
}

/*
 * cleanup():  free everything that was allocated.
 */
VOID cleanup(int returncode)
{
WORD depth;

/*  Free the color map created by GetColorMap().  */
if(cm) FreeColorMap(cm);

/* Free the ViewPortExtra created by GfxNew() */
if(vpextra) GfxFree(vpextra);

/*  Free the BitPlanes drawing area.  */
for(depth=0; depth<DEPTH; depth++)
    {
    if (bitMap.Planes[depth])
        FreeRaster(bitMap.Planes[depth], WIDTH, HEIGHT);
    }

/* Free the MonitorSpec created with OpenMonitor() */
if(monspec) CloseMonitor( monspec );

/* Free the ViewExtra created with GfxNew() */
if(vextra) GfxFree(vextra);

/* Close the graphics library */
CloseLibrary((struct Library *)GfxBase);

exit(returncode);
}


/*
 * drawFilledBox(): create a WIDTH/2 by HEIGHT/2 box of color
 *                  "fillcolor" into the given plane.
 */
VOID drawFilledBox(WORD fillcolor, WORD plane)
{
UBYTE value;
WORD boxHeight, boxWidth, width;

/*  Divide (WIDTH/2) by eight because each UBYTE that */
/* is written stuffs eight bits into the BitMap.      */
boxWidth = (WIDTH/2)/8;
boxHeight = HEIGHT/2;

value = ((fillcolor & (1 << plane)) != 0) ?  0xff : 0x00;

for( ; boxHeight; boxHeight--)
    {
    for(width=0 ; width < boxWidth; width++)
        *displaymem++ = value;

    displaymem += (bitMap.BytesPerRow - boxWidth);
    }
}