Aros/Developer/Docs/Libraries/Graphics
Contents |
[edit] Introduction
AROS has a line based graphics mode which is useful for polygon and wire-framed based drawing utilities
And has the ability for bitmap manipulation for images (pictures)
To clarify that, if all you want to do is blast an RGB image onto a display, then you'll have no problems with Cybergfx or P96 chunky pixel functions. If you actually want to do some block fills and rasterize primitives, then you'll need the graphics.library. It doesn't actually matter that you are using a pen in those cases since on an RGB display, you can allocate a pen and change it's colour as often as you want without affecting anything you already rendered.
[edit] Line Graphics
Whenever a window is opened, a drawing surface is also prepared and the information is stored in its own rastport. Every drawing operation involves a rastport. If you want to draw directly into a window, you use the window's rastport. If you draw to an off-screen bitmap you create your own temporary rastport and then blit the temporary bitmap into the window's rastport.
struct RastPort
{
struct Layer *Layer;
struct BitMap *BitMap;
UWORD *AreaPtrn; /* Ptr to areafill pattern */
struct TmpRas *TmpRas;
struct AreaInfo *AreaInfo;
struct GelsInfo *GelsInfo;
UBYTE Mask; /* Write mask for this raster */
BYTE FgPen; /* Foreground pen for this raster */
BYTE BgPen; /* Background pen */
BYTE AOlPen; /* Areafill outline pen */
BYTE DrawMode; /* Drawing mode for fill, lines, and text */
BYTE AreaPtSz; /* 2^n words for areafill pattern */
BYTE linpatcnt; /* Current line drawing pattern preshift */
BYTE dummy;
UWORD Flags; /* Miscellaneous control bits */
UWORD LinePtrn; /* 16 bits for textured lines */
WORD cp_x, cp_y; /* Current pen position */
UBYTE minterms[8];
WORD PenWidth;
WORD PenHeight;
struct TextFont *Font; /* Current font address */
UBYTE AlgoStyle; /* The algorithmically generated style */
UBYTE TxFlags; /* Text specific flags */
UWORD TxHeight; /* Text height */
UWORD TxWidth; /* Text nominal width */
UWORD TxBaseline; /* Text baseline */
WORD TxSpacing; /* Text spacing (per character) */
APTR *RP_User;
ULONG longreserved[2];
#ifndef GFX_RASTPORT_1_2
UWORD wordreserved[7]; /* Used to be a node */
UBYTE reserved[8]; /* For future use */
#endif
};
AROS like AmigaOS(TM) before has a number of function relating to line graphics using the graphics.library. These include setting color, plotting points (pixels), drawing lines, rectangles, circles, patterns, area filling and so on. Most functions require a pointer to a RastPort which is a special public structure (template) that is created automatically from a Window or a Layer call, referenced by Window->RPort (RastPort address). This value can then be used for the SetAPen(rp,FrontPenNumber), SetOPen(rp,OutlinePenNumber), Move(rp,x,y) and Draw(rp,x,y) and Text(rp,pointer_to_text,ext_length) function commands.
Window Co-ords are Graphics Co-ords are 0,0 are top left and 640,400 could be bottom right
WritePixel(rp,x,y) function plots a point with colour set in SetAPen().
void SetAPen( struct RastPort *rp, unsigned long pen ) - Set foreground colour using preset colour pens void SetBPen( struct RastPort *rp, unsigned long pen ) - Set background colour using preset colour pens void Move(struct RastPort rp, long x, long y) - Move to co-ordinates row x, column y in a Rastport (rp) where 0,0 is the top left of window. void Draw(struct RastPort rp, long x, long y) - Draws a line from current position to row x, column y. void DrawEllipse( struct RastPort *rp, long xCenter, long yCenter, long a, long b ) - Draw an Ellipse ULONG ReadPixel( struct RastPort *rp, long x, long y ) - Read a pixel value LONG WritePixel( struct RastPort *rp, long x, long y ) - Write a pixel void PolyDraw( struct RastPort *rp, long count, WORD *polyTable ) - Draw a multi-lined polygon using an array of x,y points.
Refreshing windows can be done via SIMPLE_REFRESH (redraw) or SMART_REFRESH windows or SUPER_BITMAP (GIMMEZEROZERO) window.
/* Grid in a Window */ #include <proto/intuition.h> #include <proto/gadtools.h> #include <proto/graphics.h> #include <proto/layers.h> #include <proto/exec.h> #include <proto/dos.h> #include <intuition/intuition.h> int main() { struct Window *myWindow; struct RastPort *rp; int closewin = FALSE, row, column; struct IntuiMessage *msg; ULONG msgClass; long startx,starty,width; myWindow = OpenWindowTags(NULL, WA_Left, 0, WA_Top, 0, WA_Width, 640, WA_Height, 400, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW, WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE | WFLG_SMART_REFRESH, WA_Title, "Grid In a Window", WA_PubScreenName, "Workbench", TAG_DONE); /* Get Window's Rastport */ rp = myWindow->RPort; /* Draw 8x8 grid of boxes */ /* Set foreground color */ SetAPen(rp, 1); for(row=1; row<=8; row++) { for(column=1; column<=8; column++) { /* Move to correct screen position and draw box */ Move(rp, row*30, column*30); Draw(rp, row*30+30, column*30 + 0); Draw(rp, row*30+30, column*30 + 30); Draw(rp, row*30+0, column*30 + 30); Draw(rp, row*30+0, column*30 + 0); } } while (closewin == FALSE) { Wait(1L << myWindow->UserPort->mp_SigBit); msg = GT_GetIMsg(myWindow->UserPort); msgClass = msg->Class; GT_ReplyIMsg(msg); if (msgClass == IDCMP_CLOSEWINDOW) { CloseWindow(myWindow); closewin = TRUE; } if (msgClass == IDCMP_REFRESHWINDOW) RefreshWindowFrame(myWindow); } return(0); }
Take a look at amilines for another example and arosbattleships for an ascii version grid.
[edit] Set Background Color
If your window is borderless you can just
SetRast(win->RPort, 2);
However, if your window has borders then you need to account for them
{ LONG l, t, w, h; l = win->BorderLeft; t = win->BorderTop; w = win->Width - win->BorderLeft - win->BorderRight; h = win->Height - win->BorderTop - win->BorderBottom; if (w > 0 && h > 0) { /* White background */ SetAPen(win->RPort, 2); RectFill(win->RPort, l, t, l + w - 1, t + h - 1); ... } }
Another possibility is using WA_BackFill and a custom backfill hook.
[edit] Pens
If you are using graphics.library, pens are limited from 0-255, regardless of what your display is running on.
If you need to set an arbitrary colour for area pens for use on an RGB display, you need to use LoadRGB32 to set the colour of your chosen pen (or pens). On an RGB display, you can keep changing the pen colour without affecting already rendered pixels. On an indexed display, you have to worry about finding a suitable pen that is close to your desired colour in the first place.
If using 'pen 1', and then change the palette value of 'pen 1' by using the values with SetRGB32(). Just allocate a pen, set it's RGB value, render with it, change the RGB value again, render some more and when you are done release the pen. If it's on your own screen, you can just allocate the pen after you open the screen then release it before you close it. You aren't restricted to using just the one pen, you can allocate pens for area, fill etc. Regarding SetRGB32(), the documentation makes it clear that it's slower than LoadRGB32() with a single colour index.
On AFA OS 68k, AROS and MOS you can set RGB foreground and background colors with that Tag
RPTAG_FgColor: RPTAG_BgColor:
SetRPAttrs( rastport, RPTAG_FgColor:, 0xRRGGBB, TAG_DONE );
if you like the OS4 syntax you can just do
#define RPATTR_APenColor RPTAG_FgColor
#include <proto/graphics.h> #include <proto/exec.h> #include <intuition/intuitionbase.h> #include <intuition/screens.h> #include <graphics/view.h> #include <stdio.h> int main(void) { struct IntuitionBase * IntuitionBase; struct Library * GfxBase; struct ViewPort * vp; struct ColorMap * cm; struct PaletteExtra * pe; #define NUMCOLORS 32 ULONG n[2*NUMCOLORS]; ULONG i; IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0); GfxBase = OpenLibrary("graphics.library",0); cm = GetColorMap(NUMCOLORS); vp = &IntuitionBase->ActiveScreen->ViewPort; AttachPalExtra(cm,vp); pe = cm->PalExtra; n[0] = ObtainPen(cm, -1, 0xa0000000, 0xb0000000, 0xc0000000, 0); printf("Got pen number %ld.\n",(long)n[0]); printf("Trying to obtain the same pen as shared.\n"); n[1] = ObtainPen(cm, -1, 0xa0000000, 0xb0000000, 0xc0000000, 0); printf("Got pen number %ld (=%ld!).\n",(long)n[1],(long)n[0]); printf("Trying to obtain a pen as exclusive.\n"); n[2] = ObtainPen(cm, -1, 0xa0000000, 0xb0000000, 0xc0000000, PENF_EXCLUSIVE); printf("Got pen number %ld.\n",(long)n[2]); printf("Trying to allocate pen %ld as exclusive again.\n",(long)n[2]); n[3] = ObtainPen(cm, n[2], 0xa0000000, 0xb0000000, 0xc0000000, PENF_EXCLUSIVE); printf("Got pen number %ld.\n",(long)n[3]); printf("Trying to allocate pen %ld as shared.\n",(long)n[2]); n[4] = ObtainPen(cm, n[2], 0xa0000000, 0xb0000000, 0xc0000000, 0); printf("Got pen number %ld.\n",(long)n[4]); printf("Releasing all pens.\n"); ReleasePen(cm, n[4]); ReleasePen(cm, n[3]); ReleasePen(cm, n[2]); ReleasePen(cm, n[1]); ReleasePen(cm, n[0]); printf("Obtaining a shared pen.\n"); n[0] = ObtainPen(cm, -1, 0xa0000000, 0xb0000000, 0xc0000000, 0); printf("Got pen number %ld.\n",(long)n[0]); ReleasePen(cm, n[0]); printf("---------------------------\n"); printf("Trying to allocate %d shared pens\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i] = ObtainPen(cm, -1, i << 28, i << 24, i << 20,0); printf("Got pen %ld\n",(long)n[i]); i++; } printf("Trying to get %d exclusive pens (no pen was released)\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i+NUMCOLORS] = ObtainPen(cm, -1, 0,0,0,PENF_EXCLUSIVE); printf("Got pen %ld (=-1)\n",(long)n[i+NUMCOLORS]); i++; } printf("Releasing all pens!\n"); i = 0; while (i < 2 * NUMCOLORS) { ReleasePen(cm, n[i]); i++; } printf("---------------------------\n"); printf("Trying to get %d exclusive pens\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i] = ObtainPen(cm, -1, 0,0,0,PENF_EXCLUSIVE); printf("Got pen %ld\n",(long)n[i]); i++; } printf("Trying to allocate %d shared pens (no pen was released)\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i+NUMCOLORS] = ObtainPen(cm, -1, 0,0,0,0); printf("Got pen %ld (=-1)\n",(long)n[i+NUMCOLORS]); i++; } printf("Releasing all pens!\n"); i = 0; while (i < 2*NUMCOLORS) { ReleasePen(cm, n[i]); i++; } printf("---------------------------\n"); printf("Trying to allocate %d shared pens at certain indices\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i] = ObtainPen(cm, i, 0, 0, 0,0); printf("Got pen %ld\n",(long)n[i]); i++; } printf("Trying to get %d exclusive pens (no pen was released)\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i+NUMCOLORS] = ObtainPen(cm, -1, 0,0,0,PENF_EXCLUSIVE); printf("Got pen %ld (=-1)\n",(long)n[i+NUMCOLORS]); i++; } printf("Releasing all pens!\n"); i = 0; while (i < 2 * NUMCOLORS) { ReleasePen(cm, n[i]); i++; } printf("---------------------------\n"); printf("Trying to get %d exclusive pens at certain indices\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i] = ObtainPen(cm, i, 0,0,0,PENF_EXCLUSIVE); printf("Got pen %ld\n",(long)n[i]); i++; } printf("Trying to allocate %d shared pens (bo pen was released)\n",NUMCOLORS); i = 0; while (i < NUMCOLORS) { n[i+NUMCOLORS] = ObtainPen(cm, -1, 0,0,0,0); printf("Got pen %ld (=-1)\n",(long)n[i+NUMCOLORS]); i++; } printf("Releasing all pens!\n"); i = 0; while (i < 2*NUMCOLORS) { ReleasePen(cm, n[i]); i++; } printf("---------------------------\n"); FreeColorMap(cm); return 0; }
[edit] Drawing with Polygon Areas
The AreaInfo structure list the points that make up the filled shape.
struct AreaInfo
{
WORD *VctrTbl; /* ptr to start of vector table */
WORD *VctrPtr; /* ptr to current vertex */
BYTE *FlagTbl; /* ptr to start of vector flag table */
BYTE *FlagPtr; /* ptrs to areafill flags */
WORD Count; /* number of vertices in list */
WORD MaxCount; /* AreaMove/Draw will not allow Count>MaxCount*/
WORD FirstX,FirstY; /* first point for this polygon */
};
The graphics workspace is served by a data structure called
struct TmpRas
{
BYTE *RasPtr;
LONG Size;
};
/* unoptimized for 32bit alignment of pointers */
It is now possible to produce filled polygon 'areas' using the InitArea, AreaMove, AreaDraw and AreaEnd functions as long as a TmpRas struct is set up which can plot out an outline of a shape and flood fill it with a specified color.
struct TmpRas *InitTmpRas( struct TmpRas *tmpRas, PLANEPTR buffer, long size ) void InitArea( struct AreaInfo *areaInfo, APTR vectorBuffer, long maxVectors ) ULONG SetOutlinePen( struct RastPort *rp, unsigned long pen ) LONG AreaMove( struct RastPort *rp, long x, long y ) LONG AreaDraw( struct RastPort *rp, long x, long y ) LONG AreaEnd( struct RastPort *rp )
An area is initialised with the InitTmpRas which sets up a working area for areas and flood fills in the Raster and InitArea which sets up a vector buffer to store area co-ordinates, the pointers are then associated with the Window's Raster structure to be eventually rendered on the screen. To create an area, use AreaMove to set the start position, then each subsequent position is then drawn with AreaDraw using absolute x,y co-ordinates, you do not need to join the last co-ordinate with the first position, as AreaEnd will do this for you. Notice that I have used SetAPen and SetOutlinePen to set the colour of the area and the lines around the shapes. The InitTmpRas requires a pointer to a TmpRas structure, a pointer to a buffer in Chip memory (which is allocated using AllocMem) for the area of the window (width height x 8) and the size of the buffer. AreaInfo requires a pointer to a AreaInfo structure, a buffer to store x,y vectors and a max number of vectors (buffer * 2 /5) which uses Word values rather than UBYTE as it has to be word aligned. The structures are then assigned to the Rastport e.g. rp->AreaInfo and rp->TmpRas before using the areas.
Flood(rp,mode,x,y)
If negative coordinates are passed to these AreaMove() AreaDraw() functions the display gets corrupted. Moreover, even for further calls with no negative coordinates the new drawings are also corrupted.
Have a go compiling bug-e.c which used to show buggy output on old Amigas and [www.lysator.liu.se/~nisse/archive/Vectors-1.1/test.c vectors test]
[edit] BitMaps
A BitMap tells the graphics library where in memory the drawing area is located and how it is arranged. After this, a RastPort can be added/linked...
struct BitMap { UWORD BytesPerRow; UWORD Rows; UBYTE Flags; UBYTE Depth; UWORD pad; PLANEPTR Planes[8]; };
static struct Window *win; static struct BitMap *drawbm; static struct RastPort *winrp, *drawrp; static struct AreaInfo ai; static struct TmpRas tr; static void *trbuf; /* Initialize the RastPort and link the BitMap to it. */ InitRastPort(&rastPort); rastPort.BitMap = &bitMap;
struct RastPort *offscreen_buffer_rp; offscreen_buffer_rp &myBufferRP;
- Allocate a window.
- Create a friend bitmap the same size as your windows visible area as an offscreen buffer.
- Create a second friend bitmap that is some sensible multiple of your tile size.
- Render your tiles into the second bitmap.
Allocate a bitmap with friend bitmap set to something else than NULL. Otherwise, bitmap with buffers in regular memory will be created - such thing cannot be locked (especially os-hosted modes). On hosted display driver's bitmap is not a pixel array at all. It's some underlying OS' blob instead. It could be emulated (temporarily allocate pixel array, copy data, then copy back upon unlock).
It is better to have the picture in a back buffer if your window has a size gadget or does simple refreshing so that you can easily redraw exposed areas.
When you create your offscreen bitmap, make sure it has a rastport of its own that has the same properties as that used by the window (things like palette etc.).
screen = LockPubScreen(NULL);
if (screen)
{
printf("screen bitmap %p\n", screen->RastPort.BitMap);
bitmap = AllocBitMap(400, 300, 32, BMF_MINPLANES | /*BMF_DISPLAYABLE | */ BMF_SPECIALFMT | SHIFT_PIXFMT(PIXFMT_ABGR32), screen->RastPort.BitMap);
If you want it completely flicker free you may instead want to do that to an off screen bitmap, update the text, and then blit the whole thing to the window.
struct RastPort rp; struct * Bitmap PBM, ULONG screenDepth, flags, BOOL isStandardBM; InitRastPort (& rp); screenDepth GetBitMapAttr = (pWin-> WScreen-> RastPort.BitMap, BMA_DEPTH); isStandardBM GetBitMapAttr = (pWin-> WScreen-> RastPort . BitMap, BMA_FLAGS) & BMF_STANDARD; flags = (FindPort ("FBlit")?0:BMF_DISPLAYABLE) | (isStandardBM? 0: BMF_MINPLANES); /* friend_bitmap clones the existing bitmap's pixel format in graphics RAM and has all the correct alignment for blitting and stuff */ PBM = AllocBitMap (IMAGE_WIDTH, IMAGE_HEIGHT, screenDepth, flags, pWin-> WScreen-> RastPort.BitMap) if (! PBM) return / * quit if allocation failed * / = rp.BitMap PBM, / * binds to BitMap RastPort * / WriteChunkyPixels (& rp, 0, 0, IMAGE_WIDTH-1 IMAGE_HEIGHT-1 Image IMAGE_WIDTH); /* draw the Bitmap in the window */ BltBitMapRastPort (struct Bitmap * bitmap_source, src_x WORD, WORD src_y, struct * RastPort rastport_dest, dest_x WORD, WORD dest_y, WORD width, WORD height UBYTE minterm); bitmap_source
ClipBlit?
static struct RastPort *Alloctemprp(struct RastPort *rp) { struct Layer_Info *li; struct Layer *l; struct BitMap *tempbm; ULONG bmwidth, bmheight, bmdepth; 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 ((l = 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); } }
Always use GetBitMapAttr() to query the depth, e.g. ULONG depth = GetBitMapAttr(screen->RastPort.BitMap, BMA_DEPTH); Otherwise you'll get "8" even for 24 and 32 bit screens. Not sure if superbitmap is prepared for true color screens or if AROS implementation of superbitmap windows is broken requires additional tests. My suggestion is that you leave out superbitmap windows. You can use ClipBlit() to blit into a window.
The code where you either RectFill() the background or WritePixelArray() the image behind the text needs to be moved/duplicated/put into a function and called from your inner loop. Alternatively you could install a backfill hook and do EraseRect() in both cases.
A hook is a custom function you write in order to be able to handle a specific situation that arises from intercepting the main code (such as, processing a message). The function must be designed to accept three arguments, whose order and type is given.
Avoid hacks such as direct rendering into a screen's struct BitMap. You'll blindly overwrite display's contents. RastPorts are needed for PROPER drawing, they are responsible for clipping and storing hidden parts in separate bitmaps. Though, direct drawing on a BitMap is allowed ONLY if it's completely your screen and OS doesn't display anything on it, even titlebar. Or of its your own BitMap in memory.
If you want to keep the background pattern, you should move the WritePixelArrayAlpha in place of the ClearScreen.
if (gfxdata)
{
WritePixelArrayAlpha (...);
}
else
{
SetRPAttrs(RP, RPTAG_BgColor, 0xFFFFFF, TAG_DONE);
Move (rp,0,0);
ClearScreen (rp);
}
Also, note that ClearScreen() doesn't do what you seem to think it does - it does *not* clear the entire window, it clears from the current position, which since you haven't done a Move() after writing the text will be *after* where the text is located. ClearScreen only clears from the current cursor position to the lower right end. In order to clear the entire drawing area you have to do Move(0,0) first.
[edit] Copy
There are few different ways to copy one bitmap to another. BltBitMap (bitmap to bitmap - most prone to crashes), ClipBlit (rastport to rastport - destroy parts of destination) and BltBitmapRastPort (bitmap to rastport).
Transparency
/* Spy is a toy to view the next screen as "iconified" in a window on the current screen (using graphics library BitMapScale function). */ #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <graphics/scale.h> #include <stdio.h> static const char version[] = "$VER: Spy 41.1.2 (29.08.2008) by Olivier Tigréat"; void redraw(struct Window *spy_window, struct BitMap *wbm, struct Screen *observed_screen); void redraw(struct Window *spy_window, struct BitMap *wbm, struct Screen *observed_screen) { struct RastPort temprp; InitRastPort(&temprp); temprp.BitMap = wbm; struct BitScaleArgs bms_args; bms_args.bsa_SrcBitMap = observed_screen->RastPort.BitMap; bms_args.bsa_DestBitMap = temprp.BitMap; bms_args.bsa_Flags = 0; bms_args.bsa_SrcWidth = observed_screen->Width; bms_args.bsa_SrcHeight = observed_screen->Height; bms_args.bsa_SrcX = 0; bms_args.bsa_SrcY = 0; bms_args.bsa_DestX = 0; bms_args.bsa_DestY = 0; bms_args.bsa_XSrcFactor = observed_screen->Width; bms_args.bsa_XDestFactor = spy_window->GZZWidth; bms_args.bsa_YSrcFactor = observed_screen->Height; bms_args.bsa_YDestFactor = spy_window->GZZHeight; BitMapScale(&bms_args); ClipBlit( &temprp, 0, 0, spy_window->RPort, spy_window->BorderLeft, spy_window->BorderTop, spy_window->GZZWidth, spy_window->GZZHeight, 0x00C0); DeinitRastPort(&temprp); } int main() { int retval = 0; /* Return code for main() (Shell error code) */ int closewin = FALSE; /* Flag used to end program */ struct IntuiMessage *imsg; /* Structure to store Intuition message data */ ULONG signals; /* User interaction reported by signals */ struct Screen *screen = NULL, *observed_screen = NULL; struct Window *spy_window = NULL; /* Our Spy window */ struct BitMap *scaledBitMap = NULL; /* BitMap structure for scaled representation */ IPTR depth = 0 ; if (NULL == (screen = LockPubScreen(NULL))) { retval = RETURN_ERROR; puts("LockPubScreen() failed to lock current screen"); } else depth = GetBitMapAttr(screen->RastPort.BitMap, BMA_DEPTH); if (depth == 0) { retval = RETURN_ERROR; puts("GetBitMapAttr() failed to get depth of screen"); } else observed_screen = screen->NextScreen; if (!(scaledBitMap = AllocBitMap( screen->Width, screen->Height, depth, BMF_DISPLAYABLE, observed_screen->RastPort.BitMap) ) ) { UnlockPubScreen(NULL,screen); retval = RETURN_ERROR; puts("AllocBitMap() failed to allocate/initialise BitMap"); } else { struct TagItem initial_tags[] = { { WA_Width , 160 }, { WA_Height , 120 }, { WA_Left , 400 }, { WA_Top , screen->BarHeight + 1 }, { WA_BackFill , (IPTR)LAYERS_NOBACKFILL }, { WA_GimmeZeroZero , FALSE }, { WA_SizeBBottom , TRUE }, { WA_DragBar , TRUE }, { WA_RMBTrap , TRUE }, { WA_DepthGadget , TRUE }, { WA_CloseGadget , TRUE }, { WA_SizeGadget , TRUE }, { WA_NoCareRefresh , TRUE }, { WA_IDCMP , IDCMP_CLOSEWINDOW|IDCMP_CHANGEWINDOW }, { WA_MinWidth , 80 }, { WA_MinHeight , 80 }, { WA_MaxWidth , -1 }, { WA_MaxHeight , -1 }, { WA_Title , (IPTR)"Spy" }, { WA_BackFill , (IPTR)LAYERS_NOBACKFILL }, { TAG_DONE } }; if ( !(spy_window = OpenWindowTagList(NULL,initial_tags))) { UnlockPubScreen(NULL,screen); closewin = TRUE; retval = RETURN_ERROR; puts("OpenWindowTags() failed to open spy window"); } else { UnlockPubScreen(NULL,screen); redraw(spy_window,scaledBitMap,observed_screen); while((closewin == FALSE)) { signals = Wait(1L << spy_window->UserPort->mp_SigBit | SIGBREAKF_CTRL_C); /* Wait for an event! */ if (signals & (1L << spy_window->UserPort->mp_SigBit)) { while ((imsg = (struct IntuiMessage *)GetMsg(spy_window->UserPort))) { switch (imsg->Class) { case IDCMP_CLOSEWINDOW: /* Check here if Close Window selected */ closewin = TRUE; /* so while loop will end there */ break; case IDCMP_CHANGEWINDOW: redraw(spy_window,scaledBitMap,observed_screen); break; case IDCMP_REFRESHWINDOW: redraw(spy_window,scaledBitMap,observed_screen); break; default: puts("Unknown IDCMP message"); } /* switch (imsg->Class) */ ReplyMsg((struct Message *)imsg); } /* while ((imsg = (struct IntuiMessage *)GetMsg(spy_window->UserPort))) */ } /* if(signals & (1L << spy_window->UserPort->mp_SigBit)) */ if (signals & SIGBREAKF_CTRL_C) { puts("Spy execution aborted with CTRL_C signal"); closewin = TRUE; } /* if (signals & SIGBREAKF_CTRL_C) */ } /* while((closewin == FALSE)) */ } /* else after if( !(spy_window... */ } /* else after else if (!(scaledBitMap... */ if (closewin == TRUE) { if (scaledBitMap) FreeBitMap(scaledBitMap); if (spy_window) CloseWindow(spy_window); /* Close window */ spy_window = NULL; } if(retval) { PrintFault(IoErr(), "spy"); } return retval; }
[edit] Rotations
/* assuming width and height are integers with the image's dimensions */ for(int x = 0; x < width; x++) { int hwidth = width / 2; int hheight = height / 2; double sinma = sin(-angle); double cosma = cos(-angle); for(int y = 0; y < height; y++) { int xt = x - hwidth; int yt = y - hheight; int xs = (int)round((cosma * xt - sinma * yt) + hwidth); int ys = (int)round((sinma * xt + cosma * yt) + hheight); if(xs >= 0 && xs < width && ys >= 0 && ys < height) { /* set target pixel (x,y) to color at (xs,ys) */ } else { /* set target pixel (x,y) to some default background */ } } }
[edit] ImageClass
You create a new boopsi class which is subclass of Intuition's IMAGECLASS (like this bitmap class) and in the IM_DRAW method you do the painting in whatever way you want. If you have some Bitmap from the datatype object use that with BltBitMapRastPort(), if you have some chunky pixel array, use WritePixelArray().
See compiler/coolimages/imageclass.c
Objects created from classes derived from IMAGECLASS can be passed to DrawImage(). from Converting struct BitMap into struct Image
If using native format bitmaps for the gfx hardware but how can it ensure they have Alpha? And since its impossible to lock access to the bitmap in most drivers how can it get access to the raw array of pixel data to pass into the Alpha functions in AROS? the pixfmt to use with the function can easily be obtained from the bitmap but until theres some way to get the data to use its pointless.
All the normal blit operations should respect alpha anyhow - and apps should determine if they will use it by allocating bitmaps without alpha etc (since they should know if they support/need it or not).
All gadgets will be drawn using PutImageAlpha (slow) while if using BltNewImageSubImageRastPort as previous, an attempt is made to check if the subimage of bitmap has no alpha channel pixels and if yes, a regular bitmap copy (CopyBox) is being done (faster). The image conversion method it is checked whether a subimage has not alpha pixels and if yes this subimage is marked as "able to copy from bitmap" instead of using WritePixelArrayAlpha. As a solution is the following:
- in the CreateNewImageContainerMatchingScreen function move the "transparency per subimage" test to main code path out of truecolor only
- don't assume that in LUT case all subimages can be read from bitmap, but re-use results of "transparency per subimage" check
This way you will cover all cases with BltNewImageSubImageRastPort, because it will detect (->subimageinbm[i]) that some images can't be copied from *bitmap and have to be drawn using WritePixelArrayAlpha regardless if the screen is LUT or truecolor. This also means BltNewImageSubImageRastPortSimple can again be based on BltNewImageSubImageRastPort.
using a 256 colour IFF to C, the palette is mostly black, but the screen is in a truecolour mode? Image data contains just pen numbers. Doesn't IFF2C create a color table? Its just a picture for an about box. PPaint gives me an array of 256 values, labelled 'palette'. How do I get this into the screen palette?
Do I need to extract the palette from the image separately and if so, how do I set my screen to use it? You can use SA_Colors attribute for OpenScreenTags() Or you can use LoadRGB32() from graphics.library Another thing: image data must be (UBYTE *) rather than (UWORD *) or you'll get a corrupt image because of wrong endianness.
Am I thinking about this the right way? Is there an easier way to do it? It depends what you really want to do. If you want to load an image and blit it to the screen it's likely better to use the Datatype system.
What's the purpose of NewImage's bitmap2? It seems to be allocated as a one-plane bitmap?
- data holds the raw bytes of image loaded from disk. There is also a check if any of the subimages of the image is not full-non-transparent. If that is the case, bitmap2 is allocated and *data is written to it using WritePixelArray (so removing alpha channel). Then when the subimage is to be drawn (by a call to BltNewImageSubImageRastPort) there is a detection if said subimage is fully non-trasparent. If it is, the image is copied from bitmap2 using BltBitMap instead of beeing drawing from *data using WritePixelArrayAlpha. This is done to increaset the speed of drawing gadgets. Actually if you analyze the code deeper you will notice that the role of bitmap2 is identical to role of bitmap. However, while bitmap2 is an allocated object, bitmap is just a pointer to bitmap of datatype - because of this difference in lifecycle, I selected to create bitmap2 instead of reusing bitmap fields.
Technically, a struct BitMap should be allocated in MEMF_PUBLIC while the bitplanes should be MEMF_CHIP. This way the pointers to the bitplanes can be in Fast RAM while the bitplanes themselves will not be. As a temporary workaround, I propose allocating bitplanes with MEMF_ANY on pc-i386. Is it even necessary to allocate bitplanes from chipmem anyway, since AFAIK displayable bitmaps are allocated through HIDDs on 68k? And should struct BitMap not get the same type of memory as its bitplanes?
[edit] Masks
You set the bltmask to a word aligned single bit plane in chip ram the same size as the bitmap to be blitted. A 0 in the mask means nothing is copied and a 1 means the source bitmap is copied through to the destination.
Interleaved blits only affect opaque blits because the masks would have to be as large as the source image on an interleaved transparent blit. The transparent blits are executed in non-interleaved mode regardless of how it is stored. Also, you have to request interleaved mode with a specific flag when you allocate the bitmap/screen.
If source and dest bitmaps are interleaved, mask for BltMaskBitMapRastPort() must be interleaved/repeated too. It's not clear if this is a bug or a feature. If you try to blit from interleaved to interleaved then you must use one of those horrible repeating masks.
A minterm value (ABC, ABNC and ANBC) describing how the image must be copied
from blit.h:
#define ABC 0x80 #define ABNC 0x40 #define ANBC 0x20 #define ANBNC 0x10 #define NABC 0x08 #define NABNC 0x04 #define NANBC 0x02 #define NANBNC 0x01
minterm 0xC0 would be ABC|ABNC and minterm 0xE0 being ABC|ABNC|ANBC
However, this is not apparent when using a graphics card, and only some very specific work values. The value of 0xE0 (0xC0 is not supported) is to be used for a single copy of the image without modification.
BltBitMapRastPort supports 0xC0, BltMaskBitMapRastPort ignores it.
Here is the call to do to draw your image:
BltBitMapRastPort (PBM, 0, 0, pWin-> RPORT, dest_x, dest_y, IMAGE_WIDTH, IMAGE_HEIGHT, 0xE0);
Remember to release the Bitmap before leaving the program with the function FreeBitMap ().
Note that the AutoDoc FreeBitMap () recommends calling WaitBlit () before releasing the Bitmap to be sure that nothing is being written in it.
[edit] Animation
Amiga was special in that its OS is more closely adapted to how the hardware works than other OSes (less abstracted from hw). So much so that a lot of what follows is for backwards compatibility only now.
[edit] Sprites
Most sprite stuff (mouse pointer #0) is almost completely moved away from graphics.library's handling. Only AllocSpriteData() is still used, in order to provide code reuse. The rest is done in monitorclass, it fits much better there, and many things can be done there in a simpler way than when using graphics.library sprite handling.
struct GelsInfo
{
BYTE sprRsrvd; /* flag of which sprites to reserve from vsprite system */
UBYTE Flags; /* system use */
struct VSprite *gelHead, *gelTail; /* dummy vSprites for list management*/
WORD *nextLine; /* pointer to array of 8 WORDS for sprite available lines */
WORD **lastColor; /* pointer to array of 8 pointers for color-last-assigned to vSprites */
struct collTable *collHandler; /* addresses of collision routines */
WORD leftmost, rightmost, topmost, bottommost;
APTR firstBlissObj,lastBlissObj; /* system use only */
};
AmigaOS(TM) GetSpriteData and copy the sprite graphics into it at your program init, then when you need to move them around or show them you ask the OS to use some sprites with GetSprite; when they don't need to be seen anymore you FreeSprite and when you don't need the spritegraphics anymore you FreeSpriteData.
AmigaOS(TM) FreeSprite frees 1 of the 8 hardware sprites that you reserved for use with GetSprite for your Viewport; returns it to be used by the OS (or another program that needs to use a sprite). FreeSpriteData should free the memory containing the sprite structure data - sprite's pixeldata etc.
[edit] Hardware
AmigaOS(TM) used to have a function InitGels() which starts VSprite but not implemented in AROS atm...
struct VSprite *vsHead; struct VSprite *vsTail; struct GelsInfo *gInfo;
InitGels(vsHead, vsTail, gInfo);
Simple Sprites are always 16 bits wide (sprite.h)
GetSprite() Attempts to allocates a sprite for exclusive use ChangeSprite() Modifies a Simple Sprite's image data MoveSprite() Changes a Simple Sprite's position FreeSprite() Relinquishes a sprite so it can be used by others
makeVSprite() and freeVSprite() functions
[edit] Virtual
AROS has VSprites (gels.h) but are only used by the mouse pointer (sprite #0) which converts them to simple sprites and displays them.
struct VSprite {
struct VSprite *NextVSprite; /* system only */
struct VSprite *PrevVSprite;
struct VSprite *DrawPath;
struct VSprite *ClearPath;
WORD OldY, OldX;
WORD Flags; /* */
WORD Y, X; /* */
WORD Height;
WORD Width;
WORD Depth;
WORD MeMask; /* */
WORD HitMask;
WORD *ImageData;
WORD *BorderLine;
WORD *CollMask;
WORD *SprColors;
struct Bob *VSBob;
BYTE PlanePick; /* */
BYTE PlaneOnOff;
VUserStuff VUserExt;
};
[edit] Bobs
Associated with the Amiga's Blitter chip so really only implemented in AROS m68k port...
struct Bob
{
WORD Flags; /* general purpose flags */
WORD *SaveBuffer;/* buffer for background save */
WORD *ImageShadow; /* shadow mask of image */
struct Bob *Before; /* draw this Bob before Bobs on this list */
struct Bob *After; /* draw this Bob after Bobs on this list */
struct VSprite *BobVSprite;/* this Bob's VSprite definition */
struct AnimComp *BobComp; /* pointer to this Bob's AnimComp def */
struct DBufPacket *DBuffer; /* pointer to this Bob's dBuf packet */
BUserStuff BUserExt; /* Bob user extension */
};
[edit] Collisions
AROS has SetCollision() function....
[edit] Font Rendering
- see here
void Text(struct RastPort *rp, CONST_STRPTR string, ULONG count)
void SetFont(struct RastPort *rp, struct TextFont *textFont)
struct TextFont {
struct Message tf_Message; /* reply message for font removal */
/* font name in LN | used in this */
UWORD tf_YSize; /* font height | order to best */
UBYTE tf_Style; /* font style | match a font */
UBYTE tf_Flags; /* preferences and flags / request. */
UWORD tf_XSize; /* nominal font width */
UWORD tf_Baseline; /* distance from the top of char to baseline */
UWORD tf_BoldSmear; /* smear to affect a bold enhancement */
UWORD tf_Accessors; /* access count */
UBYTE tf_LoChar; /* the first character described here */
UBYTE tf_HiChar; /* the last character described here */
APTR tf_CharData; /* the bit character data */
UWORD tf_Modulo; /* the row modulo for the strike font data */
APTR tf_CharLoc; /* ptr to location data for the strike font */
/* 2 words: bit offset then size */
APTR tf_CharSpace; /* ptr to words of proportional spacing data */
APTR tf_CharKern; /* ptr to words of kerning data */
};
It is required to use SetDrMd(rp,mode) to set the drawing mode before writing the text. But if I use SetRPAttrs setting and SetDrMd drawing, the background does not show, but the text is not refreshing and it redraws again and again, and in the end it is unreadable. the background has to be refreshed before drawing the new text.
For rendering fonts we use BlitColorExpansion() method. In order to be accelerated, source bitmap passed to this method must be allocated via the same driver. The first possible (and the simplest) way to solve this problem is to store a separate font bitmap per driver. I really don't like it because it would be a huge waste of memory.
If the bitmap is created using PutTemplate() method. So why can't we use PutTemplate() directly to produce a text? If we look more carefully, we'll see that BltTemplate() is already used in some cases (for software-generated italic and underline styles). So may be just implement accelerated PutTemplate() and PutAlphaTemplate() and completely drop BlitColorExpansion() ?
Removed font->bitmap conversion and BlitColorExpansion() support. BltTemplate() is used for font rendering from now on.
BltTemplate -- Draw a shape in a rectangle to the RastPort.
BltTemplate(SrcTemplate, SrcX, SrcMod, rp, DstX, DstY, SizeX, SizeY)
This function draws the image in the template into the RastPort in the current color and drawing mode at the specified position. The template is assumed not to overlap the destination.
If the template falls outside the RastPort boundary, it is truncated to that boundary.
Note: the SrcTemplate pointer should point to the "nearest" word (rounded down) of the template mask. Fine alignment of the mask is achieved by setting the SrcX bit offset within the range of 0 to 15 decimal.
SrcTemplate - pointer to the first (nearest) word of the template mask. SrcX - x bit offset into the template mask (range 0..15). SrcMod - number of bytes per row in template mask. rp - pointer to destination RastPort. DstX, DstY - x and y coordinates of the upper left corner of the destination for the blit. SizeX, SizeY - size of the rectangle to be used as the template.
[edit] Example
See w:Aros/Developer/Docs/Examples/GfxLibraryExample
[edit] TextEditor
Usually one stores the entire text in an internal buffer and then draws only the part of the buffer which is visible. You draw each section separately and set font and color before you draw a section.
What you should be doing is drawing your text based upon the text stored in memory & a value indicating how far you have scrolled. Later on you can add optimisations that avoid redrawing the whole window, by using the blitter to scroll the already-visible part.
Frankly, think the nitty-gritty of the display is nothing compared to the rest of the program - receiving input from keyboard, mouse and GUI inputs, maintaining the current text database, deciding how you are going to handle changes in window size. For instance, does text wrap or is it cut off at the right hand edge? If it wraps, you then have an extra line to display between the line on each side and you have to insert that new partial line into the database.
If you are serious about the job, you could start by designing and implementing the database first. You can always display the content using existing gadgets and classes. Then, later, you could write all the WYSIWYG functions to display it nicely.
Do I need to use the rastport of windows? Yes, and use WFLG_GIMMEZEROZERO flag windows. Use ClearEOL() and ClearScreen() to clear end-of-line and the rest of the screen. These are functions from graphics.library great to use with text-editors.
How do I get the cursor in a window? You type in letter with SetAPen() and SetBPen() or use SetDrMd() with COMPLEMENT.
How do I save the text that scrolls out of the window? You save the text in buffers that is logic part of the text (the displayed is physic part). The best method to store buffers in text editors is to store it in list of strings.
How do I have different fonts in the same row/line of text? That's tricky! Then you want to make Word or WordWorth type program. You must write proper function that covers that. It requires more effort than simple text editor (not word processor).
How do I do to have different colours on the same row/line of text? That's simple. Write the text with Text() and the inner cursor of RastPort will move you to the end of the word/words. You change colors with SetAPen() and SetBPen() then write the rest of the line.
[edit] Monitor
Monitor drivers is another sad chapter - there is no documentation on them whatsoever, only a set of hooks in the gfx library and the viewport structure (IIRC), the colormap is completely undocumented and carries a lot of payload around that was fitted into it because view and viewport were fully documented and could not be extended.
ColorMap Index 0. (the 'light grey' on Amiga 4-color mode) Runs the fastest!
- now moved to monitorclass
[edit] Uses
[edit] 2.5D Calculating Distance/Depth
A perspective transform (perspective projection == divide by Z) amounts to
x = x*d/z+d y = y*d/z+d
where d is the distance from the viewpoint and x, y, z are (obviously ) your x, y, z coordinates in 3d space If there is no "divide by Z", the depth-wise movement will feel wrong and it will feel like your object is accelerating/braking at the wrong times.
3d Projection
y_screen = (y_world / z) + (screen_height >> 1)
or:
z = y_world / (y_screen - (screen_height >> 1))
This formula takes the x or y world coordinates of an object, the z of the object, and returns the x or y pixel location. Or, alternately, given the world and screen coordinates, returns the z location.
Fast Linear Interpolation
o(x) = y1 + ((d * (y2-y1)) >> 16)
This assumes that all the numbers are in 16.16 fixed point. y1 and y2 are the two values to interpolate between, and d is the 16-bit fractional distance between the two points. For example, if d=$7fff, that would be halfway between the two values. This is useful for finding where between two segments a value is.
Fixed Point Arithmetic Floating point is very expensive for old systems which did not have specialized math hardware. Instead, a system called fixed point was used. This reserved a certain number of bits for the fractional part of the number. For a test case, say you only reserve one bit for the fractional amount, leaving seven bits for the whole number amounts. That fraction bit would represent one half (because a half plus a half equals a whole). To obtain the whole number value stored in that byte, the number is shifted right once. This can be expanded to use any number of bits for the fractional and whole portions of the number.
Fixed point multiplication is trickier than addition. In this operation, you would multiply the two numbers and then shift right by however many bits are reserved for fractions. Due to overflow, sometimes you may need to shift before multiplication instead of after. See "Fast Linear Interpolation" for an example of fixed point multiplcation.
Point Rotation
x' = x*cos(a) - y*sin(a) y' = x*sin(a) + y*cos(a)
Mentioned briefly in the tutorial as being an expensive operation, here is the basic point rotation formula. As you can see, it's at least 2 table lookups, 4 multiplications, and two additions, but the sine and cosine values can be reused for each point. Rotating for the purpose of hills would mean rotating the Z and Y coordinates, not the X and Y coordinates. To find the derivation of this formula, look up Rotation of Axes.
Avoid Division Instead of dividing by the z of an object in the standard projection formulas, you can take advantage of some properties of the road to speed up calculations. Say you have a 3d segment z position and a y position, and you want to find which line of the screen it belongs on. First, read through the z-map until you get to the 3d segment's z position. Then, multiply the height of the segment by the corresponding scaling value. The result is the number of pixels above the road that the segment belongs.
Use Z as Scaling Value Scaling routines work by slowing or speeding up the speed at which a draw routine reads through graphics data. For example, if you were to set the read speed to half, this would draw a sprite double the size. This is because for each time a pixel is drawn, the read position in the sprite data is only incremented by half, causing the read position to only increment by a whole number every two pixels.
Usually, a scaling routine has parameters like x, y, and scaling factor. But since a scaling factor is just 1/z, we can just reuse the Z value of that sprite! We will still need the scaling factor though to determine the boundaries of the sprite so that we can keep it centered as it scales.
Read more about 2.5D here
[edit] Maze Generation
Mazes can be viewed in 2.5D Algorithms
- Binary Tree (simple but limitations)
- Sidewinder (better Binary tree)
- Depth First Search (DFS) (good simple mazes - traces route and backtracks to fill in missing)
- Growing Tree
- Recursive Subdivision (wall adding - fractal like)
- Aldous-Broeder (inefficient uniform spanning tree based)
- Wilson's (better spanning tree)
- Prim's (another spanning tree)
- Kruskal's (good but complex tree spanning)
[edit]
[edit] Reference
FindDisplayInfo() is just a kludge to something very incomplete - it returns some opaque pointer that actually has no use since GetDisplayInfoData() perfectly lives without it.
The idea behind this is that we have GC (graphics context) HIDD object attached to every RastPort. This object has to be allocated/deallocated. In early days CreateRastPort() and DeleteRastPort() did this. Nowadays, GC object is allocated automagically on first attempt to use the RastPort. This object is then cached with usage counter attached. When some drawing operation begins, usage counter is incremented. It's decremented when the operation ends. These objects are supposed to be destroyed by some garbage collector which is not implemented yet. A DeInitRastPort() function exists which forces GC destruction. So, in fact, CreateRastPort() and DeleteRastPort() are obsolete.
Unlike AOS, AROS needs a rastport cleanup function (DeInitRastPort()), otherwise there may be a memory leak. That's why code is prepared for non-yet-existing rastport garbage collector. For cases where coders forget to use DeinitRastPort() in ported code (or theoretically for 68k binaries with a theoretical 68k emu). But the garbage collector would never know for sure if a rastport is definitely dead and will never be used again. Therefore even after killing driverdata/gc_object it's possible that some time later rastport is used again. In this case the driverdata/gc_object must be re-created from the info in the RastPort structure.
driverdata/gc_object gargabe collection may have some negative effect, so the idea would be to use it only for rastports created (or cloned) manually. But not for rastports created with CreateRastPort() or CloneRastPort(), because coders in this cases would know that they have to free it with DeleteRastPort(). One such negative effect may be speed, but also the case where some new AROS rastport features are used (like the clip rectangle), which is not stored in the RastPort structure (instead in DriverData struct) and can therefore not be re-created in case the driverdata/gc_object got killed by garbage collection but rastport is used again later on. So in this case the app must use CreateRastPort() or CloneRastPort() to prevent garbage collection from ever happening.
For me the solution should be first to reserve/lock on LVOs used currently by MOS/OS4 extensions moving around AROS extensions and then reserve a block of LVOs (100?) at the end. After this block, AROS functions could be added.
OrRectRegionND() ClearRectRegionND() OrRegionRegionND() ClearRegionRegionND() XorRegionRegionND() XorRectRegionND() AreRegionsEqual() ScrollRegion() (*) SwapRegions() BltRastPortBitMap() (*) ShowImminentReset() (**)
Apart from the last one, I see the others as public extensions/improvements, not private functions. For example "ND" stands for "non destructive". The original region functions all "return" the resulting region in one of the source regions (i.e. they modify/destroy it).
Example:
AndRegionRegion():
R2 = R1 intersected with R2;
The ND versions don't do that. AndRegionRegionND():
R3 = R1 intersected with R2;
Of course you can simulate this with the standard (old) region functions, but just because you can simulate a RectFill() with tons of WritePixel() doesn 't mean it's a good idea to remove RectFill().
DPaint (1-3) uses RectFill() to fill the gadget area manually using JAM2 mode. Which does not make any sense, JAM2 should overwrite everything. After more test much later I finally found out the reason: DPaint pokes directly to RasPort and modifies RastPort->mintern[0] value so that bitplane 0 is inverted but bitplane 1 is drawn normally. AOS apparently recalculates all mintern values after each SetAPen(),BPen,DrMd call which are then used by any drawing routine that uses blitter. (mintern[0] = plane0, mintern[1] = plane1 etc..) Not probably worth the trouble to implement but it is interesting implementation default. (this even works on OS39).
http://www.amigacoding.com/index.php/Graphics.library
Taking a look at ms_transform() and ms_translate() callbacks in struct MonitorSpec. Names give a clue that their purpose is to translate screen coordinates somehow. Does this mean that our graphics subsystem can work in some another coordinates (not in pixels), automatically dealing with screen aspects and such? Looked at MorphOS code there, ms_translate() is a stub which just copy one Rectangle structure to another. ms_transform() simply returns.
When implementing GetMonitorList() and FreeMonitorList(), noticed that their original LVOs are already in use by StartScreenNotifyTagList() and EndScreenNotify() functions. LVOs do not conflict with anything except two private AmigaOS v3 functions, which are used for adding DisplayInfo to the system. They are used by disk-based video mode drivers (contents of DEVS:Monitors).
The topic of extending 3.x libraries in a way not to hurt MOS/OS4 future compatibility is on the list of ABI V1
It was proposed to move as much as possible out of core libraries and place into some new components. For example these region manipulation functions could be moved into something like gfxutils.library. In addition this would decrease size of kickstart.
The only thing that bothers me: why are these extensions there? Who uses them? Or they are here "just in case"? The latter case is not good IMHO. IMHO all API extensions should be carefully designed, and not implemented as hacks just because some single application's author says that it would be a nice thing. If we examine these functions carefully, we can note that they are 99% duplication of code. And for example AndRegionRegionND() is in fact just:
struct Region *r3 = CopyRegion(r1); AndRegionRegion(r3, r2);
Yes, looking at the internals we can consider CopyRegion() a really useful function because it's not just two or three lines of code and there's really no replacement. So it has rights to live. This way we can decrease number of extensions.
Another example of this is SetError() function of dos.library. Internally it's two lines of code. Additionally it happens to be used by startup code. Currently it's not bad, but when m68k AROS appears, this means that applications built under m68k AROS will have no chance to run on for example classic AmigaOS, even with version checks. This function could be moved to libamiga.a at all. Additionally it could be renamed to SetErrorOutput() for AmigaOS4 compatibility.
- monitorclass is a BOOPSI class, it's not my invention.
- In order to create a BOOPSI object, we have to call intuition.library/NewObject(). It doesn't matter who will do it.
- In AROS adding a display driver is done by graphics.library/AddDisplayDriverA(), which is AROS-specific function (since there's no public equivalent of this function in other OSes).
- Creation of monitorclass object needs to be tied somehow with AddDisplayDriverA(). This causes the situation you dislike.
- If we implement some another, AROS-specific API, then we in fact don't need monitorclass, we can directly base on this API.
GetDisplayInfoData() doesn't provide this composition capability information.
If you followed the development, you may remember the previous version of this. Sync objects and MonitorSpecs were separate entities. graphics.library enumerated all syncs and created corresponding MonitorSpecs for them. There were following flaws:
- A need to sync up data every time after some change in MonitorSpec or sync.
- Data duplication (50% of sync object data duplicated MonitorSpec data).
- Need for excessive code to copy duplicated data forth and back.
- Excessive memory fragmentation due to (2).
Additionally, there was strict relation "one sync == one MonitorSpec". Sync object needed to know about associated MonitorSpec and MonitorSpec needed to know about associated sync. This further gave me an idea that MonitorSpec could be completely merged together. This way it would be managed in much better way (for example better implementation of variable/constant sync objects and better handling of MonitorSpecs without SpecialMonitor addition). The solution to make MonitorSpecs self-registering became quite obvious. This allowed to get rid of addition/removal code. When a display driver is disposed, its sync objects are disposed, and this causes automatic removal of associated MonitorSpecs from graphics.library list.
GfxNew() and GfxFree() are also invented by Commodore. In fact could use AllocMem()/FreeMem(), but with some code duplication, decided not to do it.
However internally operations on user interface are turned into operations on bitmaps. Operations on screens are turned into operations on ViewPorts. Some functionality is missing from graphics.library but is present in HIDD API, and it's safe to use it (these are information query calls, not rendering calls).
GetDisplayInfoData() returns needed pointers in reserved fields (this originally was implemented for CGX). However here we have one little quirk...
A display driver registers itself using graphics.library/AddDisplayDriverA(). But how will Intuition know that a new driver was registered (in order to create a monitorclass object) ?
There are again the following solutions:
- Drivers could call Intuition's function (which in turn will call graphics function).
- Graphics could call some Intuition's function in order to create a monitorclass object.
- Intuition could patch AddDisplayDriverA() in order to add own code.
- Display drivers can create BOOPSI objects themselves.
My opinions on them:
- This would really make graphics inoperative without Intuition (no way to add a display driver). In addition it would not decrease amount of AROS-specific extensions (look at include/graphics/driver.h - these are absolutely needed things, and their amount will grow).
- This is what i was going to do.
- Hate OS patching itself!!! Especially when this can be done without patches. Additionally graphics.library needs to keep a pointer to monitorclass object in its DisplayInfoDataBase (in order for Intuition to be able to look it up by mode ID).
- This causes code duplication in every driver and this sucks. This approach tends to turn into what is done in OS 3.1 with display driver.
In addition i would have to add this code to every display driver, this is time-consuming work breaking backwards compatibility.
Believe in MorphOS all this is managed by cgxsystem.library. There (like in classic AmigaOS) DisplayInfoDataBase is just a static list, and Intuition seems to have another static list. CGX just creates needed items and pushes all them into respective lists. We differ only in one place - we have no cgxsystem.library (which is entirely private to the CGX anyway) and this functionality is merged into graphics.library.
AROS is not adding new public library functions. It's adding a new public BOOPSI class, which is quite less prone to conflicts, especially if it is decided to implement MorphOS binary compatibility.
It looks like graphics' story is no less interesting than dos' one. Some things tell me that Amiga graphics.library API is just a wrapper on top of something. For example internal implementation of GetDisplayInfoData() is likely taglist-based, and looks like there are more options to query.
Read more here
There are two things about graphics.library code,
- there is already support planar bitmaps in RAM (including ChipRAM)
- graphics.library allocates temporary planarbm hidd objects from the pool and attaches bitmaps to them for doing operations on them.
This means that you could:
- Add some attributes to planarbm class for processing displayable bitmaps (those which have copperlists). Not only bitmap but also a copperlist should be attached to temporary objects then.
- Implement a driver which would be able to display such objects using Show or ShowViewPorts method.
For ABI v1 all fields in struct QueryHeader in graphics/displayinfo.h should be changed from ULONG to IPTR. This is because originally this structure is two TagItems. Under certain conditions it can be processed using taglist functions from utility.library.
RastPort cleanup and DeinitRastPort() de-mandation W.I.P.:
What do you do when you want to add some new feature and private space is full? The same as done now with ClipRect. Setting extended attribute allocates extension space. After this, yes, you need deinit. Added more private space on x86-64. !!! BINARY COMPATIBILITY BROKEN !!! Removed PatOrigin attributes to free up usable space in RastPort. See no rationale behind them, simply adjust pattern start address instead.
Pattern size is assumed to be equal to source bitmap. So, if the bitmap has size of (x, y), and we start not from (0, 0), but from some offset, where would it take extra pixels from? Well, such a feature could be implemented better as a separate function with extra arguments. Origin is for alignment of the pattern == like wraparound scrolling of the pattern. If for example you have a checkerfield pattern you may want to have it aligned in such a way that it "starts" exactly at the inner window area's (x,y) which depends on window border size because most windows are non-GZZ and (0,0) is over the window border.
Consider broken-by-design ClipRect removal. Nonfunctional in many cases, and gives lots of headache maintaining it. May be i was too harsh saying it. But, the first question. What was the rationale behind adding it ? Because in many cases having clipping support like this is easier and faster layers.libary/InstallClipRegion() sucks because when you for example install a clip region in a smart refresh layer which is partly hidden then this even may result in forth&back blits between layer cliprect bitmaps.
The main use I had in mind was for things like clipping Text() in multi column listviews, ie. where a lot of clippings may be done in a short time. Other OSes have it. But IMHO they have it because the philosophy of drawing is quite different. There's no backing store in those OSes. There is effectively no analog to Layers; when a window opens, it simply occupies part of the screen bitmap, and the hidden part goes to nowhere (yes, and the programmer has to redraw it every time). Like simple refresh windows in AOS (which are also the ones which work best in AROS, because smart refresh ones lack some optimization to avoid things like backing up/Restoring offscreen cliprect bitmaps even if a layer operation does not affect them at all). But nowadays even this OSes all support backing store because they need it for compositing.
if we install ClipRegion over a partially cover smart refresh window, two sets of obscured ClipRects are created. The first set is created from the whole window, and the second set represents first set intersected with ClipRegion. So, ClipRects from the second set are sub-clip-rects of the first one, and they have duplicated storage bitmaps. And every time the window is moved, we have to reassemble the pieces back, which requires two sets of blits. This is slow. But what if we extend ClipRects, making it possible to refer to a part of already existing bitmap? This way ClipRects from the second (clipped) set could reuse storage bitmaps from the first set. This would eliminate unneeded blits and reduce memory usage. Such optimization would make it working transparently for existing applications, unless some of them do rendering by manual walking through ClipRects. Additionally, ClipRegion allows to use more complex shapes than one rectangle.
Why headache? Because making it working correctly requires tons of new additions. Do you know about layers.library's DoHookClipRect() function? It's supposed to do the same as do_render_func() currently does. Just it ignores this ClipRect, it doesn't know about it. The general public, wishing to implement some complex operation on the RastPort, is expected to use it. And, if someone wants to set a ClipRect on the RastPort, this will make it working incorrectly. For special cases like this I would probably make a rastport flag changeable by SetRPAttrs() which tells a function like DoHookClipRects() whether to apply the rastport cliprect or not. The callback function itself is not supposed to have to deal with the rastport cliprect itself. added that some time after writing RPTAG_ClipRectangle stuff because it was an easy extension (no cliprectangle? -> assume bitmap bounds is cliprectangle) and I found it always stupid that apps could render outside bitmap.
- RastPort made self-contained. There's no more mandatory extra data which needs to be explicitly freed. GC objects are built inside the RastPort. Consequently, GC operations are much faster.
- CreateRastPort(), CloneRastPort(), FreeRastPort(), DeinitRastPort() moved to libarossupport, mainly to support old code. RastPort cleanup is still needed if ClipRect has been installed on it. This can be accomplished by FreeVec(rp->RP_Extra).
- Correctly imlemented RPTAG_PenMode, MorphOS-compatible.
AROS has a special feature which allows setting a clip rectangle for a rastport which can be also used for (rastports connected to) offscreen bitmaps. Use that to prevent rendering outside bitmap bounds (= memtrash/crash in AROS native and X11 error msg in AROS hosted/X11). May be it happened long time ago? I tested the change on Darwin-hosted with mungwall enabled. With X11 driver you will likely have an X11 pixmap being used for the bitmap, so no mem trashes - only X11 errors showing up.
The method HIDD_BM_PutPixel should use HIDDT_Pixel type as last argument. If 64bit compiler complains about loosing some portion of data due to 64bit (IPTR) to 32bit (HIDD_Pixel) scaling, then you need to fix body of your function in other way.
Point ExtendedNode.xln_Init to dummy function. Prevents WB2.0+ monitor driver crash. this xln_Init() function does. It gets two arguments: node pointer and flags. For MONITOR_SPEC_TYPE nodes flags value is put into ms_Flags member. Then, if MSF_REQUEST_SPECIAL bit is set, SpecialMonitor structure will be allocated and attached. So, this init function is responsible for setting some default values in the structure. I could implement it but decided not to do it because for AROS it's useless anyway.
Now about the "driver" itself. This program can be treated as part of graphics.library placed on disk. All it does is inserting data about display modes into graphics.library's mode database. The database is a structure pointed to by GfxBase->DisplayInfoDataBase. I started documenting things i figured out, bit had no time do to much. DisplayInfoDataBase documented here. All values in MonitorSpecs and mode ID properties are hardcoded constants. Some of them have different variants based on what chipset is specified by GfxBase->ChipRevBits. There's also a magic bit number 5 in GfxBase->Bugs. In fact this variable is some internal flags. If bit 5 is set, VGA drivers choose slightly different sets of constants. I guess this bit is set by VGAOnly program. There's also GfxBase->ProgData pointing to some stuff, i guess some chipset constants. Display drivers scan this memory, search for something in it, and copy into structure pointed to by VecInfo->Data of every display mode ID they create. I did not understand the exact purpose of these manipulations.
In fact i thought that if GfxBase->DisplayInfoDataBase is NULL, the driver will fail gracefully and will not do anything. Either i've mistaken or something is wrong. I think you just need to provide conditions for the driver to fail. It should neither insert own MonitorSpec nor attempt to insert database records. Populating mode DB is done using two private graphics.library functions: AddDisplayInfoData() and SetDisplayInfoData(). Their LVOs are occupied by AROS-specific functions. I don't remember values but you can google for function names, you'll find them easily. I also thought about a possibility to make these drivers working, but:
- It requires to reverse engineer and to reimplement a major part of AmigaOS graphics.library which can be a copyright breach.
- It's much easier to reimplement the whole thing in AROS own way. using AROS own infrastructure. If you look at AmigaOS implementation of mode database, you'll understand that AROS implementation is way better.
AROS PolyDraw, the rkm say, count is a word value, but on AROS its a long value. On MOS and OS4 it seem too a word value, because amiblitz work ok on MOS and OS4. Amiblitz fail on AROS 68k with endless drawing lines, because upper register contain high random value. Maybe its wrong in the includes then, but in the amiga developer CD file stand this. e.g. void PolyDraw( struct RastPort *, WORD, WORD * );
struct ViewPort {
struct ViewPort *Next;
struct ColorMap *ColorMap; /* table of colors for this viewport, if nil MakeVPort assumes default */
struct CopList *DspIns; /* user by MakeView() */
struct CopList *SprIns; /* used by sprite stuff */
struct CopList *ClrIns; /* used by sprite stuff */
struct UCopList *UCopIns; /* User copper list */
WORD DWidth,DHeight;
WORD DxOffset,DyOffset;
UWORD Modes;
UBYTE SpritePriorities; /* used by makevp */
UBYTE ExtendedModes;
struct RasInfo *RasInfo;
};
struct View {
struct ViewPort *ViewPort;
struct cprlist *LOFCprList; /* used for interlaced and noninterlaced */
struct cprlist *SHFCprList; /* only used during interlace */
WORD DyOffset,DxOffset; /* complete View positioning offsets are +- adjustments to standard #s */
UWORD Modes; /* such as INTERLACE, GENLOC */
};
/* these structures are obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewExtra {
struct ExtendedNode n;
struct View *View; /* backwards link */
struct MonitorSpec *Monitor; /* monitors for this view */
};
/* this structure is obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewPortExtra {
struct ExtendedNode n;
struct ViewPort *ViewPort; /* backwards link */
struct Rectangle DisplayClip; /* makevp display clipping information */
};
#define EXTEND_VSTRUCT 0x1000 /* unused bit in Modes field of View */
/* defines used for Modes in IVPargs */
#define GENLOCK_VIDEO 0x0002
#define LACE 0x0004
#define SUPERHIRES 0x0020
#define PFBA 0x0040
#define EXTRA_HALFBRITE 0x0080
#define GENLOCK_AUDIO 0x0100
#define DUALPF 0x0400
#define HAM 0x0800
#define EXTENDED_MODE 0x1000
#define VP_HIDE 0x2000
#define SPRITES 0x4000
#define HIRES 0x8000
#define VPF_A2024 0x40
#define VPF_AGNUS 0x20
#define VPF_TENHZ 0x20
struct RasInfo /* used by callers to and InitDspC() */ {
struct RasInfo *Next; /* used for dualpf */
struct BitMap *BitMap;
WORD RxOffset,RyOffset; /* scroll offsets in this BitMap */
};
struct ColorMap {
UBYTE Flags;
UBYTE Type;
UWORD Count;
APTR ColorTable;
struct ViewPortExtra *cm_vpe;
UWORD *TransparencyBits;
UBYTE TransparencyPlane;
UBYTE reserved1;
UWORD reserved2;
struct ViewPort *cm_vp;
APTR NormalDisplayInfo;
APTR CoerceDisplayInfo;
struct TagItem *cm_batch_items;
ULONG VPModeID;
};
/* if Type == 0 then ColorMap is V1.2/V1.3 compatible */
/* if Type != 0 then ColorMap is V36 compatible */
#define COLORMAP_TYPE_V1_2 0x00
#define COLORMAP_TYPE_V1_4 0x01
#define COLORMAP_TYPE_V36 COLORMAP_TYPE_V1_4 /* use this definition */
/* Flags variable */
#define COLORMAP_TRANSPARENCY 0x01
#define COLORPLANE_TRANSPARENCY 0x02
#define BORDER_BLANKING 0x04
#define BORDER_NOTRANSPARENCY 0x08
#define VIDEOCONTROL_BATCH 0x10
#define USER_COPPER_CLIP 0x20
struct ExtendedNode {
struct Node *xln_Succ;
struct Node *xln_Pred;
UBYTE xln_Type;
BYTE xln_Pri;
char *xln_Name;
UBYTE xln_Subsystem;
UBYTE xln_Subtype;
LONG xln_Library;
LONG (*xln_Init)();
};
#define SS_GRAPHICS 0x02
#define VIEW_EXTRA_TYPE 1
#define VIEWPORT_EXTRA_TYPE 2
#define SPECIAL_MONITOR_TYPE 3
#define MONITOR_SPEC_TYPE 4
struct MonitorSpec {
struct ExtendedNode ms_Node;
UWORD ms_Flags;
LONG ratioh;
LONG ratiov;
UWORD total_rows;
UWORD total_colorclocks;
UWORD DeniseMaxDisplayColumn;
UWORD BeamCon0;
UWORD min_row;
struct SpecialMonitor *ms_Special;
UWORD ms_OpenCount;
LONG (*ms_transform)();
LONG (*ms_translate)();
LONG (*ms_scale)();
UWORD ms_xoffset;
UWORD ms_yoffset;
struct Rectangle ms_LegalView;
LONG (*ms_maxoscan)(); /* maximum legal overscan */
LONG (*ms_videoscan)(); /* video display overscan */
UWORD DeniseMinDisplayColumn;
ULONG DisplayCompatible;
struct List DisplayInfoDataBase;
struct SignalSemaphore DisplayInfoDataBaseSemaphore;
ULONG ms_reserved00;
ULONG ms_reserved01;
};
struct SpecialMonitor {
struct ExtendedNode spm_Node;
UWORD spm_Flags;
int (*do_monitor)();
int (*reserved1)();
int (*reserved2)();
int (*reserved3)();
struct AnalogSignalInterval hblank;
struct AnalogSignalInterval vblank;
struct AnalogSignalInterval hsync;
struct AnalogSignalInterval vsync;
};
[edit] Functions
LONG BltBitMap(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, ULONG mask, PLANEPTR tempA) void BltTemplate(PLANEPTR source, LONG xSrc, LONG srcMod, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize) void BltBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm) void BltMaskBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, PLANEPTR bltMask) void BltRastPortBitMap(struct RastPort *srcRastPort, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, LONG xDest, LONG yDest, ULONG xSize, ULONG ySize, ULONG minterm) BOOL InitRastPort(struct RastPort *rp) void InitVPort(struct ViewPort *vp) ULONG MrgCop(struct View *view) ULONG MakeVPort(struct View *view, struct ViewPort *viewport) void LoadView(struct View *view) void WaitBlit() void SetRast(struct RastPort *rp, ULONG pen) void Move(struct RastPort *rp, WORD x, WORD y) void Draw(struct RastPort *rp, LONG x, LONG y) ULONG AreaMove(struct RastPort *rp, WORD x, WORD y) ULONG AreaDraw(struct RastPort *rp, WORD x, WORD y) LONG AreaEnd(struct RastPort *rp) void WaitTOF() void QBlit(struct bltnode *bn) void InitArea(struct AreaInfo *areainfo, void *buffer, WORD maxvectors) void SetRGB4(struct ViewPort *vp, ULONG n, ULONG r, ULONG g, ULONG b) void QBSBlit(struct bltnode *bn) void BltClear(void *memBlock, ULONG bytecount, ULONG flags) void RectFill(struct RastPort *rp, LONG xMin, LONG yMin, LONG xMax, LONG yMax) void BltPattern(struct RastPort *rp, PLANEPTR mask, LONG xMin, LONG yMin, LONG xMax, LONG yMax, ULONG byteCnt) void DrawEllipse(struct RastPort *rp, LONG xCenter, LONG yCenter, LONG a, LONG b) ULONG AreaEllipse(struct RastPort *rp, WORD cx, WORD cy, WORD a, WORD b) void LoadRGB4(struct ViewPort *vp, UWORD *colors, LONG count) LONG ReadPixel(struct RastPort *rp, LONG x, LONG y) LONG WritePixel(struct RastPort *rp, LONG x, LONG y) BOOL Flood(struct RastPort *rp, ULONG mode, LONG x, LONG y) void PolyDraw(struct RastPort *rp, LONG count, WORD *polyTable) void SetAPen(struct RastPort *rp, ULONG pen) void SetBPen(struct RastPort *rp, ULONG pen) void SetDrMd(struct RastPort *rp, ULONG drawMode) void InitView(struct View *view) void InitBitMap(struct BitMap *bm, BYTE depth, UWORD width, UWORD height) void ScrollRaster(struct RastPort *rp, LONG dx, LONG dy, LONG xMin, LONG yMin, LONG xMax, LONG yMax) PLANEPTR AllocRaster(ULONG width, ULONG height) (D0, D1) void FreeRaster(PLANEPTR p, ULONG width, ULONG height) (A0, D0, D1) BOOL AttemptLockLayerRom(struct Layer *l) (A5) struct ExtendedNode *GfxNew(ULONG node_type) (D0) void GfxFree(struct ExtendedNode *node) (A0) void GfxAssociate(void *pointer, struct ExtendedNode *node) (A0, A1) void BitMapScale(struct BitScaleArgs *bitScaleArgs) (A0) UWORD ScalerDiv(UWORD factor, UWORD numerator, UWORD denominator) (D0, D1, D2) void TextExtent(struct RastPort *rp, CONST_STRPTR string, ULONG count, struct TextExtent *textExtent) ULONG TextFit(struct RastPort *rp, CONST_STRPTR string, ULONG strLen, struct TextExtent *textExtent, struct TextExtent *constrainingExtent, LONG strDirection, ULONG constrainingBitWidth, ULONG constrainingBitHeight) struct ExtendedNode *GfxLookUp(void *pointer) (A0) ULONG VideoControl(struct ColorMap *cm, struct TagItem *tags) (A0, A1) struct MonitorSpec *OpenMonitor(STRPTR monitor_name, ULONG display_id) (A1, D0) LONG CloseMonitor(struct MonitorSpec *monitor_spec) (A0) DisplayInfoHandle FindDisplayInfo(ULONG ID) (D0) ULONG NextDisplayInfo(ULONG last_ID) (D0) ULONG GetDisplayInfoData(DisplayInfoHandle handle, UBYTE *buf, ULONG size, ULONG tagID, ULONG ID) void FontExtent(struct TextFont *font, struct TextExtent *fontExtent) (A0, A1) LONG ReadPixelLine8(struct RastPort *rp, LONG xstart, LONG ystart, ULONG width, UBYTE *array, struct RastPort *tempRP) (A0, D0, D1, D2, A2, A1) LONG WritePixelLine8(struct RastPort *rp, LONG xstart, LONG ystart, ULONG width, UBYTE *array, struct RastPort *tempRP) (A0, D0, D1, D2, A2, A1) LONG ReadPixelArray8(struct RastPort *rp, LONG xstart, LONG ystart, LONG xstop, LONG ystop, UBYTE *array, struct RastPort *temprp) (A0, D0, D1, D2, D3, A2, A1) LONG WritePixelArray8(struct RastPort *rp, ULONG xstart, ULONG ystart, ULONG xstop, ULONG ystop, UBYTE *array, struct RastPort *temprp) (A0, D0, D1, D2, D3, A2, A1) ULONG GetVPModeID(struct ViewPort *vp) ULONG ModeNotAvailable(ULONG modeID) WORD WeighTAMatch(struct TextAttr *reqTextAttr, struct TextAttr *targetTextAttr, struct TagItem *targetTags) void EraseRect(struct RastPort *rp, LONG xMin, LONG yMin, LONG xMax, LONG yMax) ULONG ExtendFont(struct TextFont *font, struct TagItem *fontTags) void StripFont(struct TextFont *font) UWORD CalcIVG(struct View *View, struct ViewPort *ViewPort) LONG AttachPalExtra(struct ColorMap *cm, struct ViewPort *vp) LONG ObtainBestPenA(struct ColorMap *cm, ULONG r, ULONG g, ULONG b, struct TagItem *tags) struct Region *ClearRegionRegionND(struct Region *R1, struct Region *R2) void SetRGB32(struct ViewPort *vp, ULONG n, ULONG r, ULONG g, ULONG b) ULONG GetAPen(struct RastPort *rp) ULONG GetBPen(struct RastPort *rp) ULONG GetDrMd(struct RastPort *rp) ULONG GetOutlinePen(struct RastPort *rp) void LoadRGB32(struct ViewPort *vp, const ULONG *table) ULONG SetChipRev(ULONG ChipRev) void SetABPenDrMd(struct RastPort *rp, ULONG apen, ULONG bpen, ULONG drawMode) void GetRGB32(struct ColorMap *cm, ULONG firstcolor, ULONG ncolors, ULONG *table) struct BitMap *AllocBitMap(ULONG sizex, ULONG sizey, ULONG depth, ULONG flags, struct BitMap *friend_bitmap) (D0, D1, D2, D3, A0) void FreeBitMap(struct BitMap *bm) (A0) LONG GetExtSpriteA(struct ExtSprite *sprite, struct TagItem *tags) (A2, A1) ULONG CoerceMode(struct ViewPort *RealViewPort, ULONG MonitorID, ULONG Flags) (A0, D0, D1) void ChangeVPBitMap(struct ViewPort *vp, struct BitMap *bm, struct DBufInfo *db) (A0, A1, A2) void ReleasePen(struct ColorMap *cm, ULONG n) (A0, D0) LONG ObtainPen(struct ColorMap *cm, ULONG n, ULONG r, ULONG g, ULONG b, ULONG flags) (A0, D0, D1, D2, D3, D4) IPTR GetBitMapAttr(struct BitMap *bitmap, ULONG attribute) (A0, D1) struct DBufInfo *AllocDBufInfo(struct ViewPort *vp) (A0) void FreeDBufInfo(struct DBufInfo *db) (A1) ULONG SetOutlinePen(struct RastPort *rp, ULONG pen) (A0, D0) ULONG SetWriteMask(struct RastPort *rp, ULONG mask) (A0, D0) void SetMaxPen(struct RastPort *rp, ULONG maxpen) (A0, D0) void SetRGB32CM(struct ColorMap *cm, ULONG n, ULONG r, ULONG g, ULONG b) (A0, D0, D1, D2, D3) void ScrollRasterBF(struct RastPort *rp, LONG dx, LONG dy, LONG xMin, LONG yMin, LONG xMax, LONG yMax) (A1, D0, D1, D2, D3, D4, D5) ULONG FindColor(struct ColorMap *cm, ULONG r, ULONG g, ULONG b, ULONG maxpen) (A3, D1, D2, D3, D4) struct ExtSprite *AllocSpriteDataA(struct BitMap *bitmap, struct TagItem *tagList) (A2, A1) LONG ChangeExtSpriteA(struct ViewPort *vp, struct ExtSprite *oldsprite, struct ExtSprite *newsprite, struct TagItem *tags) (A0, A1, A2, A3) void FreeSpriteData(struct ExtSprite *extsp) (A2) void SetRPAttrsA(struct RastPort *rp, struct TagItem *tags) (A0, A1) void GetRPAttrsA(struct RastPort *rp, struct TagItem *tags) (A0, A1) ULONG BestModeIDA(struct TagItem *TagItems) (A0) void WriteChunkyPixels(struct RastPort *rp, LONG xstart, LONG ystart, LONG xstop, LONG ystop, UBYTE *array, LONG bytesperrow) (A0, D0, D1, D2, D3, A2, D4) struct RastPort *CreateRastPort() () struct RastPort *CloneRastPort(struct RastPort *rp) (A1) void DeinitRastPort(struct RastPort *rp) (A1) void FreeRastPort(struct RastPort *rp) (A1) LONG AddDisplayDriverA(APTR gfxhidd, struct TagItem *tags) (A0, A1) LONG WritePixels8(struct RastPort *rp, UBYTE *array, ULONG modulo, LONG xstart, LONG ystart, LONG xstop, LONG ystop, HIDDT_PixelLUT *pixlut, BOOL do_update) LONG FillRectPenDrMd(struct RastPort *rp, LONG x1, LONG y1, LONG x2, LONG y2, HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update) LONG DoRenderFunc(struct RastPort *rp, Point *src, struct Rectangle *rr, RENDERFUNC render_func, APTR funcdata, BOOL do_update) LONG DoPixelFunc(struct RastPort *rp, LONG x, LONG y, PIXELFUNC render_func, APTR funcdata, BOOL do_update) struct Region *XorRegionRegionND(struct Region *R1, struct Region *R2) struct Region *XorRectRegionND(struct Region *Reg, struct Rectangle *Rect) BOOL ClearRegionRegion(struct Region *R1, struct Region *R2) struct Region *CopyRegion(struct Region *region) BOOL AreRegionsEqual(struct Region *R1, struct Region *R2) BOOL IsPointInRegion(struct Region *Reg, WORD x, WORD y) BOOL ScrollRegion(struct Region *region, struct Rectangle *rect, WORD dx, WORD dy) void SwapRegions(struct Region *region1, struct Region *region2) BOOL AndRectRect(struct Rectangle *rect1, struct Rectangle *rect2, struct Rectangle *intersect) struct Region *NewRectRegion(WORD MinX, WORD MinY, WORD MaxX, WORD MaxY) BOOL SetRegion(struct Region *src, struct Region *dest) void AndRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1) BOOL OrRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1) struct Region *NewRegion() () BOOL ClearRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1) void ClearRegion(struct Region *region) (A0) void DisposeRegion(struct Region *region) (A0) BOOL XorRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1) struct Region *OrRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1) struct Region *ClearRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1) struct Region *OrRegionRegionND(struct Region *R1, struct Region *R2) (A0, A1) BOOL OrRegionRegion(struct Region *R1, struct Region *R2) (A0, A1) BOOL XorRegionRegion(struct Region *R1, struct Region *R2) (A0, A1) BOOL AndRegionRegion(struct Region *R1, struct Region *R2) (A0, A1) struct Region *AndRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1) struct Region *AndRegionRegionND(struct Region *R1, struct Region *R2) (A0, A1) WORD TextLength(struct RastPort *rp, CONST_STRPTR string, ULONG count) void Text(struct RastPort *rp, CONST_STRPTR string, ULONG count) void SetFont(struct RastPort *rp, struct TextFont *textFont) struct TextFont *OpenFont(struct TextAttr *textAttr) void CloseFont(struct TextFont *textFont) ULONG AskSoftStyle(struct RastPort *rp) ULONG SetSoftStyle(struct RastPort *rp, ULONG style, ULONG enable) void ClearEOL(struct RastPort *rp) void ClearScreen(struct RastPort *rp) void AskFont(struct RastPort *rp, struct TextAttr *textAttr) void AddFont(struct TextFont *textFont) void RemFont(struct TextFont *textFont) void AddBob(struct Bob *bob, struct RastPort *rp) void AddVSprite(struct VSprite *vs, struct RastPort *rp) void DoCollision(struct RastPort *rp) void DrawGList(struct RastPort *rp, struct ViewPort *vp) void InitGels(struct VSprite *head, struct VSprite *tail, struct GelsInfo *GInfo) void InitMasks(struct VSprite *vs) void RemIBob(struct Bob *bob, struct RastPort *rp, struct ViewPort *vp) void RemVSprite(struct VSprite *vs) void SetCollision(ULONG num, VOID_FUNC routine, struct GelsInfo *GInfo) void SortGList(struct RastPort *rp) void AddAnimOb(struct AnimOb *anOb, struct AnimOb **anKey, struct RastPort *rp) void Animate(struct AnimOb **anKey, struct RastPort *rp) BOOL GetGBuffers(struct AnimOb *anOb, struct RastPort *rp, BOOL db) void InitGMasks(struct AnimOb *anOb) WORD GetSprite(struct SimpleSprite *sprite, WORD pick) void FreeSprite(WORD pick) void ChangeSprite(struct ViewPort *vp, struct SimpleSprite *s, void *newdata) void MoveSprite(struct ViewPort *vp, struct SimpleSprite *sprite, WORD x, WORD y) void LockLayerRom(struct Layer *l) void UnlockLayerRom(struct Layer *l) void SyncSBitMap(struct Layer *l) void CopySBitMap(struct Layer *l) void OwnBlitter() void DisownBlitter() struct TmpRas *InitTmpRas(struct TmpRas *tmpras, void *buffer, ULONG size) void SetRGB4CM(struct ColorMap *cm, WORD n, UBYTE r, UBYTE g, UBYTE b) (A0, D0, D1, D2, D3) void FreeVPortCopLists(struct ViewPort *vp) void FreeCopList(struct CopList *coplist) void ClipBlit(struct RastPort *srcRP, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, UBYTE minterm) void FreeCprList(struct cprlist *cprList) struct ColorMap *GetColorMap(ULONG entries) void FreeColorMap(struct ColorMap *colormap) ULONG GetRGB4(struct ColorMap *colormap, LONG entry) void ScrollVPort(struct ViewPort *vp) (A0) struct CopList *UCopperListInit(struct UCopList *ucl, WORD n) void FreeGBuffers(struct AnimOb *anOb, struct RastPort *rp, BOOL db) void CBump(struct UCopList *ucl) void CMove(struct UCopList *ucl, void *reg, WORD value) void CWait(struct UCopList *ucl, WORD v, WORD h) LONG VBeamPos() void WaitBOVP(struct ViewPort *vp) void ShowImminentReset()
This page may need to be