amiga-bootcamp/08_graphics/rastport.md
Ilia Sharin f61c26b542 Expand documentation suite: 30+ articles enriched with diagrams, code examples, and hardware details
Graphics: text_fonts (bitmap layout, styles), sprites (DMA, multiplexing), gfx_base (chipset detection), rastport (draw modes, clipping), ham_ehb (mermaid fixes), display_modes (HAM palettes)

Devices: scsi (per-model interfaces, Gayle limits, CD-ROM, native vs vendor drivers), console (ANSI sequences, CON:/RAW:), parallel (CIA registers, pinout), timer (resource exhaustion), gameport (quadrature, XOR state)

Libraries: workbench (WBStartup, AppWindow/Icon/MenuItem), rexxsyslib (ARexx port hosting, command parsing), diskfont (font directory, colour fonts), keymap (rawkey codes, dead keys), locale (catalogue system, date formatting), layers (ClipRect, refresh types), utility (TagItem chains), icon (DiskObject, ToolTypes), iffparse (IFF structure, ByteRun1), expansion (Zorro AutoConfig)

Networking: tcp_ip_stacks (major rewrite - Amiga vs Unix architecture, SANA-II pipeline, PPP/SLIP dial-up, Ethernet cards, MiSTer), bsdsocket (pure API ref), sana2 (buffer hooks, driver requirements), protocols (all code examples). Deduplicated overlap between the three files.

Toolchain: debugging (Enforcer patterns, SnoopDOS, GDB remote, kprintf checklist), sasc (pragma encoding, __saveds idioms), stormc (NEW - StormC IDE, C++, PowerPC)

References: error_codes (DOS, Exec, trackdisk, Intuition error tables)
Driver development: rtg_driver (Native driver analysis, P96 tuning)

All 22 README indexes updated. Root README synced with stormc.md entry.
2026-04-23 21:37:26 -04:00

13 KiB
Raw Blame History

← Home · Graphics

RastPort — Drawing Primitives and Layers

Overview

RastPort is the primary drawing context in AmigaOS — the equivalent of a "device context" (Windows) or "graphics context" (X11). All graphics primitives (pixel, line, rectangle, polygon, text) operate through a RastPort, which bundles together a target BitMap, drawing pen colours, patterns, font, draw mode, and an optional Layer for clipping.

Every Intuition window and screen has its own RastPort. When you draw into a window, you're drawing through its RastPort.

flowchart TD
    subgraph "RastPort — Drawing Context"
        RP["struct RastPort"]
        RP --> BM["BitMap<br/>(pixel storage)"]
        RP --> PEN["Pens<br/>FgPen, BgPen, AOlPen"]
        RP --> DM["DrawMode<br/>JAM1/JAM2/COMPLEMENT"]
        RP --> FONT["TextFont<br/>(current font)"]
        RP --> PAT["AreaPtrn<br/>(fill pattern)"]
        RP --> LAYER["Layer<br/>(clipping region)"]
        RP --> CP["cp_x, cp_y<br/>(cursor position)"]
    end

    APP["Application Code"] -->|"SetAPen, Move,<br/>Draw, RectFill,<br/>Text, ClipBlit"| RP
    RP -->|"Drawing operations"| BM
    LAYER -->|"Clips to visible region"| BM

    style RP fill:#e8f4fd,stroke:#2196f3,color:#333
    style BM fill:#c8e6c9,stroke:#2e7d32,color:#333
    style LAYER fill:#fff9c4,stroke:#f9a825,color:#333

struct RastPort

/* graphics/rastport.h — NDK39 */
struct RastPort {
    struct Layer   *Layer;       /* associated layer (NULL = no clipping) */
    struct BitMap  *BitMap;      /* target bitmap */
    UWORD          *AreaPtrn;   /* area fill pattern */
    struct TmpRas  *TmpRas;     /* temp raster for area fills/floods */
    struct AreaInfo *AreaInfo;   /* area fill vertex buffer */
    struct GelsInfo *GelsInfo;   /* GEL (BOB/VSprite) list */
    UBYTE           Mask;        /* plane mask (which planes to draw to) */
    BYTE            FgPen;       /* foreground pen colour index */
    BYTE            BgPen;       /* background pen colour index */
    BYTE            AOlPen;      /* area outline pen */
    BYTE            DrawMode;    /* JAM1, JAM2, COMPLEMENT, INVERSVID */
    BYTE            AreaPtSz;    /* area pattern size (log2) */
    BYTE            linpatcnt;   /* line pattern counter */
    BYTE            dummy;
    UWORD           Flags;       /* FRST_DOT etc. */
    UWORD           LinePtrn;    /* 16-bit line dash pattern */
    WORD            cp_x, cp_y;  /* current pen position */
    UWORD           minterms[8];
    WORD            PenWidth;
    WORD            PenHeight;
    struct TextFont *Font;       /* current text font */
    UBYTE           AlgoStyle;   /* algorithmic style flags */
    UBYTE           TxFlags;
    UWORD           TxHeight;
    UWORD           TxWidth;
    UWORD           TxBaseline;
    WORD            TxSpacing;
    APTR           *RP_User;
    /* ... */
};

Draw Modes

The draw mode controls how new pixels combine with existing content:

flowchart LR
    subgraph "JAM1 — Transparent"
        J1BG["Background<br/>unchanged"] --- J1FG["Foreground<br/>drawn with FgPen"]
    end

    subgraph "JAM2 — Opaque"
        J2BG["Background<br/>drawn with BgPen"] --- J2FG["Foreground<br/>drawn with FgPen"]
    end

    subgraph "COMPLEMENT — XOR"
        XBG["All pixels<br/>XOR with existing"]
    end
#define JAM1        0   /* draw FgPen only; background pixels are NOT touched */
#define JAM2        1   /* draw FgPen AND BgPen — fully opaque */
#define COMPLEMENT  2   /* XOR all drawn pixels with existing content */
#define INVERSVID   4   /* swap foreground/background (for text inverse) */
Mode Text Example Fill Example Use Case
JAM1 Characters drawn, background shows through Solid fill with FgPen Transparent overlays, labels on images
JAM2 Characters + background box drawn Same as JAM1 for fills Opaque text on busy backgrounds
COMPLEMENT XOR of text pixels with screen XOR fill Rubber-band selection, dragging cursors
`JAM1 INVERSVID` Background drawn with FgPen, chars transparent

Drawing Primitives

Pen and Position Setup

/* Set pen colours: */
SetAPen(rp, 1);       /* foreground = colour register 1 */
SetBPen(rp, 0);       /* background = colour register 0 */
SetDrMd(rp, JAM1);    /* transparent background mode */

/* OS 3.0+ — use named pen for correct Workbench colours: */
SetAPen(rp, screen->RastPort.BitMap->Depth > 1 ?
    ObtainBestPen(screen->ViewPort.ColorMap,
                  0xFF000000, 0x00000000, 0x00000000,  /* red */
                  OBP_Precision, PRECISION_GUI,
                  TAG_DONE) : 1);

Lines and Pixels

flowchart LR
    M["Move(rp, 10, 20)"] -->|"sets cp_x, cp_y"| D1["Draw(rp, 100, 20)"]
    D1 -->|"draws line,<br/>updates cp"| D2["Draw(rp, 100, 80)"]
    D2 -->|"draws line,<br/>updates cp"| D3["Draw(rp, 10, 80)"]
    D3 -->|"draws line,<br/>updates cp"| D4["Draw(rp, 10, 20)"]

    style M fill:#e8f4fd,stroke:#2196f3,color:#333
/* Move cursor (no drawing): */
Move(rp, 100, 50);

/* Draw line from current position to (x,y), update cp: */
Draw(rp, 200, 100);
/* cp is now (200, 100) — next Draw continues from here */

/* Draw a connected polygon: */
Move(rp, 10, 10);
Draw(rp, 100, 10);    /* top edge */
Draw(rp, 100, 80);    /* right edge */
Draw(rp, 10, 80);     /* bottom edge */
Draw(rp, 10, 10);     /* close: left edge */

/* Single pixel: */
WritePixel(rp, 160, 120);
LONG colour = ReadPixel(rp, 160, 120);

/* Dashed lines: */
SetDrPt(rp, 0xF0F0);  /* 16-bit pattern: 1111000011110000 */
Draw(rp, 200, 100);    /* draws dashed line */
SetDrPt(rp, 0xFFFF);  /* restore solid */

Rectangles and Fills

/* Solid filled rectangle (uses FgPen + DrawMode): */
SetAPen(rp, 3);
RectFill(rp, 10, 10, 100, 50);  /* x1,y1 to x2,y2 inclusive */

/* Erase to background (clear a region): */
SetAPen(rp, 0);
SetDrMd(rp, JAM1);
RectFill(rp, 0, 0, 319, 255);

/* Scroll a region (with clear): */
ScrollRaster(rp, dx, dy, x1, y1, x2, y2);
/* Shifts content by (dx,dy); exposed area cleared to BgPen */

Text Rendering

flowchart LR
    ATTR["TextAttr<br/>(name, size)"] -->|"OpenFont /<br/>OpenDiskFont"| TF["TextFont"]
    TF -->|"SetFont(rp, font)"| RP["RastPort"]
    RP -->|"Move + Text"| OUT["Rendered text<br/>on bitmap"]
/* Set font: */
struct TextAttr ta = {"topaz.font", 8, 0, FPF_ROMFONT};
struct TextFont *font = OpenFont(&ta);
SetFont(rp, font);

/* Render text at position: */
Move(rp, 20, 30);          /* baseline position */
Text(rp, "Hello Amiga", 11);

/* Measure text width before rendering (for alignment): */
UWORD width = TextLength(rp, "Hello Amiga", 11);
/* Right-align: */
Move(rp, screenWidth - width - 10, 30);
Text(rp, "Hello Amiga", 11);

/* Bold/italic (algorithmic): */
UWORD supported = AskSoftStyle(rp);
SetSoftStyle(rp, FSF_BOLD | FSF_ITALIC, supported);
Text(rp, "Bold Italic", 11);
SetSoftStyle(rp, 0, supported);  /* restore */

Area Fills (Polygons)

/* Area fills require setup: TmpRas + AreaInfo */
UBYTE areaBuffer[5 * 5];  /* 5 vertices × 5 bytes each */
struct AreaInfo areaInfo;
InitArea(&areaInfo, areaBuffer, 5);
rp->AreaInfo = &areaInfo;

PLANEPTR tmpRasData = AllocRaster(320, 256);
struct TmpRas tmpRas;
InitTmpRas(&tmpRas, tmpRasData, RASSIZE(320, 256));
rp->TmpRas = &tmpRas;

/* Draw a filled triangle: */
AreaMove(rp, 100, 10);     /* first vertex */
AreaDraw(rp, 200, 180);    /* second vertex */
AreaDraw(rp, 20, 180);     /* third vertex */
AreaEnd(rp);               /* fill and close */

/* Cleanup: */
FreeRaster(tmpRasData, 320, 256);

Flood Fill

/* Flood fill from a seed point: */
/* Requires TmpRas (same setup as area fills) */
Flood(rp, 1, 50, 50);
/* mode 1 = fill until FgPen colour boundary */
/* mode 0 = fill all connected pixels of same colour as seed */

Blitting (Block Transfer)

flowchart LR
    SRC["Source RastPort<br/>(or BitMap)"] -->|"ClipBlit /<br/>BltBitMapRastPort"| DST["Destination RastPort"]
    
    subgraph "Minterm Controls"
        MT["0xC0 = copy<br/>0x30 = invert copy<br/>0x50 = XOR<br/>0x00 = clear"]
    end
    MT --> DST
/* Copy region between RastPorts (respects clipping): */
ClipBlit(srcRP, sx, sy,     /* source position */
         dstRP, dx, dy,     /* destination position */
         width, height,
         0xC0);             /* minterm: straight copy */

/* Copy from BitMap to RastPort: */
BltBitMapRastPort(srcBM, sx, sy,
                  dstRP, dx, dy,
                  width, height,
                  0xC0);

/* Common minterms: */
/* 0xC0 = A (copy source)           */
/* 0x30 = NOT A (invert source)     */
/* 0x50 = A XOR B (toggle)          */
/* 0x00 = clear destination         */
/* 0xFF = set all bits               */

Layers — Window Clipping

When rp->Layer != NULL, all drawing is automatically clipped to the layer's visible region. Intuition creates layers for every window — this is how overlapping windows work without drawing over each other.

flowchart TD
    subgraph "Screen"
        subgraph "Window A (front)"
            LA["Layer A<br/>(fully visible)"]
        end
        subgraph "Window B (behind)"
            LB["Layer B<br/>(partially obscured)"]
        end
        subgraph "Window C (behind both)"
            LC["Layer C<br/>(mostly obscured)"]
        end
    end

    DRAW["Draw(windowB->RPort, ...)"] --> LB
    LB -->|"ClipRects exclude<br/>obscured regions"| BM["BitMap<br/>(only visible<br/>portions drawn)"]

    style LA fill:#c8e6c9,stroke:#2e7d32,color:#333
    style LB fill:#fff9c4,stroke:#f9a825,color:#333
    style LC fill:#ffcdd2,stroke:#c62828,color:#333

Each layer maintains a list of ClipRects — rectangles defining which parts of the layer are visible. When you draw to a partially obscured window, layers.library breaks your drawing operation into multiple clipped sub-draws, one per visible ClipRect.

/* Direct layer creation (Intuition does this for windows): */
struct Layer_Info *li = NewLayerInfo();
struct Layer *layer = CreateUpfrontLayer(li, bm,
    x1, y1, x2, y2,
    LAYERSIMPLE,  /* or LAYERSMART, LAYERSUPER */
    NULL);
struct RastPort *rp = layer->rp;  /* use this for drawing */

/* LAYERSIMPLE  — no backing store; app must redraw damaged areas */
/* LAYERSMART   — automatic backing store; OS handles redraw */
/* LAYERSUPER   — super bitmap; full offscreen buffer */

/* Layer clipping is automatic — Draw, RectFill, Text all respect it */
Draw(rp, 200, 100);  /* clipped to visible portion of layer */

/* Cleanup: */
DeleteLayer(0, layer);
DisposeLayerInfo(li);

Layer Types

Type Flag Backing Store Damage Handling Memory
Simple LAYERSIMPLE None App receives IDCMP_REFRESHWINDOW and must redraw Minimal
Smart LAYERSMART Auto-saved obscured regions OS restores automatically Moderate
Super LAYERSUPER Full off-screen bitmap Full bitmap always valid High

Tip

WFLG_SIMPLE_REFRESH windows use the least memory but require the most application code (you must handle IDCMP_REFRESHWINDOW). WFLG_SMART_REFRESH is the default for most applications — Intuition saves/restores obscured regions automatically.


Patterns

Line Patterns

/* 16-bit repeating pattern for dashed lines: */
SetDrPt(rp, 0xFF00);   /* ████████░░░░░░░░ — long dash */
SetDrPt(rp, 0xF0F0);   /* ████░░░░████░░░░ — medium dash */
SetDrPt(rp, 0xAAAA);   /* █░█░█░█░█░█░█░█░ — dotted */
SetDrPt(rp, 0xFCFC);   /* ██████░░██████░░ — dash-dot */

Area Fill Patterns

/* Area patterns are powers-of-2 height, 16 bits wide: */
UWORD checkerPattern[] = { 0x5555, 0xAAAA };  /* 2-line checkerboard */
rp->AreaPtrn = checkerPattern;
rp->AreaPtSz = 1;    /* log2(2) = 1 */

/* Now RectFill uses the pattern instead of solid fill: */
RectFill(rp, 10, 10, 100, 80);

/* Multiplane patterns (one set per bitplane): */
UWORD brickPattern[] = {
    /* plane 0: */  0xFFFF, 0x8080, 0xFFFF, 0x0808,
    /* plane 1: */  0xFFFF, 0x8080, 0xFFFF, 0x0808
};
rp->AreaPtrn = brickPattern;
rp->AreaPtSz = 2;   /* log2(4 lines) = 2 */
rp->Mask |= 0x02;   /* enable plane 1 pattern */

Plane Mask — Selective Bitplane Drawing

/* Mask controls which bitplanes are affected by drawing: */
rp->Mask = 0xFF;  /* all planes — default */
rp->Mask = 0x01;  /* only plane 0 — fast for single-plane effects */
rp->Mask = 0x03;  /* planes 0 and 1 only */

/* Use case: draw a 2-colour overlay without disturbing other planes: */
rp->Mask = 0x04;  /* only plane 2 */
SetAPen(rp, 4);   /* colour index with bit 2 set */
RectFill(rp, 0, 0, 319, 255);
rp->Mask = 0xFF;  /* restore */

References

  • NDK39: graphics/rastport.h, graphics/gfxmacros.h
  • ADCD 2.1: SetAPen, Move, Draw, Text, RectFill, ClipBlit
  • See also: bitmap.md — BitMap structure and allocation
  • See also: layers.md — layers.library detailed reference
  • See also: text_fonts.md — font loading and rendering
  • See also: blitter.md — hardware Blitter used by BltBitMap