Pbuffer and extension function pointers..

Hey all, I’m trying to use pbuffers for my little tech demo ( http://postpose.com/dbarrie/graphics ), and I’m running into some problems.

My code uses quite a few OGL extensions, which means I use wglGetProcAddress to access their function pointers. However, it seems that since my pbuffer uses a different context than the main one, I can not use these same pointers when drawing with my pbuffer. This wouldn’t be such a big deal if all I had to do was store a list of function pointers with each rendering context, but since I’m using Cg, it allocates function pointers as well, and it breaks quite hard when using pbuffers. Anyone know a way around this?

ShareContext

What is this function and where is it defined, because none of my gl headers have it…?

i think he means to share your pbuffer context with the visual…since that’s the crux of your problem…multiple contexts…or so it would seem. perhaps he was in a hurry to a meeting at the round table and didn’t have time to spell it all out :slight_smile:

…are you sure about the cg business? are you sharing lists? i don’t understand your problem to be honest about it. seems like this oughta just work…works for me in windows without any fuss. maybe you missed a step somewhere…

regards,
bonehead

Well, let me make sure that I’ve got the process correct then:

  1. Set up your main context (GLUT is doing this for me at the moment). Get pointers to the HDC and HGLDC of this main context.

  2. Get a pixel format that will work for your pbuffer, then create the pbuffer. Since this is a different context than the main one, you also need to get a new Cg context. Right now, I’m using:

void createLightPbuffer (void)
{
	// pbufferage
	gHDC = wglGetCurrentDC();
	gHGLRC = wglGetCurrentContext();

	int format = 0;
	unsigned int numformats;

	const int attributes[] = {	WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE,
								WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
								WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ARB,
								WGL_RED_BITS_ARB, 32,
								WGL_DEPTH_BITS_ARB, 24,
								WGL_BIND_TO_TEXTURE_RGBA_ARB, GL_TRUE,
								WGL_DOUBLE_BUFFER_ARB, GL_FALSE,
								0 };

	const int cubemap_flags[] = {	WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
									WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_CUBE_MAP_ARB,
									//WGL_MIPMAP_TEXTURE_ARB, GL_TRUE,
									0 };

	if (!wglChoosePixelFormatARB(gHDC, attributes, NULL, 1, &format, &numformats))
	{
		std::cout << "Could not choose pixel format for pbuffer, GetLastError() returned" << GetLastError() << std::endl;
		exit(1);
	}
	if (format == 0)
	{
		std::cout << "No suitable pixel format found for pbuffer!" << std::endl;
		exit(1);
	}

	lightPbuffer.hPB = wglCreatePbufferARB(gHDC, format, SHADOWMAP_SIZE, SHADOWMAP_SIZE, cubemap_flags);
	assert (lightPbuffer.hPB);
	lightPbuffer.hDC = wglGetPbufferDCARB (lightPbuffer.hPB);
	assert (lightPbuffer.hDC);
	lightPbuffer.hGLRC = wglCreateContext (lightPbuffer.hDC);
	assert (lightPbuffer.hGLRC);
	if (!wglShareLists(gHGLRC, lightPbuffer.hGLRC))
	{
		std::cout << "Couldnt' share lists" << std::endl;
		exit(1);
	}

	wglMakeCurrent(lightPbuffer.hDC, lightPbuffer.hGLRC);

	lightPbuffer.glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
	lightPbuffer.wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress("wglSetPbufferAttribARB");

	// set up cg too
	lightPbuffer.cgContext = cgCreateContext();
	assert(lightPbuffer.cgContext);
	
	lightPbuffer.cgVertProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
	assert(lightPbuffer.cgVertProfile != CG_PROFILE_UNKNOWN);
	cgGLSetOptimalOptions(lightPbuffer.cgVertProfile);

	lightPbuffer.cgFragProfile = cgGLGetLatestProfile (CG_GL_FRAGMENT);
	assert(lightPbuffer.cgFragProfile != CG_PROFILE_UNKNOWN);
	cgGLSetOptimalOptions(lightPbuffer.cgFragProfile);
	glEnable (GL_CULL_FACE);
	glEnable (GL_DEPTH_TEST);

	wglMakeCurrent(gHDC, gHGLRC);
} 

To do this.

  1. Make the main context current again with wglMakeCurrent().

Actually USING the pbuffer:

  1. Make the pbuffer’s context current. Set up everything required to render what you want (projection/modelview matrices, etc).

  2. Render what you want into the pbuffer.

  3. Make the main context current again, and bind the pbuffer to a texture with wglBindTexImageARB(). Draw using the texture bound to the pbuffer. Then unbind the pbuffer so that you can draw to it again.

  4. You’re done!

Now, this is what I’m doing, but after setting up the Cg context for the pbuffer, when I try to make the main context current again, gDEBugger pops up an error about glGenProgramsARB, the error being:

Error code: AP_FOREIGN_CONTEXT_EXTENSION_FUNC_CALL_ERROR.

Error description:
The debugged process asked for an extension function pointer (glGenProgramsARB) from one render context, but called this function pointer in another render context (contex #2)

So I’m just confused. :frowning:

i’m puzzled by your decision to init cg in your pbuffer context…is there wisdom in this? in my world cg is init’ed with my visual context and life is good.

regards,
bonehead

Well, I first tried just initing it in my visual context, and that gave the same error. Then I tried making a seperate context that was initied when I created the pbuffers, which produced the same error as well.