Jump to content
  • Advertisement
Sign in to follow this  
ChocoboX

Distorted desktop image when flipping ?

This topic is 5048 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

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;
}




Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!