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

pbuffer leaking memory

Started by rick_appleton Apr 25, 2004 at 5:10 PM 1 replies 1.7k views
Original Post
rick_appleton
rick_appleton
I've implemented a pBuffer (taken from ATI's example) to be able to render reflections and such. However, I have noticed I'm leaking memory (and quite a lot too). I've narrowed it down, and it seems to come from the wglMakeContextCurrentARB functions. So I'm guessing I'm doing something wrong. Here's my pbuffer class:
#include <windows.h>
#include "GL/glfw.h"
#include "GL/wglext.h"
#include "pbuffer.h"
#include "../rndrBase.h"

#define GL_CLAMP_TO_EDGE_EXT 0x812F

// handle, device context and render context for pbuffer buffer

HPBUFFERARB hPBuffer = NULL;
HDC hPBufferDC = NULL;
HGLRC hPBufferRC = NULL;

// variables to hold pbuffers dimensions

int pbufferWidth = 0;
int pbufferHeight = 0;

// texture object ID for binding pbuffer to a texture

GLuint pbufferTextureID = 0;

// allows us to foolproof the interface to prevent using the pbuffer before

// it is initialized

bool pbufferInitialized = false;

// pbuffer function prototypes

PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB = NULL;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = NULL;
PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = NULL;
PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = NULL;
PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = NULL;
PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = NULL;
PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB = NULL;
PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB = NULL;
PFNWGLSETPBUFFERATTRIBARBPROC wglSetPbufferAttribARB = NULL;

bool pbufferInit (int width, int height);
void pbufferEnable ();
void pbufferDisable ();
void pbufferBind (void);
void pbufferRelease (void);
void pbufferDestroy (void);

void printError(const char*)
{
}

bool pbufferInit (int width, int height)
{
	// initialize extension entry points

	wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)
	wglGetProcAddress("wglMakeContextCurrentARB");
	wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)
	wglGetProcAddress("wglChoosePixelFormatARB");
	wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)
	wglGetProcAddress("wglCreatePbufferARB");
	wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)
	wglGetProcAddress("wglDestroyPbufferARB");
	wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)
	wglGetProcAddress("wglGetPbufferDCARB");
	wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)
	wglGetProcAddress("wglReleasePbufferDCARB");
	wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)
	wglGetProcAddress("wglQueryPbufferARB");
	wglBindTexImageARB =(PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB");
	wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)
	wglGetProcAddress("wglReleaseTexImageARB");
	wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)
	wglGetProcAddress("wglSetPbufferAttribARB");
	
	// do some error checking to make sure function pointers were initialized correctly

	if (wglMakeContextCurrentARB == NULL)
	{
		printError ("Can't init wglMakeContextCurrentARB");
		return(false);
	}
	if (wglChoosePixelFormatARB == NULL)
	{
		printError ("Can't init wglChoosePixelFormatARB");
		return(false);
	}
	if (wglCreatePbufferARB == NULL)
	{
		printError ("Can't init wglCreatePbufferARB");
		return(false);
	}
	if (wglDestroyPbufferARB == NULL)
	{
		printError ("Can't init wglDestroyPbufferARB");
		return(false);
	}
	if (wglGetPbufferDCARB == NULL)
	{
		printError ("Can't init wglGetPbufferDCARB");
		return(false);
	}
	if (wglReleasePbufferDCARB == NULL)
	{
		printError ("Can't init wglReleasePbufferDCARB");
		return(false);
	}
	if (wglQueryPbufferARB == NULL)
	{
		printError ("Can't init wglQueryPbufferARB");
		return(false);
	}
	if (wglBindTexImageARB == NULL)
	{
		printError ("Can't init wglBindTexImageATIX");
		return(false);
	}
	if (wglReleaseTexImageARB == NULL)
	{
		printError ("Can't init wglReleaseTexImageATIX");
		return(false);
	}
	if (wglSetPbufferAttribARB == NULL)
	{
		printError ("Can't init wglSetPbufferAttribATIX");
		return(false);
	}
	
	// if the pbuffer is already initialized make sure the previous buffer

	// is freed before allocating a new one.

	if (pbufferInitialized)
	{
		pbufferDestroy();
	}
	
	// keep track of the pbuffer size incase we have to create a new one

	// because of a display mode change.

	pbufferWidth = width;
	pbufferHeight = height;
	
	// define the minimum pixel format requirements we will need for our pbuffer

	// a pbuffer is just like a frame buffer, it can have a depth buffer associated

	// with it and it can be double buffered.

	int attr[] =
	{
		WGL_SUPPORT_OPENGL_ARB, TRUE, // pbuffer will be used with gl

		WGL_DRAW_TO_PBUFFER_ARB, TRUE, // enable render to pbuffer

		WGL_BIND_TO_TEXTURE_RGBA_ARB, TRUE, // pbuffer will be used as a texture

		//WGL_RED_BITS_ARB, 8, // at least 8 bits for RED channel

		//WGL_GREEN_BITS_ARB, 8, // at least 8 bits for GREEN channel

		//WGL_BLUE_BITS_ARB, 8, // at least 8 bits for BLUE channel

		//WGL_ALPHA_BITS_ARB, 8, // at least 8 bits for ALPHA channel

		WGL_COLOR_BITS_ARB, 32,
		WGL_DEPTH_BITS_ARB, 24, // at least 24 bits for depth buffer

		WGL_DOUBLE_BUFFER_ARB, FALSE, // we don’t require double buffering

		0 // zero terminates the list

	};

	// choose a pixel format that meets our minimum requirements

	unsigned int count = 0;
	int pixelFormat;
	wglChoosePixelFormatARB(renderer->window.dc,(const int*)attr, NULL, 1,&pixelFormat,&count);
	if(count == 0)
	{
		printError("P-buffer Error: Unable to find an acceptable pixel format");
		return(false);
	}
	
	// set some pbuffer attributes so that we can use this pbuffer as a

	// 2D RGBA texture target

	int pAttrib[] =
	{
		WGL_TEXTURE_FORMAT_ARB, // our pbuffer will have texture format RGBA

		WGL_TEXTURE_RGBA_ARB,
		WGL_TEXTURE_TARGET_ARB, // of texture type GL_TEXTURE_2D

		WGL_TEXTURE_2D_ARB,
		0 // zero terminates the list

	};

	// allocate the pbuffer

	hPBuffer = wglCreatePbufferARB(renderer->window.dc, pixelFormat, width, height, pAttrib);
	hPBufferDC = wglGetPbufferDCARB(hPBuffer);
	hPBufferRC = wglCreateContext(hPBufferDC);
	if(!hPBuffer)
	{
		printError("P-buffer Error: Unable to create P-buffer");
		return(false);
	}

  glShadeModel(GL_SMOOTH);							// Enable Smooth Shading

	glClearColor(0.0f, 0.1f, 0.0f, 1.f);				// Black Background

	glClearDepth(1.0f);									// Depth Buffer Setup

	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing

	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do

	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations

	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);	// Really Nice Perspective Calculations


	// make a texture object for binding the pbuffer to

	glGenTextures(1, &pbufferTextureID);
	glBindTexture(GL_TEXTURE_2D, pbufferTextureID);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE_EXT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE_EXT);
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//GL_CLAMP_TO_EDGE_EXT);

	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//GL_CLAMP_TO_EDGE_EXT);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	pbufferInitialized = true;
	return(true);
}

// ****************************************************************************

// pbufferEnable: change the current context such that we will now be writing

// to the pbuffer. also, resize viewport to size width by height.

// ****************************************************************************

void pbufferEnable ()
{
	// make sure the pbuffer has been initialized

	if (!(pbufferInitialized))
	{
		return;
	}
	
	// make sure we haven't lost our pbuffer due to a display mode change

	int flag = 0;
	wglQueryPbufferARB(hPBuffer, WGL_PBUFFER_LOST_ARB, &flag);
	if (flag != 0)
	{
		return;
	}

	// set read/write context to pbuffer

	wglMakeContextCurrentARB(hPBufferDC, hPBufferDC, hPBufferRC);
	//wglMakeCurrent(hPBufferDC, hPBufferRC);


	// draw & read the front buffer of pbuffer

	glDrawBuffer(GL_FRONT);
	glReadBuffer(GL_FRONT);
	
	// resize view port. generally you'll want to set this to the

	// size of your pbuffer so that you render to the entire pbuffer

	// but there are cases where you might want to render to just a

	// sub-region of the pbuffer.

	glViewport(0.0, 0.0, pbufferWidth, pbufferHeight);
	
	return;
}

// ****************************************************************************

// pbufferDisable: change the current context such that we will now be writing

// to the framebuffer again. also, resize viewport to size width by height.

// ****************************************************************************

void pbufferDisable ()
{
	// make sure the pbuffer has been initialized

	if (!(pbufferInitialized))
	{
		return;
	}
	
	// make sure we haven't lost our pbuffer due to a display mode change

	int flag = 0;
	wglQueryPbufferARB(hPBuffer, WGL_PBUFFER_LOST_ARB, &flag);
	if (flag != 0)
	{
		return;
	}

	// set read/write context back to gl device

	wglMakeContextCurrentARB(renderer->window.dc, renderer->window.dc, renderer->window.rc);
	//wglMakeCurrent(renderer->window.dc, renderer->window.rc);


	// draw to the back buffer of frame buffer

	// read from the front buffer of the frame buffer

	glDrawBuffer(GL_BACK);
	glReadBuffer(GL_FRONT);
	
	// reset the view port

	glViewport(0.0, 0.0, renderer->window.width, renderer->window.height);
	return;
}

// ****************************************************************************

// pbufferBind: bind the pbuffer to a texture. while the pbuffer is bound to a

// texture object, it is illegal to read or write to the pbuffer until it is

// released.

// ****************************************************************************

void pbufferBind (void)
{
	// make sure the pbuffer has been initialized

	if (!(pbufferInitialized))
	{
		return;
	}
	
	// make sure we haven't lost our pbuffer due to a display mode change

	int flag = 0;
	wglQueryPbufferARB(hPBuffer, WGL_PBUFFER_LOST_ARB, &flag);
	if (flag != 0)
	{
		pbufferInit(pbufferWidth, pbufferHeight);
	}

	// bind a texture object that we will associate a pbuffer with

	glBindTexture (GL_TEXTURE_2D, pbufferTextureID);
	
	// bind pbuffer to the currently bound texture object

	// while the pbuffer is bound to a texture it is illegal

	// to read or write from the pbuffer until it is released

	wglBindTexImageARB(hPBuffer, WGL_FRONT_LEFT_ARB);
	return;
}

// ****************************************************************************

// pbufferRelease: release the pbuffer from the texture it was bound to. once

// the pbuffer is released you will be able to render to it again by calling

// pbufferEnable()

// ****************************************************************************

void pbufferRelease (void)
{
	// make sure the pbuffer has been initialized

	if (!(pbufferInitialized))
	{
		return;
	}
	
	// release the pbuffer so that it can be rendered to again

	wglReleaseTexImageARB(hPBuffer, WGL_FRONT_LEFT_ARB);
	return;
}

// ****************************************************************************

// pbufferDestroy: free all resources associated with the pbuffer

// ****************************************************************************

void pbufferDestroy (void)
{
	glDeleteTextures(1, &pbufferTextureID);

	// make sure the pbuffer has been initialized

	if (!(pbufferInitialized))
	{
		return;
	}
	
	if (!	wglReleaseTexImageARB(hPBuffer, WGL_FRONT_LEFT_ARB))
		int i=5;
	if (!	wglDeleteContext(hPBufferRC))
		int i=5;
	if (!	wglReleasePbufferDCARB(hPBuffer, hPBufferDC))
		int i=5;
	if (!	wglDestroyPbufferARB(hPBuffer))
		int i=5;
	pbufferInitialized = false;
	return;
}

and how I use it:
   
#include "shdrCubemap.h"
#include "GL/glfw.h"
#include "pbuffer.h"

VALUE_ID Cubemap_Shader::CUBEMAP_ID;


TextureInfo *tmp;

void Cubemap_Shader::Enter( TextureInfo *texInfo ) 
{
	texInfo->isVisible = false;
	tmp = texInfo;
	pbufferEnable ();
	

  glShadeModel(GL_SMOOTH);							// Enable Smooth Shading

	glClearColor(0.f, 0.f, 0.2f, 1.f);				// Black Background

	glClearDepth(1.0f);									// Depth Buffer Setup

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer

	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing

	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do

	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations

	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);	// Really Nice Perspective Calculations

	glEnable(GL_POLYGON_SMOOTH);

	glMatrixMode(GL_MODELVIEW);
	float matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1};
	glPushMatrix();
	glLoadMatrixf(&matrix[0]);

	// Cliplane on the reflector

	double equation[] = {0., 0., 1., 0.};
	glClipPlane(GL_CLIP_PLANE0, &equation[0]);
	glEnable(GL_CLIP_PLANE0);
	
	// Call main rendering function

	renderer->RenderGroup(SG_MAIN);
	renderer->RenderGroup(SG_TRANSPARENT);

	glDisable(GL_CLIP_PLANE0);
	glPopMatrix();

	if (!propMap->AddProperty("rendertotextureID", &texIDCubemap))
		propMap->SetProperty("rendertotextureID", texIDCubemap);

}

void Cubemap_Shader::Exit( void )
{
	pbufferDisable ();
	tmp->isVisible = true;
}

void Cubemap_Shader::GetValue( VALUE_ID id, long *value )
{
	if (id==CUBEMAP_ID)
		*value = (long)texIDCubemap;
}

void Cubemap_Shader::Init( void )
{
	bool okay = pbufferInit(1024,1024);
	if (!okay)
		exit(0);
	texIDCubemap = pbufferTextureID;
}

void  Cubemap_Shader::DeInit( void )
{
	pbufferDestroy ();
}

Cubemap_Shader::~Cubemap_Shader( void )
{
	DeInit();
}
Yes, I know it's not a cubemap, but I'm still working on it. If you have any idea, I'll welcome it. [edited by - rick_appleton on April 26, 2004 5:49:53 PM]
GKW
GKW
Are you sure this code works? Not much in the way off error reporting.

if (! wglReleaseTexImageARB(hPBuffer, WGL_FRONT_LEFT_ARB))
int i=5;
if (! wglDeleteContext(hPBufferRC))
int i=5;
if (! wglReleasePbufferDCARB(hPBuffer, hPBufferDC))
int i=5;
if (! wglDestroyPbufferARB(hPBuffer))
int i=5;
pbufferInitialized = false;
return;


"... we should have such an empire for liberty as she has never surveyed since the creation ..."
Thomas Jefferson

[edited by - GKW on April 27, 2004 12:16:06 PM]
"... we should have such an empire for liberty as she has never surveyed since the creation ..."Thomas Jefferson

Topic Locked

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

Sign in to reply to this topic.