Skip to main content
GameDev.net gamedev.net
🔒 Locked

Software renderer problem - Error in CreateCompatibleBitmap()

Started by Chetanhl Sep 6, 2010 at 9:58 AM 6 replies 1.9k views
Original Post
Chetanhl
Chetanhl
Hi
I am working on a software renderer (wireframe only).
After making all that maths library for it am stuk at this GDI function - CreateCompatibleBitmap()

I am trying to draw things on a bitmap and then stretch it to client area of window using BitBlit() function.

Problem is in MakeFrameBuffer() Call to CreateCompatibleBitmap() always failed and as a result it returns false. Even if i let the application running nothing is displayed except a white window.
I have checked my maths library by rendering things in directx using matrices generated by my library.
I have searched alot on net but can't make it work.


Here's some of the code involved -

chWindow - It creates and manages the application window and passes window handle to chSoftwareRenderer

chSoftwareRenderer - It Creates and manages bitmap and presents it application window.



class chSoftwareRenderer{public:	chSoftwareRenderer(HWND windowHandle,int width,int height);	~chSoftwareRenderer(void);	void GetViewMatrix(const chMatrix* viewMat);	void GetProjectionMatrix(const chMatrix* projMat);	bool MakeFrameBuffer();	//void EndDrawing();	void ClearFrameBuffer();	void Present();	void DrawPrimitive(chVector3* vertices,int size,const chMatrix* worldMatrix);//private:	int wd,ht,vx,vy;	chMatrix projMatrix,viewMatrix;	HWND wndHandle;	HDC hdcFrameBuffer;	HBITMAP hbtFrameBuffer,hOldBitmap;	void DrawLine(const chVector3* v1,const chVector3 *v2);};




chSoftwareRenderer::chSoftwareRenderer(HWND windowHandle){	assert(windowHandle!=0);	this->wd = width;	ht = height;	this->wndHandle = windowHandle;	projMatrix.Identity();	viewMatrix.Identity();	RECT rc;	GetClientRect(wndHandle,&rc);	vx = rc.left;	vy = rc.top;	wd = rc.right - rc.left;	ht = rc.bottom - rc.top;}void chSoftwareRenderer::Present(){	HDC hdc = GetDC(wndHandle);	BitBlt(hdc,vx,vy,wd,ht,hdcFrameBuffer,vx,vy,SRCCOPY);	ReleaseDC(wndHandle,hdc);}bool chSoftwareRenderer::MakeFrameBuffer(){	HDC hdc = NULL;	hdc = GetDC(wndHandle);	if(!hdcFrameBuffer)		hdcFrameBuffer = CreateCompatibleDC(hdc);	if(hbtFrameBuffer)	{		SelectObject(hdcFrameBuffer,hOldBitmap);		DeleteObject(hbtFrameBuffer);		hbtFrameBuffer = NULL;		hOldBitmap = NULL;	}		hbtFrameBuffer = CreateCompatibleBitmap(hdcFrameBuffer,wd,ht);	if(!hbtFrameBuffer)		return false;	hOldBitmap = (HBITMAP)SelectObject(hdcFrameBuffer,hbtFrameBuffer);	ReleaseDC(wndHandle,hdc);	SetBkMode(hdcFrameBuffer,TRANSPARENT);}
empirical2
empirical2
A quick glance and I cannot see anything obviously wrong.

The only thing I notice with the Windows code example is that they supply the ORIGINAL DC not the new one. (e.g for you CreateCompatibleBitmap(hdc,wd,ht);)

I would have thought you could use the new hDC. However checking my own code library I notice that I also use the hDC I pulled from the window to create the Bitmap.

If however, that does not work:

Place a break point on the line for CreateCompatibleBitmap and check the input is correct. Check the DC is not null and that the dimensions are not less than 1 (for some reason).

If the arguments are correct, call GetLastError immediately after that line.
Chetanhl
Chetanhl
@empirical2 Thanks alot man.
using orignal dc worked but strange that in msdn it is given we shld use commpatibleDC.
Also I checked output of GetLastError() while using CreateCompatibleDC it gave me zero everytime. Parameters are correct too.
empirical2
empirical2
Quote:
Original post by Chetanhl
@empirical2 Thanks alot man.
using orignal dc worked but strange that in msdn it is given we shld use commpatibleDC.
Also I checked output of GetLastError() while using CreateCompatibleDC it gave me zero everytime. Parameters are correct too.


Actually in the MSDN example code it shows using the hDC from the window, which is where I got the suggestion from :)
jwezorek
jwezorek
bool chSoftwareRenderer::MakeFrameBuffer(){	HDC hdc = NULL;	hdc = GetDC(wndHandle);	if(!hdcFrameBuffer)		hdcFrameBuffer = CreateCompatibleDC(hdc);	if(hbtFrameBuffer)	{           [...]	}		hbtFrameBuffer = CreateCompatibleBitmap(hdcFrameBuffer,wd,ht);        [...]}

This is a common mistake that people make when programming to the Win32 API: you don't want to call CreateCompatibleBitmap with an HDC that was returned from CreateCompatibleDC. Honestly I don't remember the story any more: I think that immediately after to the call to CreateCompatibleDC hdc will have a monochrome single pixel bitmap selected into it and you are then making a bitmap that is compatible to that. Anyway, just get in the habit of always calling CreateCompatible-anything with the screen's device context unless you have a very good reason not to and you will never run into this problem again.
Chetanhl
Chetanhl
I wanted to use CreateCompatibleDC only from what i learned on msdn & searchign around.
But thing is i cant make it work using above code.
Everytime i use CompatibleDC CreateCompatibleBitmap call fails.
yadango
yadango
Another thing I noticed in your code in MakeFrameBuffer, is that you never return true either. So MakeFrameBuffer is always going to return false.



[Edited by - yadango on September 7, 2010 12:32:03 AM]
jwezorek
jwezorek
Quote:
Original post by Chetanhl
I wanted to use CreateCompatibleDC only from what i learned on msdn & searchign around.
But thing is i cant make it work using above code.
Everytime i use CompatibleDC CreateCompatibleBitmap call fails.


HDC hdcScreen = GetDC(NULL);HDC hdcBitmap = CreateCompatibleDC(hdcScreen);HBITMAP bitmap = CreateCompatibleBitmap(hdcScreen, wd, hgt);HBITMAP old_bitmap = (HBITMAP) SelectObject(hdcBitmap, bitmap);// do stuff with bitmap via hdcBitmap SelectObject(hdcBitmap, old_bitmap);//DeleteObject(bitmap) /*if you don't need it...*/DeleteDC(hdcBitmap);ReleaseDC(NULL, hdcScreen);

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.