Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
The following example demonstrates the creation of the primary and backbuffer surfaces, rendering using GDI functions, and page flipping. Listing 4-4: A simple page flipping application
    var

      Form1: TForm1;

      FDirectDraw: IDirectDraw4;

      FPrimarySurface,

      FBackBuffer: IDirectDrawSurface4;

    implementation

    procedure TForm1.FormCreate(Sender: TObject);

    begin

      {initialize form properties.  note that the FormStyle property must be

       set to fsStayOnTop}

      BorderStyle := bsNone;

      BorderIcons := [];

      FormStyle   := fsStayOnTop;

      Color       := clBlack;

      {turn off the cursor}

      ShowCursor(FALSE);

    end;

    procedure TForm1.FormActivate(Sender: TObject);

    var

      {we can only get a DirectDraw4 interface from the DirectDraw interface, so we

       need a temporary interface}

      TempDirectDraw: IDirectDraw;

      {structures required for various methods}

      DDSurface: TDDSurfaceDesc2;

      DDSCaps: TDDSCaps2;

      {these variables are used in GDI rendering}

      TempCanvas: TCanvas;

      SrfcDC: HDC;

    begin

      {create a temporary DirectDraw object. this is used to create the

       desired DirectDraw4 object}

      DirectDrawCreate(nil, TempDirectDraw, nil);

      try

        {we can only get a DirectDraw4 interface through the QueryInterface

         method of the DirectDraw object}

        TempDirectDraw.QueryInterface(IID_IDirectDraw4, FDirectDraw);

      finally

        {now that we have the desired DirectDraw object, the temporary DirectDraw

         object is no longer needed}

        TempDirectDraw := nil;

      end;

      {set the cooperative level}

      FDirectDraw.SetCooperativeLevel(Handle, DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE);

      {set the display resolution and color depth}

      FDirectDraw.SetDisplayMode(640, 480, 8, 0, 0);

      {initialize the DDSurface structure to indicate that we will be creating a

       complex flipping surface with one backbuffer}

      FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0);

      DDSurface.dwSize  := SizeOf(TDDSurfaceDesc2);

      DDSurface.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;

      DDSurface.ddsCaps.dwCaps := DDSCAPS_COMPLEX or DDSCAPS_FLIP or

                                  DDSCAPS_PRIMARYSURFACE;

      DDSurface.dwBackBufferCount := 1;

      {create the primary surface object}

      FDirectDraw.CreateSurface(DDSurface, FPrimarySurface, nil);

      {indicate that we want to retrieve a pointer to the backbuffer (the surface

       immediately behind the primary surface in the flipping chain) }

      FillChar(DDSCaps, SizeOf(TDDSCaps2), 0);

      DDSCaps.dwCaps := DDSCAPS_BACKBUFFER;

      {retrieve the surface}

      FPrimarySurface.GetAttachedSurface(DDSCaps, FBackBuffer);

      {create a temporary canvas object and retrieve an HDC for the primary surface}

      TempCanvas := TCanvas.Create;

      FPrimarySurface.GetDC(SrfcDC);

      try

        {set the canvas’s handle to the surface’s DC}

        TempCanvas.Handle := SrfcDC;

        {clear the surface to black}

        TempCanvas.Brush.Color := clBlack;

        TempCanvas.FillRect(Rect(0, 0, 640, 480));

        {draw some lime colored text}

        TempCanvas.Font.Color := clLime;

        TempCanvas.TextOut(100, 100, ‘Primary Surface. Press Escape to close’);

      finally

        {don’t forget to release the DC}

        TempCanvas.Handle := 0;

        FPrimarySurface.ReleaseDC(SrfcDC);

      end;

      {get the backbuffer’s DC}

      FBackBuffer.GetDC(SrfcDC);

      try

        {set up the canvas, and clear the backbuffer to blue}

        TempCanvas.Handle := SrfcDC;

        TempCanvas.Brush.Color := clBlue;

        TempCanvas.FillRect(Rect(0, 0, 640, 480));

        {draw some yellow colored text}

        TempCanvas.Font.Color := clYellow;

        TempCanvas.TextOut(200, 200, ‘Backbuffer Surface. Press Escape to close’);

      finally

        {release the DC and destroy the temporary canvas object}

        TempCanvas.Handle := 0;

        FBackBuffer.ReleaseDC(SrfcDC);

        TempCanvas.Free;

      end;

      {commence flipping}

      FlipClock.Enabled := TRUE;

    end;

    procedure TForm1.FlipClockTimer(Sender: TObject);

    begin

      {flip the contents of the primary and backbuffer surfaces}

      FPrimarySurface.Flip(nil, DDFLIP_WAIT);

    end;
#### Displaying Bitmaps The ability to draw text, or even lines and polygons, into a surface is cool, but to really create anything visually exciting, we need to be able to display bitmaps. DirectDraw, unfortunately, does not have any built-in functionality for loading a bitmap, but using GDI techniques and Delphi’s TBitmap object, we can easily remedy the situation. The most common application for loading a bitmap is to store background or sprite images off screen, which will later be copied into the primary or, most likely, the backbuffer surface. Therefore, the first order of business is to create the off-screen surface, which will hold the bitmap image. Again, we will use the CreateSurface method. However, this time we will initialize the dwFlags member of the TDDSurfaceDesc2 structure to DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH. We must then set the dwWidth and dwHeight members to the desired width and height of the surface, typically reflecting the width and height of the bitmap image. Finally, we set the ddsCaps.dwCaps member to DDSCAPS_OFFSCREENPLAIN, indicating that this is a plain, off-screen surface. The color depth of the surface will match that of the primary surface.
| Caution: You cannot create an off-screen surface wider than the primary surface in video memory unless the hardware specifically supports it. We cover retrieving the hardware capabilities below. However, you can create off-screen surfaces wider than the primary surface in system memory.
#### Surface Memory Location When creating a surface, the application can request that the memory for a surface be allocated from a specific area. This allows an application to create surfaces, and thus load bitmaps, into memory on the display hardware, or to system memory. Video memory has the advantage of being incredibly fast when copied into another surface also located on the video memory; display memory has the advantage of being directly accessed by the CPU faster than video memory. When creating a surface, the following four flags can be combined with other flags in the ddsCaps.dwCaps member of the TDDSurfaceDesc2 structure, thereby controlling where the memory for the surface is located. Table 4-1: Memory location flags
Flag | Memory Location
--- | ---
DDSCAPS_LOCALVIDMEM DDSCAPS_NONLOCALVIDMEM DDSCAPS_VIDEOMEMORY DDSCAPS_SYSTEMMEMORY | Conventional video memory. Must be combined with DDSCAPS_VIDEOMEMORY. Accelerated Graphics Port (AGP) display memory. Must be combined with DDSCAPS_VIDEOMEMORY. Video memory. System memory.
| Note: DDSCAPS_NONLOCALVIDMEM is applicable only to AGP hardware, and only if the DirectDraw driver for that hardware supports it. You can determine if AGP is supported by DirectDraw by retrieving the hardware capabilities as discussed below.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.