# The Game Kit: BDirectWindow

Derived from: BWindow

Declared in: be/kit/game/DirectWindow.h

Library: libgame.so

## Overview

The BDirectWindow class gives your code direct access to the graphics frame buffer on the video card. Unlike BWindowScreen, BDirectWindow can be used in both full-screen and window modes--you can create a BDirectWindow that looks just like a normal window, but lets your code draw into it by directly accessing the frame buffer.

In addition, BDirectWindow lets you switch between full-screen exclusive mode and windowed modes without breaking down and rebuilding the object. A simple call to the `SetFullScreen()` function does the job.

|  | If you want your direct window to be full-screen but don't want exclusive mode, just resize the window to fill the entire screen; since full-screen exclusive mode (as set by calling `SetFullScreen()`) won't let other windows draw in front of your direct window, you can't have menus in a full-screen exclusive mode direct window.

Another difference between BDirectWindow and BWindowScreen is that BDirectWindow lets you access all the BWindow functions; you can literally treat your BDirectWindow just like another window. There are two caveats:

|  | Don't draw into the direct window from its own thread; you should spawn another thread for drawing into the direct window, and use the `DirectConnected()` function to synchronize the interaction between BDirectWindow and your drawing thread. Also, if you choose to use BWindow or BView API inside a BDirectWindow, be sure you don't block the `DirectConnected()` function.

Not all video cards support window mode; use the `SupportsWindowMode()` function if you need to know whether or not window mode is available.

### Getting Connected (and Staying That Way)

The key to the BDirectWindow class is the `DirectConnected()` function, which your code must implement. This function is called whenever a change that your drawing code may need to be aware of occurs.

When your `DirectConnected()` function is called, it's passed a pointer to a `direct_buffer_info` structure, as follows:

       typedef struct {
          direct_buffer_state   buffer_state;
          direct_driver_state   driver_state;
          void                  *bits;
          void               *pci_bits;
          int32                  bytes_per_row;
          uint32               bits_per_pixel;
          color_space               pixel_format;
          buffer_layout               layout;
          buffer_orientation   orientation;
          uint32                  _reserved[9];
          uint32               _dd_type_;
          uint32               _dd_token_;
          uint32               clip_list_count;
          clipping_rect               window_bounds;
          clipping_rect               clip_bounds;
          clipping_rect               clip_list[1];
       } direct_buffer_info;

`buffer_state` indicates what change is occurring in the direct buffer access privileges. It can have one of the following values:

Constant | Description
`B_DIRECT_START` | Your BDirectWindow has just received direct screen access to the part of the screen described by the `direct_buffer_info` structure.
`B_DIRECT_STOP` | Your direct screen access privileges have been suspended. None of the other fields in the `direct_buffer_info` structure are valid.
`B_DIRECT_MODIFY` | A change has occurred to the direct screen access buffer; your drawing code needs to take whatever action is necessary to adjust to the new state.

You will always receive a `B_DIRECT_START` notification when your BDirectWindow is first connected to the screen, followed by any number of `B_DIRECT_MODIFY` notifications (it's possible you won't receive any at all). When you return from `DirectConnected()` after handling `B_DIRECT_START` or `B_DIRECT_MODIFY`, your application guarantees to the application server that your code will abide by the frame buffer configuration specified by the `direct_buffer_info` structure until another `B_DIRECT_MODIFY` notification is received (or `B_DIRECT_STOP` occurs).

You'll receive a `B_DIRECT_STOP` notification when the window is closed, hidden, or if moved, or if a resolution or color depth change occurs. Once your `DirectConnected()` function returns from handling this notification, you guarantee to the application server that your code won't touch the frame buffer anymore.

For any of these notifications, your `DirectConnected()` function shouldn't return until you can guarantee to the application server that your code will abide by the frame buffer configuration it received.

You can get further information about what changed by testing against other flags in the `buffer_state` field:

Constant | Description
`B_BUFFER_MOVED` | The content of your window has been moved, either by a call to `MoveTo()` or `MoveBy()` or by the user manually dragging the window. The contents of the window are always moved relative to the top-left corner of the window.
`B_BUFFER_RESET` | The entire direct access buffer has been reset. This can happen if the user changes the depth or resolution of the screen, or if the window had previously been hidden and has been made visible again.
`B_BUFFER_RESIZED` | The content area of your window has been resized.
`B_CLIPPING_MODIFIED` | The visible region of the content area of your window changed. This doesn't imply anything about the position of the window or the size of the content area of the window--it simply means that the part of the window that's visible has changed shape.

The `driver_state` field indicates changes in the state of the graphics card on which your direct window is displayed. There are two possible values:

Constant | Description
`B_MODE_CHANGED` | The resolution or depth of the graphics card has changed.
`B_DRIVER_CHANGED` | The window was moved onto another monitor.

The `bits` field is a pointer to the frame buffer in your own team's memory space.

The `pci_bits` field is a pointer to the frame buffer in the PCI memory space; this value is typically needed to control DMA.

`bytes_per_row` is the number of bytes used to represent a single row of pixels in the frame buffer.

`bits_per_pixel` is the number of bits actually used to store a single pixel, including reserved, unused, or alpha channel bits. This value is usually a multiple of eight.

`pixel_format` is the format used to encode a pixel, as defined in the `color_space` type in <GraphicsDefs.h>.

The `layout`, `orientation`, `_reserved`, `_dd_type_`, and `_dd_token_` fields are all reserved for future use and must not be used.

`window_bounds` is a rectangle that defines the full content area of the window, in screen coordinates. You can convert these coordinates into frame buffer addresses using the values in the `bits`, `bytes_per_row`, and `bits_per_pixel` fields. The `clipping_rect` structure is:

       typedef struct {
          int32      left;
          int32      top;
          int32      right;
          int32      bottom;
       } clipping_rect;

Note that, as always, these edges are inclusive; for example, if left is 5 and top is 3, the pixel at (5,3) is included in the rectangle's contents.

`clip_bounds` is the bounding rectangle of the visible part of the content area of the window, in screen coordinates. This rectangle is the smallest rectangle that contains all the rectangles in the `clip_list`, described below.

`clip_list_count` is the number of rectangles in the `clip_list`. The `clip_list` is a list of rectangles that together define the visible region of the content area of the window, in screen coordinates

The data in the `direct_buffer_info` structure is only valid until `DirectConnected()` returns, so if you need to reference any of the information later, you should make a copy of the fields you need.

### Window Mode vs. Full Screen Mode

There are some differences in how BDirectWindow behaves depending on whether it's in window mode or full-screen exclusive mode.

In window mode, the BDirectWindow behaves almost exactly like a BWindow--so much so that you can use a BDirectWindow in any situation you'd normally use a BWindow. The `window_bounds` rectangles are the same size and shape as the window itself, as you'd expect. If exclusive window mode is available (`SupportsWindowMode()` returns true), `DirectConnected()` will be called as described above, thereby providing the means to directly access the frame buffer. If the graphics card doesn't support exclusive access to the frame buffer while in window mode, `DirectConnected()` will never be called, and you can only use BWindow and BView APIs to work in the window.

In full-screen exclusive mode, the `window_bounds` are actually the size and shape of the entire screen, even if the screen isn't the same size as the direct window you created. You have to handle the difference yourself.

Full-screen exclusive mode also guarantees that your window will always be the focus, always be in front, and will always stay full-screen (the application server will resize the window for you if the screen resolution changes). Since no other windows can come in front of a full-screen exclusive direct window, any Interface Kit objects that use a window to display their contents won't work; this includes any type of menu.

If you want your BDirectWindow to be full-screen, but still compatible with menus or other windows, create it as a non-exclusive window, then use the following code:

       BScreen screen(this);
       MoveTo(0,0);
       ResizeTo(screen.width, screen.height);

This will make the non-exclusive direct window fill the entire screen. Keep in mind that in this case, other windows may appear in front of yours, and if the screen resolution changes, you will have to resize the window yourself if you want to continue to fill the entire screen.

### Using a Direct Window

Let's put together a simple class, derived from BDirectWindow, that demonstrates the basics of drawing into a direct window.

       class DirectSample : public BDirectWindow {
          public:
                         DirectSample(BRect frame);
                         ~DirectSample();
             virtual bool   QuitRequested();
             virtual void   DirectConnected(direct_buffer_info *info);

             uint8         *fBits;
             int32         fRowBytes;
             color_space      fFormat;
             clipping_rect   fBounds;

             uint32         fNumClipRects;
             clipping_rect   *fClipList;

             bool         fDirty;      // needs refresh?
             bool         fConnected;
             bool         fConnectionDisabled;
             BLocker         *locker;
             thread_id      fDrawThreadID;
       };

The DirectSample class implements a constructor as well as the `QuitRequested()` and `DirectConnected()` functions.

Some variables are added to the class for cacheing information about the frame buffer.

- `fBits` will contain a pointer to the frame buffer's bitmap.

- `fRowBytes` will contain the number of bytes per row of screen data.

- `fFormat` will contain the pixel format (such as `B_CMAP8` for 8-bit indexed color graphics mode). Our sample program will only work in this mode.

- `fBounds` will contain the bounds rectangle for the window.

- `fNumClipRects` will contain the number of rectangles in the clip rectangle list.

- `fClipList` is the actual list of clip rectangles, and will be allocated on-the-fly as needed.

- `fDirty` will be `true` if the window needs to be redrawn.

- `fConnected` is `true` if the window is connected to the frame buffer.

- `fConnectionDisabled` is `true` if the window is in the process of being closed.

- `locker` is a BLocker that will be used to ensure mutual exclusion when the frame buffer or buffer information data we've cached is being manipulated.

- `fDrawThreadID` contains the `thread_id` of the drawing thread, which is responsible for drawing the contents of the window.

The specifics of what these variables are and why the information contained in them is maintained will be discussed when we get to the `DirectConnected()` and `DrawingThread()` functions.

The constructor for the DirectSample class looks like this:

       DirectSample::DirectSample(BRect frame)
                : BDirectWindow(frame, "DirectWindow Sample",
                      B_TITLED_WINDOW,
                            B_NOT_RESIZABLE|B_NOT_ZOOMABLE) {

          fConnected = false;
          fConnectionDisabled = false;
          locker = new BLocker();
          fClipList = NULL;
          fNumClipRects = 0;

          AddChild(new SampleView(Bounds()));

          if (!SupportsWindowMode()) {
             SetFullScreen(true);
          }

          fDirty = true;
          fDrawThreadID = spawn_thread(DrawingThread, "drawing_thread",
                         B_NORMAL_PRIORITY, (void *) this);
          resume_thread(fDrawThreadID);
          Show();
       }

This code establishes the direct window by deferring to BDirectWindow. Then the `fConnected` and `fConnectionDisabled` flags are initialized to indicate that the window isn't connected yet, but the connection isn't in the process of being torn down by the DirectSample destructor. The `locker` is created, and the clip rectangle list is initialized to a `NULL` pointer, with a count of 0.

Then it adds a child view that occupies the entire window. The primary purpose of this view in this sample is to set the view color to `B_TRANSPARENT_32_BIT`, to prevent the application server from erasing the window with a default color.

If the video card doesn't support window mode, we call `SetFullScreen()` to switch the direct window into full-screen exclusive mode. This guarantees that you'll get connected with direct screen access (in a window if possible, otherwise in full-screen exclusive mode). If you don't use `SetFullScreen()`, and window mode isn't supported, `DirectConnected()` will never be called, and you won't have direct screen access.

Then the `fDirty` flag is set to true, which indicates that the window needs to be updated, and the drawing thread is started; the drawing thread will handle all actual drawing into the window. The argument passed to the drawing thread is a pointer to the DirectSample window itself. You should always use a separate thread for drawing into a BDirectWindow.

Finally, `Show()` is called to make the direct window visible.

The destructor needs to make sure there's no chance someone will try to draw while the window is being destructed:

       DirectSample::~DirectSample() {
          int32 result;

          fConnectionDisabled = true;      // Connection is dying
          Hide();
          Sync();
          wait_for_thread(fDrawThreadID, &result);
          free(fClipList);
          delete locker;
       }

The first thing the destructor does is set the `fConnectionDisabled` flag to `true`, which indicates that the window is in the process of being destroyed, and that future calls to `DirectConnected()` or the drawing thread should be ignored. The window is then hidden by calling `Hide()`. Finally, `Sync()` is called to block until the window is actually hidden.

`wait_for_thread()` waits until the drawing thread terminates. The drawing thread (as we'll see shortly) is designed to terminate when the `fConnectionDisabled` flag is `true`.

Then the clip rectangle list is freed and the locker deleted.

The `QuitRequested()` function is implemented as usual.

The `DirectConnected()` function is called whenever a change occurs that affects how your code should access the frame buffer:

       void DirectSample::DirectConnected(direct_buffer_info *info) {
          if (!fConnected && fConnectionDisabled) {
             return;
          }
          locker->Lock();

          switch(info->buffer_state & B_DIRECT_MODE_MASK) {
             case B_DIRECT_START:
                fConnected = true;
             case B_DIRECT_MODIFY:
                fBits = (uint8 *) info->bits;
                fRowBytes = info->bytes_per_row;
                fFormat = info->pixel_format;
                fBounds = info->window_bounds;
                fDirty = true;

                // Get clipping information

                if (fClipList) {
                   free(fClipList);
                   fClipList = NULL;
                }
                fNumClipRects = info->clip_list_count;
                fClipList = (clipping_rect *)
                      malloc(fNumClipRects*sizeof(clipping_rect));
                memcpy(fClipList, info->clip_list,
                      fNumClipRects*sizeof(clipping_rect));
                break;
             case B_DIRECT_STOP:
                fConnected = false;
                break;
          }
          locker->Unlock();
       }

`DirectConnected()` begins by checking the `fConnected` and `fConnectionDisabled` flags; the code in `DirectConnected()` is only run if the connection is opened (`fConnected` is `true`) or if we want to start it again (`fConnectionDisabled` is `false`). This arrangement prevents the `DirectConnected()` function from trying to reconnect if the destructor has started running. Otherwise, the locker is locked, to prevent `DirectConnected()` and the drawing thread from colliding.

If the buffer state is `B_DIRECT_START`, the `fConnected` flag is set to `true`. This keeps track of the fact that the application server has given permission to draw directly into the region of the frame buffer controlled by the direct window.

If the buffer state is `B_DIRECT_START` or `B_DIRECT_MODIFY` (in which case the `direct_buffer_info` structure describes changes to the frame buffer), any previously-existing clip rectangle list is deleted, then we cache the information that interests us and set the `fDirty` flag to `true` (to indicate that the display needs to be redrawn to reflect the changed graphics settings).

The clip list is also cached by saving the number of rectangles in the list in the `fNumClipRects` field and by making a copy of the clip list into a newly `malloc()`d block of memory.

If the state is `B_DIRECT_STOP`, the `fConnected` flag is set to `false`, to indicate that we shouldn't draw into the frame buffer anymore.

Finally, the locker is unlocked, which lets the drawing thread start running again.

Now let's have a look at `DrawingThread()`; this function serves as the drawing thread, and is a global function:

       int32 DrawingThread(void *data) {
          DirectSample *w;

          w = (DirectSample *) data;
          while (!w->fConnectionDisabled) {
             w->locker->Lock();
             if (w->fConnected) {
                if (w->fFormat == B_CMAP8 && w->fDirty) {
                   int32 y;
                   int32 width;
                   int32 height;
                   int32 adder;
                   uint8 *p;
                   clipping_rect *clip;
                   int32 i;

                   adder = w->fRowBytes;   // Stash locally for this pass
                   for (i=0; i<w->fNumClipRects; i++) {
                      clip = &(w->fClipList[i]);
                      width = (clip->right - clip->left)+1;
                      height = (clip->bottom - clip->top)+1;
                      p = w->fBits+(clip->top*w->fRowBytes)+clip->left;
                      y = 0;
                      while (y < height) {
                         memset(p, 0x00, width);
                         y++;
                         p+=adder;
                      }
                   }
                }
                w->fDirty = false;
             }
             w->locker->Unlock();
             // Use BWindow or BView APIs here if you want
             snooze(16000);
          }
          return B_OK;
       }

`DrawingThread()` starts by casting the argument, data, into a pointer to the DirectSample window into which it will be drawing.

The while loop that follows will continue to run as long as the `fConnectionDisabled` flag is `true`--in other words, it will keep looping as long as the connection is enabled.

The drawing loop itself begins by locking the locker to ensure that `DirectConnected()` doesn't change anything while we're working, then checking to be sure the connection is opened (`fConnected` is `true`). If the connection is open, we verify that format of the window is still 8-bit color and that the display needs to be updated. If the display needs updating and the pixel format is still `B_CMAP8`, the drawing code begins.

The `fRowBytes` field of the DirectSample window is cached in a local variable called `adder`. Then each rectangle in the clip list is drawn, one at a time, using a for loop.

A pointer to the clip rectangle to be drawn is stored in `clip`, and the `width` and `height` of the rectangle are computed. Then `p` is set to be a pointer to the first pixel in the frame buffer that's contained by the clip rectangle. Since 8-bit color pixels each occupy exactly one byte of video memory, this pixel's address can be computed by taking the base `fBits` pointer, adding the number of bytes per row times the number of rows between the top of the screen and the first row in the clip rectangle, then adding the number of bytes between the left edge of the screen and the left edge of the clip rectangle, as seen in the line:

       p = w->fBits+(clip->top*w->fRowBytes)+clip->left;

Then a while loop is used to iterate over each line in the clip rectangle, by ranging the variable `y` from `0` to the `height` of the clip rectangle. `memset()` is used to clear the row to black, which is represented by the byte value 0x00. `y` is incremented by one for each pass through the loop, to count the rows being drawn for each iteration, and the pointer `p` is incremented by `adder` to move down to the beginning of the next row in the clip rectangle.

Once each clip rectangle has been drawn, the for loop exits, and the `fDirty` flag is set to false to indicate that the screen is up-to-date. Once that's done, the locker is unlocked, which lets `DirectConnected()` do its thing if it's called. To avoid using an unreasonable amount of processing time, `snooze()` is called to give up CPU time to other threads.

If you want to use calls to BWindow or BView API in your drawing thread, you should do so just after unlocking the window.

When the thread terminates (which will only happen when the connection is disabled), the drawing thread returns `B_OK`.

This drawing function is designed to draw nothing unless it's necessary; `DirectConnected()` will set the `fDirty` flag when something happens to cause the screen to need a refresh, and other code elsewhere in the application could also set the fDirty flag to indicate that the screen should be redrawn.

Since we're taking over drawing the contents of the window, we need to tell the application server not to draw anything. This is done by adding the following line to the constructor for the SampleView:

       SetViewColor(B_TRANSPARENT_32_BIT);

This is very important: if you don't remember to do this, you'll have all kinds of synchronization problems when the application server and your drawing code try to draw into the window at the same time.

Note that this sample code doesn't really do anything useful (if all you want to do is have a black window moving around, don't use BDirectWindow--use a regular BWindow, throw a BView into it, and use `SetViewColor()` to make the view black; it'll be faster and more efficient because it will use hardware graphics acceleration if it's available). However, it serves as a simple example of how to establish a connection to let your own drawing code directly access the screen. Just replace the code inside the drawing loop with something more useful (like a nifty real-time animation).

## Hook Functions

`DirectConnected()` The `DirectConnected()` hook function is called when the connection to the screen has been made, a change has occurred to the size or format of the frame buffer, a change has occurred to the position, size, or shape of the visible part of the content area of the window, or the connection to the screen is terminated.

## Constructor and Destructor

### BDirectWindow()

          BDirectWindow(BRect frame, const char *title, window_type type, uint32 flags,
             uint32 workspace = B_CURRENT_WORKSPACE)
          BDirectWindow(BRect frame, const char *title, window_look look,
             window_feel feel, uint32 flags,
             uint32 workspace = B_CURRENT_WORKSPACE)

Creates and returns a new BDirectWindow object. This is functionally equivalent to the BWindow constructor, except the resulting BDirectWindow supports direct window operations.

You will probably want to set up a flag to keep track of whether or not the direct window's connection to the screen is viable. In the constructor, you should set this flag (let's call it `fConnectionDisabled`) to `false`, which indicates to both `DirectConnected()` and your drawing thread that the window is not in the process of being deconstructed. The destructor would then set this flag to `true` before terminating the connection to avoid the unlikely possibility of the connection trying to restart while the BDirectWindow is being dismantled.

You'll also need other flags or semaphores (or benaphores) to manage the interaction between the BDirectWindow and your drawing thread.

See the sample code in Using a Direct Window for an example.

### ~BDirectWindow()

          ~BDirectWindow()

Frees all memory the BDirectWindow object allocated for itself. You should never `delete` a BDirectWindow object; call its `Quit()` or `Close()` function instead.

Your BDirectWindow destructor should begin by setting the `fConnectionDisabled` flag to `true`, to prevent `DirectConnected()` from attempting to reconnect to the direct window while it's being deconstructed.

Then you should call `Hide()` and `Sync()` to force the direct window to disconnect direct access:

       MyDirectWindow::~BDirectWindow {
          fConnectionDisabled = true;
          Hide();
          Sync();
          /* complete usual destruction here */
       }

## Member Functions

### DirectConnected()

          virtual void DirectConnected(direct_buffer_info *info)

This hook function is the core of BDirectWindow. Your application should override this function to learn about the state of the graphics display onto which you're drawing, as well as to be informed of any changes that occur.

This function is also called to suspend and resume your direct access privileges.

Your code in this function should be as short as possible, because what your `DirectConnected()` function does can affect the performance of the entire system. `DirectConnected()` should only handle the immediate task of dealing with changes in the direct drawing context, and shouldn't normally do any actual drawing--that's what your drawing thread is for.

If you have drawing that absolutely has to be done before you can safely return control to the application server (see the note below), you may do so, but your code should do the absolute minimum drawing necessary and leave everything else to the drawing thread.

|  | `DirectConnected()` should only return when it can guarantee to the application server that the request specified by info will be strictly obeyed.

The structure pointed to by info goes away after `DirectConnected()` returns, so you should cache the information that interests you.

See Getting Connected (and Staying That Way) for more information about the `direct_buffer_info` structure.

### GetClippingRegion()

          status_t GetClippingRegion(BRegion *region, BPoint *origin = NULL) const

Sets the specified region to match the current clipping region of the direct window. If origin is specified, each point in the region is offset by the origin, resulting in a BRegion that's localized to your application's vision of where in space the origin is (relative to the origin of the screen's frame buffer).

Although the `direct_buffer_info` structure contains the clipping region of a direct window, it's not in standard BRegion form. This function is provided so you can obtain a standard BRegion if you need one.

|  | The `GetClippingRegion()` function can only be called from the `DirectConnected()` function; calling it from outside `DirectConnected()` will return invalid results.

If you need to cache the clipping region of your window and need a BRegion for clipping purposes, you could use the following code inside your `DirectConnected()` function:

       BRegion rgn;
       GetClippingRegion(&rgn);

This serves a double purpose: it obtains the clipping region in BRegion form, and it returns a copy of the region that you can maintain locally. However, it may be more efficient to copy the clipping region by hand, since the clipping rectangle list used by BDirectWindow uses integer numbers, while BRegion uses floating-point.

RETURN CODES

- `B_OK`. The clipping region was successfully returned.
- `B_ERROR`. An error occurred while trying to obtain the clipping region.

### IsFullScreen(), SetFullScreen()

          bool IsFullScreen(void) const

          status_t SetFullScreen(bool enable)

`IsFullScreen()` returns `true` if the direct window is in full-screen exclusive mode, or `false` if it's in window mode.

The value returned by `IsFullScreen()` is indeterminate if a call to `SetFullScreen()` is in progress--if this is the case, you shouldn't rely on the resulting value. Instead, it would be safer to maintain a state setting of your own and use that value.

`SetFullScreen()` enables full-screen exclusive mode if the enable flag is `true`. To switch to window mode, pass `false`. The `SupportsWindowMode()` function can be used to determine whether or not the video card is capable of supporting window mode. See Window Mode vs. Full Screen Mode for a detailed explanation of the differences between these modes.

When your window is in full screen mode, it will always have the focus, and no other window can come in front of it.

`SetFullScreen()` can return any of the following result codes.

RETURN CODES

- `B_OK`. The mode was successfully changed.
- `B_ERROR`. An error occurred while trying to switch between full screen and window modes (for example, another window may already be in full-screen exclusive mode in the same workspace).

### SetFullScreen() see IsFullScreen()

### SupportsWindowMode()

          static bool SupportsWindowMode(screen_id id = B_MAIN_SCREEN_ID)

Returns `true` if the specified screen supports window mode; if you require the ability to directly access the frame buffer of a window (rather than occupying the whole screen), you should call this function to be sure that the graphics hardware in the computer running your application supports it. Because this is a static function, you don't have to construct a BDirectWindow object to call it:

       if (BDirectWindow::SupportsWindowMode()) {
          /* do stuff here */
       }

In particular, window mode requires a graphics card with DMA support and a hardware cursor; older video cards may not be capable of supporting window mode.

If window mode isn't supported, but you still select window mode, `DirectConnected()` will never be called (so you'll never be authorized for direct frame buffer access).

Even if window mode isn't supported, you can still use BDirectWindow objects for full-screen direct access to the frame buffer, but it's recommended that you avoid direct video DMA or the use of parallel drawing threads that use both direct frame buffer access and BView calls (because it's likely that such a graphics card won't handle the parallel access and freeze the PCI bus--and that would be bad).

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 27, 1998.