# Graphics Card Drivers: Graphics Card Hook Functions

Declared in: be/add-ons/graphics/GraphicsCard.h

A graphics card driver can implement a set of hook functions that perform specific tasks on behalf of the Application Server and the Game Kit's BWindowScreen object. Drivers should implement as many of these functions as they can.

The Application Server asks the driver for the locations of its hook functions by passing the `B_GET_GRAPHICS_CARD_HOOKS` opcode. In response to this request, the driver writes an array of function pointers to data, cast as a `graphics_card_hook` pointer (described below). The `B_GET_GRAPHICS_CARD_HOOKS` request is made whenever the configuration of the frame buffer changes. The driver can thus provide hook functions that are tailored to specific frame buffer configurations.

The system can accommodate B_GRAPHICS_HOOK_COUNT (48) hook functions. Currently, only the first 14 functions are used. These functions fall into four groups:

- Indices 0-2: Cursor management. Drivers must implement all three of these functions, or none of them.

- Indices 3-9, 12, and 13: Drawing functions. These are specific drawing tasks, such as drawing a line or filling a rectangle. A driver can implement as many of these as it wishes.

- Index 10: Driver/Application Server synchronization. Drivers should implement this function only if the other hook functions are performed asynchronously.

- Index 11: Color inversion. This function inverts the colors in a rectangle.

### The graphics_card_hook Type

All pointers in the hook function array are declared to be of type `graphics_card_hook`:

          typedef void (*graphics_card_hook)(void)

The code that fills data will look something like this:

       int32 control_graphics_card(uint32 opcode, void *data)
       {
          switch (opcode) {
          ...
          case B_GET_GRAPHICS_CARD_HOOKS:
             ((graphics_card_hook *)data)[0] = (graphics_card_hook)define_cursor;
             ((graphics_card_hook *)data)[1] = (graphics_card_hook)move_cursor;
          ...
          }
       }

Despite the `graphics_card_hook` declaration, each function has its own set of arguments and returns an integer error code. All functions should return `B_OK` if they're successful, and `B_ERROR` if not.

### Unimplemented Functions

All hook functions that the driver doesn't implement (including indices 14-47) should be set to `NULL`. For example:

       ((graphics_card_hook *)data)[14] = (graphics_card_hook)NULL;

A driver can chose to nullify functions it does implement if it wants to defer to the Application Server version.

|  | Don't implement a function to simply (always) return `B_ERROR`. If you want to declare a hook as a no-op, you must pass `NULL` as the pointer.

### Coordinate Spaces

Most hook function coordinates are in depth-independent "frame buffer space" (the exceptions are well noted below). In other words, a coordinate pair gives the location of a pixel in the frame buffer independent of the buffer's depth; pixel (0, 0) is at the left top corner of the frame buffer.

### Naming

You can name the functions whatever you wish--the Application Server finds the functions by index in the hook function array. For convenience and clarity, the following descriptions suggest default names.

## Hook Functions

### Index, 0:, define_cursor()

          int32 define_cursor(uchar *xorMask, uchar *andMask,
             int32 width, int32 height,
             int32 hotX, int32 hotY)

Tells the driver to create a cursor image as defined by the arguments. The first two arguments, xorMask and andMask, are bit vectors that represent the cursor image laid out in concatenated, byte-aligned rows (top to bottom). Parallel bits from the two vectors define the color of a single cursor pixel:

xorMask | andMask | Meaning
0 | 0 | Transparent; let the color of the underlying screen pixel show through.
1 | 0 | Inversion; invert the color of the screen pixel.
0 | 1 | White; replace the screen pixel with a white cursor pixel.
1 | 1 | Black; replace the screen pixel with a black cursor pixel.

The second two arguments, width and height, are the size of the cursor image in pixels. (Currently, the Application Server supports only 16x16 cursors.)

The (hotX, hotY) arguments define the "hot spot"--the pixel that precisely locates the cursor. Hot spot coordinates are relative to the cursor rectangle itself, where the pixel at the left top corner of the cursor image is (0, 0) and the one at the right bottom corner is (width-1, height-1).

If the cursor is currently showing (i.e. not hidden), this function should display the cursor image.

### Index, 1:, move_cursor()

          int32 move_cursor(int32 screenX, int32 screenY)

Tells the driver to move the cursor so the hot spot corresponds to (screenX, screenY). The arguments are display area coordinates (not frame buffer coordinates).

### Index, 2:, show_cursor()

          int32 show_cursor(bool flag)

If the flag argument is `true`, the driver should show the cursor image on-screen; if it's `false`, it should remove the cursor from the screen.

If the driver is asked to show the cursor before `define_cursor()` is called, it should show it at (0, 0).

### Index, 3:, draw_line_with_8_bit_depth()

          int32 draw_line_with_8_bit_depth(int32 startX, int32 endX,
             int32 startY, int32 endY,
             uint8 colorIndex,
             bool clipToRect,
             int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom)

Tells the driver to draw a straight, 8-bit color, minimally thin line.

- The line begins at (startX, startY) and ends at (endX, endY), inclusive. The arguments are frame buffer coordinates.

- colorIndex gives the color of the line as an index into the 8-bit color table.

- If clipToRect is `true`, the function should draw only the portion of the line that lies within the clipping rectangle defined by the last four arguments. The sides of the rectangle are included in the drawing area. If clipToRect is `false`, the final four arguments should be ignored

To produce minimal thinness, the line should color only one pixel per row or column, as the absolute slope of the line is more or less than 45 degrees; in other words, the line should move between rows or columns on the diagonal, not by overlapping. Here's how you should (and shouldn't) produce a mostly-vertical line; for the mostly-horizontal version, turn your head sideways:

### Index, 4:, draw_line_with_32_bit_depth()

          int32 draw_line_with_32_bit_depth(int32 startX, int32 endX,
             int32 startY, int32 endY,
             uint32 color,
             bool clipToRect,
             int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom)

This is the same as `draw_line_with_8_bit_depth()` except for the color argument. Here, color is a 32-bit value with 8-bit red, green, blue, and alpha components. The components are arranged in the order that the driver specified when it received the `B_GET_GRAPHICS_CARD_INFO` request.

See also: B_GET_GRAPHICS_CARD_INFO

### Index, 5:, draw_rect_with_8_bit_depth()

          int32 draw_rect_with_8_bit_depth(int32 left, int32 top, int32 right, int32 bottom,
             uint8 colorIndex)

Tells the driver to fill a rectangle, specified by the first four arguments, with the color at colorIndex in the 8-bit color table. The arguments are frame buffer coordinates. The sides of the rectangle should be included in the area being filled.

### Index, 6:, draw_rect_with_32_bit_depth()

          int32 draw_rect_with_32_bit_depth(int32 left, int32 top, int32 right, int32 bottom,
             uint32 color)

This is the same as `draw_rect_with_8_bit_depth()` except for the color argument. Here, color is a 32-bit value with 8-bit red, green, blue, and alpha components. The components are arranged in the order that the driver specified when it received the `B_GET_GRAPHICS_CARD_INFO` request.

See also: B_GET_GRAPHICS_CARD_INFO

### Index, 7:, blit()

          int32 blit(int32 sourceX, int32 sourceY,
             int32 destinationX, int32 destinationY,
             int32 width, int32 height)

Tells the driver to copy pixel data from a source rectangle to a destination rectangle. All coordinates and sizes are in frame buffer space. The left top pixel of the source rectangle is at (sourceX, sourceY) in the frame buffer. The left top pixel of the destination rectangle is at (destinationX, destinationY) in the frame buffer. Both rectangles are width pixels wide and height pixels high. The width and height arguments will always contain positive values, and the rectangles are guaranteed to lie wholly within the frame buffer.

### Index, 8:, draw_array_with_8_bit_depth(), indexed_color_line

          int32 draw_array_with_8_bit_depth(indexed_color_line *array, int32 numItems,
             bool clipToRect,
             int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom)

Tells the driver to draw an array of lines in 8-bit depth. The line array holds a total of numItems. Each item is specified as an `indexed_color_line` structure, which contains the following fields (all coordinates are in frame buffer space):

int16 `x1` | The x coordinate of one end of the line.
int16 `y1` | The y coordinate of one end of the line.
int16 `x2` | The x coordinate of the other end of the line.
int16 `y2` | The y coordinate of the other end of the line.
uint8 `color` | The color of the line, expressed as an index into the color map.

If clipToRect is `true`, the function should draw only the portions of the lines that lie within the clipping rectangle defined by the last four arguments. The sides of the rectangle are included in the drawing area. If clipToRect is `false`, the final four arguments should be ignored

The lines should be minimally thin, as described under 16117: head3: Index 3: Drawing a Line with an 8-Bit Color .

### Index, 9:, draw_array_with_32_bit_depth(), rgb_color_line

          int32 draw_array_with_32_bit_depth(rgb_color_line *array, int32 numItems,
             bool clipToRect,
             int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom)

Except for the color specification, which is encoded in the `rgb_color_line` structure, this is the same as `draw_array_with_8_bit_depth()`. The `rgb_color_line` structure contains these fields:

int16 `x1` | The x coordinate of one end of the line.
int16 `y1` | The y coordinate of one end of the line.
int16 `x2` | The x coordinate of the other end of the line.
int16 `y2` | The y coordinate of the other end of the line.
rgb_color `color` | The color of the line, expressed as a full 32-bit value.

### Index, 10:, sync()

          int32 sync(void)

The driver should implement this function to block until all other currently-executing hook functions have finished. (More accurately, you only have to wait for those hook functions that actually touch the frame buffer.) The return value is ignored.

You should only implement this function if the card can perform any of the hook functions asynchronously. If all hook functions are synchronous, you should set the index 10 function to `NULL`.

After receiving a `sync()` call, your driver won't receive anymore hook functions until `sync()` returns. Thus, you don't have to guard against in-coming hook functions while sitting in `sync()`.

### Index, 11:, invert_rect()

          int32 invert_rect(int32 left, int32 top, int32 right, int32 bottom)

Tells the driver to invert the colors in the rectangle specified by the arguments. The sides of the rectangle are included in the inversion.

### Index, 12:, draw_line_with_16_bit_depth()

          int32 draw_line_with_16_bit_depth(int32 startX, int32 endX,
             int32 startY, int32 endY,
             uint16 color,
             bool clipToRect,
             int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom)

This is the same as `draw_rect_with_8_bit_depth()` except for the color argument. Here, color is a 16-bit value with red, green, blue, and (possibly) alpha components. The components are arranged in the order that the driver specified when it received the `B_GET_GRAPHICS_CARD_INFO` request.

See also: B_GET_GRAPHICS_CARD_INFO

### Index, 13:, draw_rect_with_16_bit_depth()

          int32 draw_rect_with_16_bit_depth(int32 left, int32 top, int32 right, int32 bottom,
             uint16 color)

This is the same as `draw_rect_with_8_bit_depth()` except for the color argument. Here, color is a 16-bit value with red, green, blue, and (possibly) alpha components. The components are arranged in the order that the driver specified when it received the `B_GET_GRAPHICS_CARD_INFO` request.

See also: B_GET_GRAPHICS_CARD_INFO

The Be Book, in lovely HTML, for BeOS Release 3.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.