PBuffer creation..... ?

Hello,

I’m having a hard time creating a pbuffer. I know how to set them up, I’ve used them before, but only in single-windowed apps.

This time I have a non-OpenGL app running and I need to create a pbuffer “on top” of it. OK, I need an OpenGL DC/RC in order to query for the WGL_xxx_ARB pointers. So, I created a dummy window with GLUT, and used glutHideWindow() to hide it as I don’t like it being shown. wglGetProcAddress works fine now, gets all the pointers for the ext string, WGL_ARB_pbuffer, WGL_ARB_pixel_format and WGL_ARB_render_texture. So far, so good…

The problem is with wglCreatePbufferARB(). It complains about an invalid handle. I am not very good at MFC and all that M$ Window creation stuff, someone please advise what’s wrong…

Here’s the code:

—8<–8<— snip snip —8<–8<—

GLUT creates a window, hidden with glutHideWindow();

—8<–8<— snip snip —8<–8<—

// Get the entry point for the OpenGL extensions string.
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress(“wglGetExtensionsStringARB”);

char* ext = NULL;
if( wglGetExtensionsStringARB ) {
ext = (char*)wglGetExtensionsStringARB( wglGetCurrentDC() );
} else {
return FALSE;
}

// WGL_ARB_pbuffer
if( strstr( ext, “WGL_ARB_pbuffer” ) == NULL ) {
return FALSE;
} else {
wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress(“wglCreatePbufferARB”);
wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress(“wglGetPbufferDCARB”);
wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress(“wglReleasePbufferDCARB”);
wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress(“wglDestroyPbufferARB”);
wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress(“wglQueryPbufferARB”);

  if( !wglCreatePbufferARB &#0124; &#0124; !wglGetPbufferDCARB &#0124; &#0124; !wglReleasePbufferDCARB &#0124; &#0124; !wglDestroyPbufferARB &#0124; &#0124; !wglQueryPbufferARB ) {
  	return FALSE;
  }

}

// WGL_ARB_pixel_format
if( strstr( ext, “WGL_ARB_pixel_format” ) == NULL ) {
return FALSE;
} else {
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress(“wglChoosePixelFormatARB”);
if( !wglChoosePixelFormatARB ) {
return FALSE;
}
}

// WGL_ARB_render_texture
if( strstr( ext, “WGL_ARB_render_texture” ) == NULL ) {
return FALSE;
} else {
wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress(“wglBindTexImageARB”);
wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress(“wglReleaseTexImageARB”);
wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress(“wglSetPbufferAttribARB”);
if( !wglBindTexImageARB | | !wglReleaseTexImageARB | | !wglSetPbufferAttribARB ) {
return FALSE;
}
}

// Get current OpenGL Device and Rendering Contexts
m_hGLDC = NULL;
m_hGLRC = NULL;

m_hGLDC = wglGetCurrentDC(); // THESE WORK FINE,
m_hGLRC = wglGetCurrentContext(); // No errors with GetLastError() at least…

if (m_hGLDC == NULL | | m_hGLRC == NULL) {
return FALSE;
}

// Choose the a suitable pixel format.
int pf_attr = {
WGL_SUPPORT_OPENGL_ARB, TRUE, // pbuffer will be used with OpenGL
WGL_DRAW_TO_PBUFFER_ARB, TRUE, // Enable rendering to pbuffer
WGL_BIND_TO_TEXTURE_RGBA_ARB, TRUE, // Texture binding wanted
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, // Full hardware acceleration needed
WGL_RED_BITS_ARB, 8, // Red channel : Number of bits needed
WGL_GREEN_BITS_ARB, 8, // Green channel : Number of bits needed
WGL_BLUE_BITS_ARB, 8, // Blue channel : Number of bits needed
WGL_ALPHA_BITS_ARB, 8, // Alpha channel : Number of bits needed
WGL_STENCIL_BITS_ARB, 8, // Stencil buffer: Number of bits needed
WGL_DOUBLE_BUFFER_ARB, FALSE, // No double-buffering needed.
0 // Zero terminates the list.
};

unsigned int count = 0;
int pixelFormat;
wglChoosePixelFormatARB(m_hGLDC, (const int*)pf_attr, NULL, 1, &pixelFormat, &count);
if (count == 0) {
return FALSE;
}

// Define some attributes for the pbuffer.
int pAttrib = {
WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, // Pbuffer texture format: RGBA
WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, // Texture type: GL_TEXTURE_2D
0 // Zero terminates the list.
};

// Create the pbuffer.
m_pbuffer.hPBuffer = NULL;
m_pbuffer.hDC = NULL;
m_pbuffer.hRC = NULL;
m_pbuffer.nWidth = 512;
m_pbuffer.nHeight= 512;

====> m_pbuffer.hPBuffer = wglCreatePbufferARB(m_hGLDC, pixelFormat, m_pbuffer.nWidth, m_pbuffer.nHeight, pAttrib); // Gives error “6”
error = GetLastError();
====> m_pbuffer.hDC = wglGetPbufferDCARB(m_pbuffer.hPBuffer); // Gives error “6”
error = GetLastError();
m_pbuffer.hRC = wglCreateContext(m_pbuffer.hDC); // No error (0)
error = GetLastError();

// Enable the pbuffer.
wglMakeContextCurrentARB(m_pbuffer.hDC, m_pbuffer.hDC, m_pbuffer.hRC);

—8<–8<— snip snip —8<–8<—

The problematic line is marked with ====> wglCreatePbufferARB(m_hGLDC, pixelFormat, m_pbuffer.nWidth, m_pbuffer.nHeight, pAttrib);

wglCreatePbufferARB() gives the error code 6 (using GetLastError()), I looked it up and it means invalid handle.
wglGetPbufferDCARB() gives the same error, 6.
wglCreateContext() gives 0, so no error there…

I’ve tried getting the DC with GetDC(parent_window_handle) but that doesn’t work much better than with m_hGLDC = wglGetCurrentDC(); … both give a handle and a no error…

I’ve called GetLastError() after every single function call, only the two marked with ====> give an error.

Why is the handle invalid ? This might be trivial, but as I said I’m not very familiar with Windows programming…

Thanks for any help,

Andru

I could only find this syntax error:

if (m_hGLDC == NULL | | m_hGLRC == NULL) { return FALSE; }

A space in | |.

Strange, that space between the |'s is not in my original code, and all that code was cut&pasted… Anyway, the original post is now edited and that’s not the problem, thanks for pointing it out, though, kansler

Wonder what’s wrong…? I’m playing with GLUT windows and trying to get a valid handle…

edit: OK guys, ignore the | | instead of | | in the code… I don’t know why but all the | |'s got a space in between them when I cut&pasted the code (!) Something wrong with the

 UBB tag perhaps (?) Anyway, help with the original problem greatly appreciated!

Andru

[This message has been edited by Andru (edited 07-08-2003).]

Anyone have any idea what’s wrong here…?

I ditched GLUT, and created my own window -> same errors still.

I’m confused…

Andru

Two things come to mind.
-I’m assuming that extension loading code succeeds, but to make sure, what does glGetString(GL_VENDOR) return?

-Double check that the pixel format returned by wglChoose*ARB() is valid by using a program such as “NV Pixel Format”.

On what hw,OS,driver?

This is on an Intel P4 2,something GHz, Radeon 9800 Pro and Win2k with latest SPs installed, Catalyst v3.5 drivers. Same problem was with v3.4, too.

const GLubyte* tmp2=glGetString(GL_VENDOR); --> “ATI Technologies Inc.”
const GLubyte* tmp3=glGetString(GL_RENDERER); --> “Radeon 9800 Pro x86/SSE2”
const GLubyte* tmp4=glGetString(GL_VERSION); --> “1.3.3803 Win2000 Release”
const GLubyte* tmp5=glGetString(GL_EXTENSIONS); --> A whole slew of EXTs, including all the ones used/needed.

The pixel format is correct, I get 1 as pixelFormatm, which suits fine.

I checked a pbuffer tutorial, and run-time debugged it and found out that I get the same errors in the same places, but the tutorial works and my app hangs in wglMakeContextCurrentARB()…

Does a pbuffer’s size have to be a power of 2, even if I don’t bind it to a texture ?

I’ve only tried sizes 256x256 and 512x512 so far, though.

Andru

EDIT: Woohooo it works!!! If I use wglMakeCurrent() instead of wglMakeContextCurrentARB() it works fine. The ATI pbuffer paper tells to use wglMakeContextCurrentARB, though (?) Anyway, now it works, even though the ERROR_INVALID_HANDLE (error 6) still gets thrown from both wglCreatePbufferARB() and wglGetPbufferDCARB().

wglDestroyPbufferARB() also throws error 1425 (ERROR_DC_NOT_FOUND). This also happens in the pbuffer tutorial thingy.

Peculiar indeed… it works, but I’d like to get it error-free, still.

[This message has been edited by Andru (edited 07-10-2003).]

Originally posted by Andru:
I checked a pbuffer tutorial, and run-time debugged it and found out that I get the same errors in the same places, but the tutorial works and my app hangs in wglMakeContextCurrentARB()…

Weird, what pixelformat/pbuffer attribs does the tut use? Same?

[b]

Does a pbuffer’s size have to be a power of 2, even if I don’t bind it to a texture ?
[/b]

I did some testing for you and found some interesting results. First of all, I checked the specs for any size restrictions and couldn’t find any(ok I didn’t look that close). Then I tried allocating an even sized(non-power of 2), and also an uneven sized pbuffer. Both were created successfully. But when I later used them, they both caused crashes in nvoglnt.dll(using 44.65 beta drivers). So to answer your question: yes it seems like the pbuffer must be of power of 2 size.

I think I jumped too some quick conclusions there. I just remembered that I had a bind texture to pbuffer call in my test code, and when I removed that, the code didn’t crash. But no errors were ever generated. Not from wglBindTexImageARB(),GetLastError() or glGetError().I guess I just have to remember that.

Hmmmm the tutorial didn’t use wglMakeContextCurrentARB(). It uses wglMakeCurrent(). I guess that was the problem. Yes the tutorial example uses same pixelformat and pbuffer attribs.

Anyway, now it works.

Thanks for digging into the power of two restriction mysticism. I’ll stick to 512x512 for now…

Thanks for the help roffe