🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

WGL: High Memory Usage and Slow Startup

Started by
-1 comments, last by AbelCorver 14 years, 12 months ago
Hey guys, I just started writing my very first OpenGL app. I need to use WGL, so that I have full control over window creation. I managed to implement this functionality, so that I have a borderless window and everything seems to work fine when no drawing takes place. When I don't draw anything (and don't swap buffers) the app uses around 7 MB RAM. I guess that's normal, since a very minimal GLUT app uses that amount of memory too. However, as soon as I start drawing things, the memory usages rises to almost 25 - 30 MB! I don't think a simple blue rectangle takes that much space. I'm probably doing something wrong here... :D The 'CWindow.h' Header File:

#ifndef __CWINDOW_H__
#define __CWINDOW_H__

#include <Windows.h>
#include "IWindow.h"

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")

// =============================================================
// Name: CWindow
// Desc: Implements a window on Microsoft Windows (r).
// =============================================================

class CWindow : public IWindow {
public:
	// ---------------------------------------------------------
	// Public Methods
	// ---------------------------------------------------------

	// constructor / destructor
	CWindow( HINSTANCE hAppInstance );
	~CWindow();
	
	// ---------------------------------------------------------
	// Public Methods Inherited from IWindow
	// ---------------------------------------------------------
	
	bool InitWindow( unsigned int Width , unsigned int Height );
	bool SetAsRenderTarget();

	HDC GetGLDC(){ return m_hRenderTargetDC; }

private:
	// ---------------------------------------------------------
	// Private Member Variables
	// ---------------------------------------------------------

	// OpenGL / WGL variables (shared by all windows)
	static HWND	m_hRenderTargetWnd;
	static HDC m_hRenderTargetDC;
	static HGLRC m_hRenderTargetRC;

	// the handle to the window
	HWND m_hWnd;

	// the handle to the application instance
	HINSTANCE m_hAppInstance;
	
	// ---------------------------------------------------------
	// Private Methods
	// ---------------------------------------------------------
	
	// release this window as a render target ( e.g. release DC and GLRC )
	static bool ReleaseAsRenderTarget();

	// window procedures
	static LRESULT CALLBACK StaticWindowProcedure( HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam );
	LRESULT CALLBACK WindowProcedure( HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam );
};

#endif


The 'CWindow.cpp' Source File:

#include "CWindow.h"

#ifndef __CWINDOW_DEFSTATICS__
#define __CWINDOW_DEFSTATICS__

// define static variables
HWND	CWindow::m_hRenderTargetWnd	= NULL ;
HDC		CWindow::m_hRenderTargetDC	= NULL ;
HGLRC	CWindow::m_hRenderTargetRC	= NULL ;

#endif

// ---------------------------------------------------------
// Constructor and Destructor
// ---------------------------------------------------------

CWindow::CWindow( HINSTANCE hAppInstance )
{
	// save application instance handle
	m_hAppInstance = hAppInstance;

	// set other variables to null
	m_hWnd = NULL;
}

CWindow::~CWindow()
{
	// release as render target
	ReleaseAsRenderTarget();

	// clean-up
	if( m_hWnd != NULL ) DestroyWindow( m_hWnd );
	m_hWnd = NULL;

	// unregister window class
	UnregisterClass( "CWindowWin32" , m_hAppInstance );
}

bool CWindow::ReleaseAsRenderTarget() 
{
	bool bError = false;

	// Do we have a rendering context for OpenGL
	if( m_hRenderTargetRC) {

		// 'unassociate' DC with OpenGL RC
		bError |= !wglMakeCurrent( NULL , NULL ); 

		// delete render context
		bError |= !wglDeleteContext( m_hRenderTargetRC);
		m_hRenderTargetRC= NULL;
	}

	// Has device context?
	if( m_hRenderTargetDC ) {

		// delete DC
		bError |= !ReleaseDC( m_hRenderTargetWnd , m_hRenderTargetDC );
		m_hRenderTargetDC = NULL;
	}

	// Finish !!
	return !bError;
}

// ---------------------------------------------------------
// Name: CreateWindow (Public)
// Desc: Create a window.
// ---------------------------------------------------------

bool CWindow::InitWindow( unsigned int Width , unsigned int Height ) 
{
	// create window class
	WNDCLASS wc = {0};
	
	// save appplication instance handle
	wc.hInstance = m_hAppInstance;

	// icon & cursor information
	wc.hIcon	= LoadIcon	( m_hAppInstance , IDI_APPLICATION	);
	wc.hCursor	= LoadCursor( m_hAppInstance , IDC_ARROW		);

	// set background to black
	wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );

	// set window style (just a window without ANY borders)
	DWORD WndStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW /* | CS_OWNDC */ ;

	// set classname
	wc.lpszClassName = "CWindowWin32";

	// set window procedure
	wc.lpfnWndProc = StaticWindowProcedure;

	// register it!
	RegisterClass( &wc );

	// create the window
	if( m_hWnd != NULL ) DestroyWindow( m_hWnd );
	m_hWnd = CreateWindow( "CWindowWin32" , "" , WndStyle , 10 , 10 , Width , Height , 0 , 0 , m_hAppInstance , this ); 
	if( m_hWnd == NULL ) return false;

	// show the world!
	ShowWindow( m_hWnd , SW_SHOW );
	UpdateWindow( m_hWnd );

	// Success !!
	return true;
}

// ---------------------------------------------------------
// Name: SetAsRenderTarget
// Desc: Sets this window as the render target. Future calls 
//       to OpenGL will use this window as drawing canvas.
// ---------------------------------------------------------

bool CWindow::SetAsRenderTarget() 
{
	// declare static variables ( do the initialization process only once ) ...
	static PIXELFORMATDESCRIPTOR PixelFormat = {0};
	static int iPixelFmt = 0;

	// validate...
	// if( !m_bDrawable ) goto Failed;

	// release if necessary
	ReleaseAsRenderTarget();

	// save window handle
	m_hRenderTargetWnd = m_hWnd;

	// get window DC
	m_hRenderTargetDC = NULL;
	m_hRenderTargetDC = GetDC( m_hWnd );
	if( m_hRenderTargetDC == NULL ) goto Failed;

	// set desired pixel format
	if( PixelFormat.nSize == 0 ) {
		// set size of this structure
		PixelFormat.nSize = sizeof( PIXELFORMATDESCRIPTOR );
		
		// set version number
		PixelFormat.nVersion = 1;

		// set settings
		PixelFormat.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

		// set pixel format
		PixelFormat.iPixelType = PFD_TYPE_RGBA;

		// set pixel depth
		PixelFormat.cColorBits = 32;

		// set Z-buffer depth
		PixelFormat.cDepthBits = 16;

		// set main drawing layer
		PixelFormat.iLayerType = PFD_MAIN_PLANE;
		
		// find pixel format
		iPixelFmt = ChoosePixelFormat( m_hRenderTargetDC , &PixelFormat );
	}

	// check pixel format
	if( !iPixelFmt ) goto Failed;

	// now that we HAVE the pixel format, SET it also
	if( !SetPixelFormat( m_hRenderTargetDC , iPixelFmt , &PixelFormat ) ) goto Failed;

	// create a rendering context
	m_hRenderTargetRC= NULL;
	m_hRenderTargetRC= wglCreateContext( m_hRenderTargetDC );
	if( m_hRenderTargetRC== NULL ) goto Failed;

	// select this context
	if( !wglMakeCurrent( m_hRenderTargetDC , m_hRenderTargetRC) ) goto Failed;

	// Success !!
	return true;

// Shit! How did we reach this point!!
Failed:
	// Clean up the mess ...
	ReleaseAsRenderTarget();

	// Failure ...
	return false;
}

// ---------------------------------------------------------
// Name: StaticWindowProcedure (Static)(Private)
// Desc: Gateway for ALL window messages for this window.
// ---------------------------------------------------------

LRESULT CALLBACK CWindow::StaticWindowProcedure( HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam ) 
{
	if( Msg == WM_CREATE ) {
		// store pointer to window class in window structure
		if( lParam != 0 ) {
			// fetch pointer
			CWindow* pWnd = (CWindow*) lParam;
			// store...
			SetWindowLongPtr( hWnd , GWLP_USERDATA , (LONG_PTR) pWnd );
		}
	}

	// get pointer back...
	CWindow* pWnd = (CWindow*) GetWindowLongPtr( hWnd , GWLP_USERDATA );
	if( pWnd != 0 ) {
		// call local window procedure
		return pWnd->WindowProcedure( hWnd , Msg , wParam , lParam );
	}

	// do the standard stuff...
	return DefWindowProc( hWnd , Msg , wParam , lParam );
}

// ---------------------------------------------------------
// Name: WindowProcedure (Private)
// Desc: Handles messages for this window object.
// ---------------------------------------------------------

LRESULT CALLBACK CWindow::WindowProcedure( HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam ) 
{
	// Handle Messages
	switch( Msg ) {

		// -------------------------------------------------
		// Handle Keys
		// -------------------------------------------------

		case WM_KEYDOWN:
			switch( LOWORD(wParam) ) {
				case VK_ESCAPE: PostQuitMessage(0);
			} return 0;
	}

	// do the standard stuff...
	return DefWindowProc( hWnd , Msg , wParam , lParam );
}


The 'Main.cpp' File (starts my app and uses the CWindow class):

#include "CWindow.h"
#include "gl/gl.h"
#include "gl/glu.h"

void InitOpenGL()
{	
	// set background color to black
	glClearColor( 0.0 , 0.0 , 0.0 , 1.0 );

	// initialize view
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glOrtho( 0.0 , 1.0 , 1.0 , 0.0 , -1.0 , 1.0 );
}

void RenderScene( CWindow* pWnd ) 
{
	// clear buffer
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	// draw blue rectangle
	glColor3f( 0.0f , 0.0f , 1.0f );
	glBegin( GL_POLYGON );
		glVertex3f( 0.10f , 0.10f , 0.0f );
		glVertex3f( 0.60f , 0.10f , 0.0f );
		glVertex3f( 0.60f , 0.40f , 0.0f );
		glVertex3f( 0.10f , 0.40f , 0.0f );
	glEnd();

	// flush operations
	glFlush();

	// swap buffers
	SwapBuffers( pWnd->GetGLDC() );
}

int WINAPI WinMain( HINSTANCE hInst , 
				    HINSTANCE hPrevInst , 
					LPSTR lpCmdLine , 
					int showCmd )
{
	// create window
	CWindow* pWnd = new CWindow( hInst );
	pWnd->InitWindow( 800 , 700 );

	// init message variable
	MSG Msg; ZeroMemory( &Msg , sizeof( MSG ) );
			
	// Set Render Target			
	pWnd->SetAsRenderTarget();
	InitOpenGL();
	
	// enter game loop
	while( true ) {
		if( PeekMessage( &Msg , 0 , 0 , 0 , PM_REMOVE ) ) {
			if( Msg.message == WM_QUIT ) break;
			TranslateMessage( &Msg );
			DispatchMessage( &Msg );
		} else {
			// Render The Scene
			RenderScene( pWnd );
			// Sleep...
			Sleep(10);
		}
	}

	// Clean-up
	delete pWnd; 
	pWnd = 0;

	// Success !!
	return 0;
}


Thanks in advance! Regards, Abel.

This topic is closed to new replies.

Advertisement