Sign in to follow this  

Having troubles with LPDIRECTDRAWCLIPPER

This topic is 4713 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Btw, I'm reading Tricks of the GP guru and that's where this is from. You see where I call the function on game_init? Well, it's failing... and the program eventually shuts down for no reason.... the code
#define WIN32_LEAN_AND_MEAN
#define INITGUID

#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>
#include <cstdlib>

#define 	null_ptr	0
#define		class_name	TEXT("Blit Surface Test")

LPDIRECTDRAW7		 lpddraw	 = null_ptr;
LPDIRECTDRAWPALETTE  lpddpal	 = null_ptr;
LPDIRECTDRAWSURFACE7 lpddfront	 = null_ptr;
LPDIRECTDRAWSURFACE7 lpddback	 = null_ptr;
LPDIRECTDRAWCLIPPER	 lpddclip	 = null_ptr;

PALETTEENTRY		palette[256] = {0};
DDSURFACEDESC2		ddsd		 = {0};
DDBLTFX				ddbltfx		 = {0};

HINSTANCE			g_hInstance	 = null_ptr;
HWND				g_hWnd		 = null_ptr;

const int screenWidth  = 640;
const int screenHeight = 480;
const int bitsPerPixel =  8;
	   
inline bool keyUp(int key)			{ return !(GetAsyncKeyState(key) & 0x8000);	}
inline bool keyDown(int key)		{ return  (GetAsyncKeyState(key) & 0x8000);	}

LPDIRECTDRAWCLIPPER attachClipper(LPDIRECTDRAWSURFACE7, int, LPRECT);

int game_init(int = 0, void* = null_ptr);
int game_main(int = 0, void* = null_ptr);
int game_over(int = 0, void* = null_ptr);

LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR cmdLine, int cmdShow)
{
 	g_hInstance = hInstance;
 	
 	WNDCLASSEX wndclsEx;
 	
 	wndclsEx.hInstance		= hInstance;
 	wndclsEx.lpfnWndProc	= wndProc;
 	wndclsEx.style			= CS_HREDRAW | CS_VREDRAW;
 	
 	wndclsEx.hCursor		= LoadCursor(0, IDC_ARROW);
 	wndclsEx.hIcon			= LoadIcon(0, IDI_APPLICATION);
 	wndclsEx.hIconSm		= LoadIcon(0, IDI_WINLOGO);
 	wndclsEx.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
 	
 	wndclsEx.lpszMenuName	= 0;
 	wndclsEx.lpszClassName	= class_name;
 	
 	wndclsEx.cbSize			= sizeof(WNDCLASSEX);
 	wndclsEx.cbWndExtra		= 0;
 	wndclsEx.cbClsExtra		= 0;
 	
 	if (!RegisterClassEx(&wndclsEx))
 	{
		MessageBox(0, TEXT("Could not register window class."), class_name, MB_OK | MB_ICONERROR);
		
		return 1;
	}
	
	HWND hWnd = CreateWindowEx(0, class_name, class_name, WS_POPUP | WS_VISIBLE, 
		 	  					  CW_USEDEFAULT, CW_USEDEFAULT, screenWidth, 
 								  screenHeight, 0, 0, hInstance, 0);
 								  
    if (!hWnd)
  	{
		MessageBox(0, TEXT("Could not register create window."), class_name, MB_OK | MB_ICONERROR);
		
		UnregisterClass(class_name, hInstance);
		
		return 1;
	}
	
	g_hWnd = hWnd;
	
	ShowWindow(hWnd, cmdShow);
	UpdateWindow(hWnd);
	
	if (!game_init())
  	{		
		UnregisterClass(class_name, hInstance);
		
		return 1;
	}
	
	MSG msg;
	
	while (1)
	{
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;
                
            TranslateMessage(&msg);
            DispatchMessage(&msg);
		}
		    
        if (!game_main())
            break;
	}
	
	if (!game_over())
	    return 1;
	    
    UnregisterClass(class_name, hInstance);
    
    return msg.wParam;
}

LPDIRECTDRAWCLIPPER attachClipper(LPDIRECTDRAWSURFACE7 lpddsurf, int nRects, LPRECT rec_list)
{
	LPDIRECTDRAWCLIPPER lpddclipper = NULL;  
	LPRGNDATA region_data			= NULL;           

	if (FAILED(lpddraw->CreateClipper(0, &lpddclipper, NULL)))
	   return NULL;

	region_data = new RGNDATA[sizeof(RGNDATAHEADER)+ nRects * sizeof(RECT)];

	memcpy(region_data->Buffer, rec_list, sizeof(RECT) * nRects);

	region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
	region_data->rdh.iType           = RDH_RECTANGLES;
	region_data->rdh.nCount          = nRects;
	region_data->rdh.nRgnSize        = nRects * sizeof(RECT);
	
	region_data->rdh.rcBound.left    =  64000;
	region_data->rdh.rcBound.top     =  64000;
	region_data->rdh.rcBound.right   = -64000;
	region_data->rdh.rcBound.bottom  = -64000;

	for (int i = 0; i < nRects; ++i)
    {
	    if (rec_list[i].left < region_data->rdh.rcBound.left)
	        region_data->rdh.rcBound.left = rec_list[i].left;
	
	    if (rec_list[i].right > region_data->rdh.rcBound.right)
	        region_data->rdh.rcBound.right = rec_list[i].right;
	
	    if (rec_list[i].top < region_data->rdh.rcBound.top)
	        region_data->rdh.rcBound.top = rec_list[i].top;
	
	    if (rec_list[i].bottom > region_data->rdh.rcBound.bottom)
	        region_data->rdh.rcBound.bottom = rec_list[i].bottom;
    } 

	if (FAILED(lpddclipper->SetClipList(region_data, 0)))
	{
	    delete []region_data;
	    
	    return NULL;
	} 
	  
	if (FAILED(lpddsurf->SetClipper(lpddclipper)))
	{
	    delete []region_data;
	    
	    return NULL;
	} 

	delete []region_data;
	
	return lpddclipper;
}

int game_init(int nParams, void *pParams)
{
 	srand(GetTickCount());
 	
 	if (FAILED(DirectDrawCreateEx(null_ptr, (void **)&lpddraw, IID_IDirectDraw7, null_ptr)))
 	    return 0;
 	    
    if (FAILED(lpddraw->SetCooperativeLevel(g_hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE |
       												DDSCL_ALLOWMODEX | DDSCL_ALLOWREBOOT)))
		return 0;
		
    if (FAILED(lpddraw->SetDisplayMode(screenWidth, screenHeight, bitsPerPixel, 0, 0)))
        return 0;
        
    memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
	ddsd.dwSize				= sizeof(DDSURFACEDESC2);
	ddsd.dwFlags			= DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	ddsd.dwBackBufferCount	= 1;
	ddsd.ddsCaps.dwCaps		= DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
	    
    if (FAILED(lpddraw->CreateSurface(&ddsd, &lpddfront, null_ptr)))
        return 0;
	
	ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
	
	if (FAILED(lpddfront->GetAttachedSurface(&ddsd.ddsCaps, &lpddback)))
	    return 0;
		    
    for (int i = 1; i < 255; ++i)
    {
	 	palette[i].peRed 	= rand() % 256;
	 	palette[i].peGreen	= rand() % 256;
	 	palette[i].peBlue 	= rand() % 256;
	 	palette[i].peFlags 	= PC_NOCOLLAPSE;
	}
	
	palette[0].peRed 	= 0;
	palette[0].peGreen	= 0;
	palette[0].peBlue 	= 0;
	palette[0].peFlags 	= PC_NOCOLLAPSE;
	
	palette[255].peRed 		= 255;
	palette[255].peGreen	= 255;
	palette[255].peBlue 	= 255;
	palette[255].peFlags 	= PC_NOCOLLAPSE;
	/*
	if (FAILED(lpddraw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,
                                          		   	 			palette, &lpddpal, null_ptr)))
        return 0;
    
    if (FAILED(lpddfront->SetPalette(lpddpal)))
        return 0;
    */
	memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
	ddsd.dwSize	= sizeof(DDSURFACEDESC2); 
	   
    if (FAILED(lpddback->Lock(null_ptr, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, null_ptr)))
        return 0;
    
	BYTE *surface_ptr = (BYTE *)ddsd.lpSurface;
	 
    for (int i = 0; i < 1000; ++i)
    {
	 	BYTE color = rand() % 256;
	 	
	 	int x = rand() % screenWidth;
	 	int y = rand() % screenHeight;
        
        surface_ptr[x + y * ddsd.lPitch] = color;
	}
	
	if (FAILED(lpddback->Unlock(null_ptr)))
	    return 0;
	
	RECT rect_list[3] = {	{10, 10, 50, 50		},
                      		{100, 100, 200, 200	},
                     		{300, 300, 500, 450	}	};
                 
	if (FAILED(lpddclip = attachClipper(lpddfront, 3, rect_list)))
	    //return 0;
	   SendMessage(g_hWnd, WM_CLOSE, 0, 0);   
    return 1;
}

int game_main(int nParams, void *pParams)
{
 	static bool window_closed = false;
 	
 	if (window_closed)
 	    return 1;
 	    
 	if (keyDown(VK_ESCAPE))
 	{
        window_closed = true;
        
		PostMessage(g_hWnd, WM_CLOSE, 0, 0);
	}
	
	RECT rect = { rand() % screenWidth, rand() % screenHeight, 
		 	  	  		   rand() % screenWidth, rand() % screenHeight };
		 	  	  		   
    RECT rect2 = { rand() % screenWidth, rand() % screenHeight, 
		 	  	  		   rand() % screenWidth, rand() % screenHeight };
	
	if (rect.right < rect.left || rect.bottom < rect.top) 
		return 1;
		
	if (rect2.right < rect2.left || rect2.bottom < rect2.top) 
		return 1;
		
	if (FAILED(lpddfront->Blt(&rect, lpddback, &rect2, DDBLT_WAIT, null_ptr)))
	    return 0;
	    
	Sleep(20);
	    
    return 1;
}

int game_over(int nParams, void *pParams)
{
 	if (lpddpal)
	{
	   	lpddpal->Release();
	   	lpddpal = null_ptr;
	}
	
 	if (lpddclip)
	{
	   	lpddclip->Release();
	   	lpddclip = null_ptr;
	}
	
 	if (lpddback)
	{
	   	lpddback->Release();
	   	lpddback = null_ptr;
	}
	
 	if (lpddfront)
	{
	   	lpddfront->Release();
	   	lpddfront = null_ptr;
	}
	
 	if (lpddraw)
	{
	   	lpddraw->Release();
	   	lpddraw = null_ptr;
	}
}

LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {	  	
    case WM_CLOSE: 
		 
		if (MessageBox(hWnd, TEXT("Going so soon?"), class_name, MB_YESNO | MB_ICONWARNING) == IDYES)
		    SendMessage(hWnd, WM_DESTROY, 0, 0);
			
		return 0;
		   
    case WM_DESTROY:
		 
        PostQuitMessage(0);
        
        return 0;
	}
	
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
His code
// DEMO7_9.CPP 8-bit clipping demo

// INCLUDES ///////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#define INITGUID

#include <windows.h>   // include important windows stuff
#include <windowsx.h> 
#include <mmsystem.h>
#include <iostream.h> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h> 
#include <math.h>
#include <io.h>
#include <fcntl.h>

#include <ddraw.h> // include directdraw

// DEFINES ////////////////////////////////////////////////

// defines for windows 
#define WINDOW_CLASS_NAME "WINCLASS1"

// default screen size
#define SCREEN_WIDTH    640  // size of screen
#define SCREEN_HEIGHT   480
#define SCREEN_BPP      8    // bits per pixel

#define MAX_COLORS_PALETTE 256 // maximum colors in 256 color palette

// TYPES //////////////////////////////////////////////////////

// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;

// MACROS //////////////////////////////////////////////////////

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

// this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

// this 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))

// this 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))

// initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }

// PROTOTYPES /////////////////////////////////////////////////

LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
                                         int num_rects,
                                         LPRECT clip_list);

// GLOBALS ////////////////////////////////////////////////////

HWND      main_window_handle = NULL; // globally track main window
int       window_closed      = 0;    // tracks if window is closed
HINSTANCE hinstance_app      = NULL; // globally track hinstance

// directdraw stuff
LPDIRECTDRAW7         lpdd         = NULL;   // dd4 object
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper
PALETTEENTRY          palette[256];          // color palette
PALETTEENTRY          save_palette[256];     // used to save palettes
DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
DDBLTFX               ddbltfx;               // used to fill
DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct
HRESULT               ddrval;                // result back from dd calls
DWORD                 start_clock_count = 0; // used for timing

char buffer[80];                             // general printing buffer

// FUNCTIONS //////////////////////////////////////////////

LRESULT CALLBACK WindowProc(HWND hwnd, 
						    UINT msg, 
                            WPARAM wparam, 
                            LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT		ps;		// used in WM_PAINT
HDC				hdc;	// handle to a device context
char buffer[80];        // used to print strings

// what is the message 
switch(msg)
	{	
	case WM_CREATE: 
        {
		// do initialization stuff here
        // return success
		return(0);
		} break;
   
	case WM_PAINT: 
		{
		// simply validate the window 
   	    hdc = BeginPaint(hwnd,&ps);	 
        
        // end painting
        EndPaint(hwnd,&ps);

        // return success
		return(0);
   		} break;

	case WM_DESTROY: 
		{

		// kill the application, this sends a WM_QUIT message 
		PostQuitMessage(0);

        // return success
		return(0);
		} break;

	default:break;

    } // end switch

// process any messages that we didn't take care of 
return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

///////////////////////////////////////////////////////////

int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here

RECT source_rect, // used to hold the destination RECT
     dest_rect;  // used to hold the destination RECT

// make sure this isn't executed again
if (window_closed)
   return(0);

// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
   {
   PostMessage(main_window_handle,WM_CLOSE,0,0);
   window_closed = 1;
   } // end if

// get a random rectangle for source
int x1 = rand()%SCREEN_WIDTH;
int y1 = rand()%SCREEN_HEIGHT;
int x2 = rand()%SCREEN_WIDTH;
int y2 = rand()%SCREEN_HEIGHT;

// get a random rectangle for destination
int x3 = rand()%SCREEN_WIDTH;
int y3 = rand()%SCREEN_HEIGHT;
int x4 = rand()%SCREEN_WIDTH;
int y4 = rand()%SCREEN_HEIGHT;

// now set up the RECT structure to fill the region from
// (x1,y1) to (x2,y2) on the source surface
source_rect.left   = x1;
source_rect.top    = y1;
source_rect.right  = x2;
source_rect.bottom = y2;

// now set up the RECT structure to fill the region from
// (x3,y3) to (x4,y4) on the destination surface
dest_rect.left   = x3;
dest_rect.top    = y3;
dest_rect.right  = x4;
dest_rect.bottom = y4;

// make the blitter call
if (FAILED(lpddsprimary->Blt(&dest_rect,  // pointer to dest RECT
                             lpddsback,   // pointer to source surface
                             &source_rect,// pointer to source RECT
                             DDBLT_WAIT,  // control flags
                             NULL)))      // pointer to DDBLTFX holding info
   return(0);

// return success or failure or your own return code here
return(1);

} // end Game_Main

////////////////////////////////////////////////////////////

int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here

// 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 
if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
   return(0);

// clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd); 

// enable valid fields
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

// set the backbuffer count field to 1, use 2 for triple buffering
ddsd.dwBackBufferCount = 1;

// request a complex, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;

// create the primary surface
if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
   return(0);

// now query for attached surface from the primary surface

// this line is needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

// get the attached back buffer surface
if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
  return(0);

// clear all entries defensive programming
memset(palette,0,MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));

// create a R,G,B,GR gradient palette
for (int index=0; index < MAX_COLORS_PALETTE; index++)
    {
    // set each entry
    if (index < 64)  // shades of red
        palette[index].peRed = index*4; 
    else            // shades of green
    if (index >= 64 && index < 128) 
        palette[index].peGreen = (index-64)*4;
    else            // shades of blue
    if (index >= 128 && index < 192) 
       palette[index].peBlue = (index-128)*4;
    else            // shades of grey
    if (index >= 192 && index < 256) 
        palette[index].peRed = palette[index].peGreen = 
        palette[index].peBlue = (index-192)*4;
    
    // set flag to force directdraw to leave alone
    palette[index].peFlags = PC_NOCOLLAPSE;
    } // end for index


// draw a color gradient in back buffer
DDRAW_INIT_STRUCT(ddsd);

// lock the back buffer
if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL)))
   return(0);

// get alias to start of surface memory for fast addressing
UCHAR *video_buffer = (UCHAR *)ddsd.lpSurface;

// draw the gradient
for (int index_y=0; index_y < SCREEN_HEIGHT; index_y++)
     {
     // fill next line with color
     memset((void *)video_buffer,index_y % 256,SCREEN_WIDTH);

     // advance pointer
     video_buffer+=ddsd.lPitch;
   
     } // end for index_y

// unlock the back buffer
if (FAILED(lpddsback->Unlock(NULL)))
   return(0);

// now create and attach clipper
RECT rect_list[3] = {{10,10,50,50},
                     {100,100,200,200},
                     {300,300, 500, 450}};

if (FAILED(lpddclipper = DDraw_Attach_Clipper(lpddsprimary,3,rect_list)))
   return(0);

// return success or failure or your own return code here
return(1);

} // end Game_Init

/////////////////////////////////////////////////////////////

int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here

// first the palette
if (lpddpal)
   {
   lpddpal->Release();
   lpddpal = NULL;
   } // end if

// now the back buffer surface
if (lpddsback)
   {
   lpddsback->Release();
   lpddsback = NULL;
   } // end if

// now the primary surface
if (lpddsprimary)
   {
   lpddsprimary->Release();
   lpddsprimary = NULL;
   } // end if

// now blow away the IDirectDraw4 interface
if (lpdd)
   {
   lpdd->Release();
   lpdd = NULL;
   } // end if

// return success or failure or your own return code here
return(1);

} // end Game_Shutdown

///////////////////////////////////////////////////////////

LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
                                         int num_rects,
                                         LPRECT clip_list)

{
// this function creates a clipper from the sent clip list and attaches
// it to the sent surface

int index;                         // looping var
LPDIRECTDRAWCLIPPER lpddclipper;   // pointer to the newly created dd clipper
LPRGNDATA region_data;             // pointer to the region data that contains
                                   // the header and clip list

// first create the direct draw clipper
if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
   return(NULL);

// now create the clip list from the sent data

// first allocate memory for region data
region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));

// now copy the rects into region data
memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);

// set up fields of header
region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
region_data->rdh.iType           = RDH_RECTANGLES;
region_data->rdh.nCount          = num_rects;
region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);

region_data->rdh.rcBound.left    =  64000;
region_data->rdh.rcBound.top     =  64000;
region_data->rdh.rcBound.right   = -64000;
region_data->rdh.rcBound.bottom  = -64000;

// find bounds of all clipping regions
for (index=0; index<num_rects; index++)
    {
    // test if the next rectangle unioned with the current bound is larger
    if (clip_list[index].left < region_data->rdh.rcBound.left)
       region_data->rdh.rcBound.left = clip_list[index].left;

    if (clip_list[index].right > region_data->rdh.rcBound.right)
       region_data->rdh.rcBound.right = clip_list[index].right;

    if (clip_list[index].top < region_data->rdh.rcBound.top)
       region_data->rdh.rcBound.top = clip_list[index].top;

    if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
       region_data->rdh.rcBound.bottom = clip_list[index].bottom;

    } // end for index

// now we have computed the bounding rectangle region and set up the data
// now let's set the clipping list

if (FAILED(lpddclipper->SetClipList(region_data, 0)))
   {
   // release memory and return error
   free(region_data);
   return(NULL);
   } // end if

// now attach the clipper to the surface
if (FAILED(lpdds->SetClipper(lpddclipper)))
   {
   // release memory and return error
   free(region_data);
   return(NULL);
   } // end if

// all is well, so release memory and send back the pointer to the new clipper
free(region_data);
return(lpddclipper);

} // end DDraw_Attach_Clipper


// WINMAIN ////////////////////////////////////////////////

int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create
HWND	   hwnd;	 // generic window handle
MSG		   msg;		 // generic message
HDC        hdc;      // graphics device context

// first fill in the window class stucture
winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style			= CS_DBLCLKS | CS_OWNDC | 
                          CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc	= WindowProc;
winclass.cbClsExtra		= 0;
winclass.cbWndExtra		= 0;
winclass.hInstance		= hinstance;
winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor		= LoadCursor(NULL, IDC_ARROW); 
winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

// save hinstance in global
hinstance_app = hinstance;

// register the window class
if (!RegisterClassEx(&winclass))
	return(0);

// create the window
if (!(hwnd = CreateWindowEx(NULL,                  // extended style
                            WINDOW_CLASS_NAME,     // class
						    "DirectDraw Clipping Demo", // title
						    WS_POPUP | WS_VISIBLE,
					 	    0,0,	  // initial x,y
						    SCREEN_WIDTH,SCREEN_HEIGHT,  // initial width, height
						    NULL,	  // handle to parent 
						    NULL,	  // handle to menu
						    hinstance,// instance of this application
						    NULL)))	// extra creation parms
return(0);

// save main window handle
main_window_handle = hwnd;

// initialize game here
Game_Init();

// enter main event loop
while(TRUE)
	{
    // test if there is a message in queue, if so get it
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	   { 
	   // test if this is a quit
       if (msg.message == WM_QUIT)
           break;
	
	   // translate any accelerator keys
	   TranslateMessage(&msg);

	   // send the message to the window proc
	   DispatchMessage(&msg);
	   } // end if
    
       // main game processing goes here
       Game_Main();
       
	} // end while

// closedown game here
Game_Shutdown();

// return to Windows like this
return(msg.wParam);

} // end WinMain

///////////////////////////////////////////////////////////

void Blit_clipped(int x, int y,          // position to draw bitmap
                  int width, int height, // size of bitmap in pixels
                  UCHAR *bitmap,         // pointer to bitmap data
                  UCHAR *video_buffer)   // pointer to video buffer surface
                
{
// this function blits and clips the image sent in bitmap to the 
// destination surface pointed to by video_buffer
// the function assumes a 640x480x8 mode with linear pitch

// first do trivial rejections of bitmap, is it totally invisible?
if ((x >= SCREEN_WIDTH) || (y>= SCREEN_HEIGHT) ||
    ((x + width) <= 0) || ((y + height) <= 0))
return;

// clip source rectangle
// pre-compute the bounding rect to make life easy
int x1 = x;
int y1 = y;
int x2 = x1 + width - 1;
int y2 = y1 + height -1;

// upper left hand corner first
if (x1 < 0)
   x1 = 0;

if (y1 < 0)
   y1 = 0;

// now lower left hand corner
if (x2 >= SCREEN_WIDTH)
    x2 = SCREEN_WIDTH-1;

if (y2 >= SCREEN_HEIGHT)
    y2 = SCREEN_HEIGHT-1;

// now we know to draw only the portions of the bitmap from (x1,y1) to (x2,y2)
// compute offsets into bitmap on x,y axes, we need this to compute starting point
// to rasterize from
int x_off = x1 - x;
int y_off = y1 - y;

// compute number of columns and rows to blit
int dx = x2 - x1 + 1;
int dy = y2 - y1 + 1;

// compute starting address in video_buffer 
video_buffer += (x1 + y1*640);

// compute starting address in bitmap to scan data from
bitmap += (x_off + y_off*width);

// at this point bitmap is pointing to the first pixel in the bitmap that needs to
// be blitted, and video_buffer is pointing to the memory location on the destination
// buffer to put it, so now enter rasterizer loop

UCHAR pixel; // used to read/write pixels

for (int index_y = 0; index_y < dy; index_y++)
     {
     // inner loop, where the action takes place
     for (int index_x = 0; index_x < dx; index_x++)
          {
          // read pixel from source bitmap, test for transparency and plot
          if ((pixel = bitmap[index_x]))
              video_buffer[index_x] = pixel;

          } // end for index_x
     
          // advance pointers
          video_buffer+=640;   // bytes per scanline
          bitmap      +=width; // bytes per bitmap row

     } // end for index_y

} // end Blit_Clipped
I figure that soemthing in the clipping function is wrong, but I tried using hsi fucniton and it doesn't work either, so I messed up somwhere.. dunno where...

Share this post


Link to post
Share on other sites
You can't use the FAILED macro with the call to your attachClipper function. FAILED works with an HRESULT, not a pointer. If your function returns a valid pointer (a success), the FAILED macro may interpret it as a non-success state (any value that, when treated as an integer, is less than zero).

If Andre's code actually does that, then it's wrong.

Change the call to something like:


if ((lpddclip = attachClipper(lpddfront, 3, rect_list)) == NULL)
{
// do whatever you want to do if it fails
}

Share this post


Link to post
Share on other sites

This topic is 4713 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this