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.