1 / 19

DirectDraw and Bitmaps Part 1

DirectDraw and Bitmaps Part 1. CIS 487/587 Bruce R. Maxim UM-Dearborn. Screen Basics. A standard 640x480x8 screen buffer has 307,200 pixels Without 3D acceleration hardware, software-based rasterization is not practical for more than 256 colors

lilia
Download Presentation

DirectDraw and Bitmaps Part 1

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. DirectDraw and BitmapsPart 1 CIS 487/587 Bruce R. Maxim UM-Dearborn

  2. Screen Basics • A standard 640x480x8 screen buffer has 307,200 pixels • Without 3D acceleration hardware, software-based rasterization is not practical for more than 256 colors • For bitmap work this is 3D acceleration is a little less critical

  3. 16 Bit Encoding • There are several 16 bit high-color pixel encoding schemes • Alpha 5.5.5 • X 5.5.5 • 5.6.5 (most common) • Getting the pixel format right before plotting is important • You can choose to set it to 5.6.5 yourself if you wish

  4. Writing a Screen Pixel • Lock the surface using Lock( ) • Build the 16-bit RGB word using the macro _RGB16BIT5.6.5 • Write the pixel using a USHORT pointer into VRAM • Unlock the primary surface using unlock

  5. LaMothe Examples

  6. Ddraw 16-bit Pixel Plotting // done as global declarations // builds a 16 bit color value in 5.6.5 format (green dominate mode) #define _RGB16BIT565(r,g,b) ((b&31) + ((g&63) << 5) + ((r&31) << 11)) // initializes a direct draw struct #define DDRAW_INIT_STRUCT(ddstruct) {memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); } inline void Plot_Pixel_Faster16(int x, int y, int red, int green, int blue, USHORT *video_buffer, int lpitch16) { // plots a pixel in 16-bit color mode assumes caller already locked the // surfaceand is sending a pointer and byte pitch to it USHORT pixel = _RGB16BIT565(red,green,blue); // first build up color WORD video_buffer[x + y*lpitch16] = pixel; // write the data } // end Plot_Pixel_Faster16

  7. Game_Main( ) // clear ddsd and set size, never assume it's clean DDRAW_INIT_STRUCT(ddsd); // lock the primary surface if (FAILED(lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) return(0); int lpitch16 = (int)(ddsd.lPitch >> 1); USHORT *video_buffer = (USHORT *)ddsd.lpSurface; // plot the pixel once position and color is set Plot_Pixel_Faster16(x,y,red,green,blue,video_buffer,lpitch16); // now unlock the primary surface if (FAILED(lpddsprimary->Unlock(NULL))) return(0);

  8. Game_Init( ) // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x16 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0))) return(0); // clear ddsd and set size memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; // enable valid fields ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // request primary surface // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0);

  9. Game_Shutdown( ) // blow away the primary surface if (lpddsprimary) { lpddsprimary->Release(); lpddsprimary = NULL; } // end if // blow away the IDirectDraw interface if (lpdd) { lpdd->Release(); lpdd = NULL; } // end if

  10. Plotting 24 Bit Pixels inline void Plot_Pixel_24(int x, int y, int red, int green, int blue, UCHAR *video_buffer, int lpitch) { // function plots pixel in 24-bit color modeassumes caller locked surface // and is sending a pointer and byte pitch to it // in byte or 8-bit math the proper address is: 3*x + y*lpitch // this is the address of low order byte which is the Blue channel // since data is in RGB order DWORD pixel_addr = (x+x+x) + y*lpitch; // write the data, first blue video_buffer[pixel_addr] = blue; // now red video_buffer[pixel_addr+1] = green; // finally green video_buffer[pixel_addr+2] = red; } // end Plot_Pixel_24

  11. Plotting 32 Bit Pixels // builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode) #define _RGB32BIT(a,r,g,b) ((b)+ ((g)<<8) + ((r)<<16) + ((a)<<24)) inline void Plot_Pixel_32(int x, int y, int alpha,int red, int green, int blue, UINT *video_buffer, int lpitch32) { // this function plots a pixel in 32-bit color mode // assuming that the caller already locked the surface // and is sending a pointer and DWORD aligned pitch to it // first build up color WORD UINT pixel = _RGB32BIT(alpha,red,green,blue); // write the data video_buffer[x + y*lpitch32] = pixel; } // end Plot_Pixel_32

  12. Animation and Bitmaps • DirectDraw gives you two choices for doing continuous animation • Page flipping (using primary and secondary surfaces) • Double buffering (using system memory for back buffer and programmer to flips the pages) • In both cases DirectDraw does the hard work of page flipping (regardless of whether VRAM is linear or non-linear)

  13. Overview of Double Buffering • Game_Init( ) • new is used to allocate double buffer • Game_Sutdown( ) • Double buffer must be freed up • Game_Main( ) • Double buffer is erased and 5000 pixels are drawn “offline” • Check is made for linear memory and then buffer is copied to screen memory

  14. Game_Init( ) // once the primary surface, cooperation, display mode, and palette // are defined // allocate double buffer if ((double_buffer=new UCHAR[SCREEN_WIDTH * SCREEN_HEIGHT])==NULL) return(0);

  15. Game_Shutdown( ) // blow away the palette, surface, and direct draw interface first // release the memory used for double buffer if (double_buffer) { delete double_buffer; double_buffer = NULL; } // end if

  16. Game_Main( ) UCHAR *primary_buffer = NULL; // alias to primary surface buffer // erase double buffer memset((void *)double_buffer,0, SCREEN_WIDTH*SCREEN_HEIGHT); double_buffer[x+y*SCREEN_WIDTH] = col; // plot at least one pixel // copy the double buffer into the primary buffer DDRAW_INIT_STRUCT(ddsd); // lock the primary surface lpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce primary_buffer = (UCHAR *)ddsd.lpSurface;

  17. Game_Main( ) // test if memory is linear if (ddsd.lPitch == SCREEN_WIDTH) { // copy memory from double buffer to primary buffer memcpy((void *)primary_buffer, (void *)double_buffer, SCREEN_WIDTH*SCREEN_HEIGHT); } // end if else { // non-linear  // make copy of source and destination addresses UCHAR *dest_ptr = primary_buffer; UCHAR *src_ptr = double_buffer;

  18. Game_Main( ) // memory is non-linear, copy line by line for (int y=0; y < SCREEN_HEIGHT; y++) { // copy line memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH); // advance pointers to next line dest_ptr+=ddsd.lPitch; src_ptr +=SCREEN_WIDTH; } // end for } // end else // now unlock the primary surface if (FAILED(lpddsprimary->Unlock(NULL))) return(0);

  19. Back Buffer Steps • Allocate memory for back buffer with same pixel dimensions as primary • In main loop erase back buffer • Perform game logic • Render the next frame in the back buffer • Copy the back buffer to the primary buffer (surface) • Synchronize display to desired frame rate • Go to step 2

More Related