Distorted desktop image when flipping ?

Started by
5 comments, last by ChocoboX 19 years, 4 months ago
I'm having a weird problem.When I flip my back buffer I see a distorted image of my desktop.I made the program sleep 1000 ms so you guys can see it.Why is this happening ? full code: It is a bit long , most of it is just initialization.have a look at where you think I might be wrong.I clear the back buffer before I attach it to the primary surface, I have no idea why this is happening.The purpose of the program is to attach a DD clipper to the back buffer, fill the back buffer with one color, then flip but since it goes through the clipper you should only see some rectangles on the screen.Please help me

#define INITGUID
#define WIN32_LEAN_AND_MEAN //No MFC

#include <stdio.h>
#include <windows.h>
#include <ddraw.h>

#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define BPP			   8

#define WND_CLASS_NAME "WINCLASS"

#define BMP_WIDTH		20
#define BMP_HEIGHT      20

#define RECT_NUM		5

typedef struct HAPPY_FACE_SU {
	int x,y;
	int x_vel, y_vel;
}HAPPY_FACE;

#define KEYPRESSED(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define RGB32(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

LPDIRECTDRAW7				lpdd;
LPDIRECTDRAWSURFACE7		primary_surface = NULL;
LPDIRECTDRAWSURFACE7		back_buffer     = NULL;
LPDIRECTDRAWCLIPPER 		teh_clip;
LPDIRECTDRAWPALETTE			pal;
DDSURFACEDESC2				surf_desc;
DDSCAPS2					ddscaps;
DDBLTFX						ddbltfx;
DDBLTFX						ddbltfx_black;

UCHAR						*video_buffer;
UCHAR						*bmp_buffer;
UCHAR						pixel;

HINSTANCE					app_hinst;
HWND						glob_hwnd;

RECT						rect_list[RECT_NUM] = { {20,20,50,50},
													{67,67,200,200},
													{100,100,300,300},
													{49,49,89,89},
													{50,50,500,500} };
LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
	PAINTSTRUCT		ps;
	HDC				hdc;

	switch(msg) {
	case WM_PAINT:
	hdc = BeginPaint(hwnd, &ps);
	EndPaint(hwnd, &ps);
	break;
	
	case WM_CLOSE:
	case WM_DESTROY:
	PostQuitMessage(0);
	break;

	}

	return DefWindowProc(hwnd, msg, wparam, lparam);
}
						

LPDIRECTDRAWCLIPPER createDdClipper(LPDIRECTDRAWSURFACE7  lpdd7, int rect_num, LPRECT clip_list) {
	
	LPDIRECTDRAWCLIPPER 	clipper;
	LPRGNDATA				surf_rgn_data;

	lpdd->CreateClipper(NULL, &clipper, NULL);
	
	surf_rgn_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + rect_num*sizeof(RECT));
	memcpy(surf_rgn_data->Buffer, clip_list,sizeof(RECT)*rect_num);

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

	for(int n = 0; n < rect_num;n++) {
		if(clip_list[n].left  < surf_rgn_data->rdh.rcBound.left  ) surf_rgn_data->rdh.rcBound.left   = clip_list[n].left;
		if(clip_list[n].top   < surf_rgn_data->rdh.rcBound.top   ) surf_rgn_data->rdh.rcBound.top    = clip_list[n].top;
		if(clip_list[n].right < surf_rgn_data->rdh.rcBound.right ) surf_rgn_data->rdh.rcBound.right  = clip_list[n].right;
		if(clip_list[n].bottom< surf_rgn_data->rdh.rcBound.bottom) surf_rgn_data->rdh.rcBound.bottom = clip_list[n].bottom;
	}

	
	clipper->SetClipList(surf_rgn_data, NULL);
	back_buffer->SetClipper(clipper);
	return clipper;

}

void gameInit(void) {
	DirectDrawCreateEx(NULL,(LPVOID*)&lpdd, IID_IDirectDraw7, NULL);
	lpdd->SetCooperativeLevel(glob_hwnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT|DDSCL_ALLOWMODEX);
	lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,BPP,0,0);

	memset(&surf_desc,0,sizeof(surf_desc));
	surf_desc.dwSize = sizeof(DDSURFACEDESC2);

	surf_desc.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
	surf_desc.dwBackBufferCount = 1;
	surf_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
	lpdd->CreateSurface(&surf_desc,&primary_surface,NULL);

	memset(&ddbltfx_black,0,sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(DDBLTFX);
	ddbltfx.dwFillColor = 0;
	primary_surface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx_black);

	surf_desc.dwFlags = DDSD_CAPS;
	surf_desc.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
	primary_surface->GetAttachedSurface(&surf_desc.ddsCaps, &back_buffer);

	back_buffer->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx_black);

	memset(&ddbltfx,0,sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(DDBLTFX);
	ddbltfx.dwFillColor = 200;
	
	

	teh_clip = createDdClipper(back_buffer, RECT_NUM, rect_list);

}

int gameMain(void) {
	if(KEYPRESSED(VK_ESCAPE)) {
		SendMessage(glob_hwnd, WM_CLOSE,0,0);
		return (0);
	}
	

	back_buffer->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx);
	primary_surface->Flip(NULL,DDFLIP_WAIT);
	Sleep(1000);
}
				
void wndInit(WNDCLASSEX *wnd_class, HWND *hwnd) {
	
	wnd_class->cbSize		= sizeof(WNDCLASSEX);
	wnd_class->style		= CS_HREDRAW|CS_VREDRAW;
	wnd_class->lpfnWndProc  = wndProc;
	wnd_class->cbWndExtra	= NULL;
	wnd_class->cbClsExtra	= NULL;
	wnd_class->hInstance	= app_hinst;
	wnd_class->hIcon		= LoadIcon(app_hinst, IDI_APPLICATION);
	wnd_class->hCursor		= LoadCursor(app_hinst, IDC_ARROW);
	wnd_class->hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wnd_class->lpszClassName= WND_CLASS_NAME;
	wnd_class->lpszMenuName = NULL;
	wnd_class->hIconSm		= LoadIcon(app_hinst, IDI_APPLICATION);

	RegisterClassEx(wnd_class);
	*hwnd = CreateWindowEx(NULL, WND_CLASS_NAME,
						   "DirectDraw manual image blitting", 
						   WS_POPUP|WS_VISIBLE, 0,0,
						   SCREEN_WIDTH,SCREEN_HEIGHT,
						   NULL,
						   NULL,
						   app_hinst,
						   NULL);
}

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE previnstance, LPSTR ncmdline, int ncmdshow) {
	
	WNDCLASSEX		wnd;
	MSG				msg;
	bool			_L00P_ = true;								
	
	app_hinst = hinstance;
	wndInit(&wnd, &glob_hwnd);
	

	gameInit();
	while(_L00P_) {
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
			if(msg.message == WM_QUIT) break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		gameMain();
	}

	return msg.wParam;
}




Advertisement
Your backbuffer contains corrupt, old data from when that memory space was used to render the desktop. For some reason your rendering code isn't properly targeting that buffer when it draws, so when that buffer is flipped to the front, you see garbage. Unfortunately at the moment I don't have time to look through your code to see where this may be going wrong, but in general you should be able to find the problem fairly easily by ensuring that the render logic targets the correct memory space.

Also you may want to try a massive ZeroMemory() on the backbuffer before you flip it (just as a debug) to see if you're flipping the right surface. If this works your backbuffer should render as solid black.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I still get it even if I fill the backbuffer with black after I attach it to the primary surface.This is annoying me, I can't get further if I don't fix it.Can you please help me?
This means you are not setting up and/or flipping the correct buffer to the front, or you're doing it at the wrong time. If you can find some sample code that does that type of flipping you should be able to compare and find where the problem is.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

You don't need to specify DDSCAPS_COMPLEX and DDSCAPS_FLIP for backbuffer. Remove those flags from back buffer initialization.

Use DDSURFACEDESC for primary buffer, but use DDSCAPS for backbuffer. ZeroMemory() first before you use them, and don't forget to set the dwSize.

You don't need to fill backbuffer with black. Since you will be drawing in it anyway. You may want to comment out your clipping initialization first, there might be something wrong with it. I never trusted DDBLTFX (because I never got it working [lol]), I used a blank bitmap instead.

Here's my DirectDraw initialization code (8-bit, there is an extra palette initialization at the end):
void InitDirectDraw( HWND hwnd, int screen_width, int screen_height, int bpp ){   gmHWindow = hwnd;   // Init DirectDraw   HRESULT retval = E_FAIL;   retval = DirectDrawCreate( NULL, &gmDirectDraw, NULL );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to create DirectDraw object." );   // Set cooperative level   retval = gmDirectDraw->SetCooperativeLevel( gmHWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to set exclusive cooperative level." );   // Set display mode   retval = gmDirectDraw->SetDisplayMode( screen_width, screen_height, bpp );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to set display mode to 640x480x8." );   // Create surfaces   DDSURFACEDESC  ddsd;   memset( &ddsd, 0, sizeof(ddsd) );   ddsd.dwSize            = sizeof(ddsd);   ddsd.dwFlags           = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;   ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;   ddsd.dwBackBufferCount = 1;   retval = gmDirectDraw->CreateSurface( &ddsd, &gmPrimarySurface, NULL );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to create the primary surface." );   gmPrimarySurface->Restore();   DDSCAPS ddcaps;   memset( &ddcaps, 0, sizeof(ddcaps) );   ddcaps.dwCaps = DDSCAPS_BACKBUFFER;   retval = gmPrimarySurface->GetAttachedSurface( &ddcaps, &gmSecondarySurface );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to create the secondary surface." );   gmSecondarySurface->Restore();   // Create clipper   retval = gmDirectDraw->CreateClipper( NULL, &gmClipper, NULL );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to create DirectDraw clipper object." );   retval = gmClipper->SetHWnd( 0, gmHWindow );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to set window handle to clipper object." );   gmSecondarySurface->SetClipper( gmClipper );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to set clipper object to back buffer." );   // Create Palette   PALETTEENTRY   pe[COLOR_COUNT];   for ( int i = 0; i < COLOR_COUNT; ++i )   {      pe.peRed = (unsigned char)i;      pe.peGreen = (unsigned char)i;      pe.peBlue = (unsigned char)i;   }   retval = gmDirectDraw->CreatePalette( DDPCAPS_8BIT , pe, &gmPalette, NULL );   if ( FAILED(retval) )      throw Exception( __FILE__, __LINE__, "Unable to create a palette." );}


Disclaimer: old code.
Fixed.I attached the clipper to the primary surface instead of the back buffer and it solved it.
I think it's because the created primary surface contained garbage data, like what has been said.I am sure I had tried to fill it with black earlier but it didn't help at all, before the app puts something on the screen.I'm not sure.

Sorry for the anonymous post, heh.It contains an error anyway, I meant back buffer :D :D :D

This topic is closed to new replies.

Advertisement