add show-pbuffers

This commit is contained in:
David Rose 2004-02-13 00:55:48 +00:00
parent 141852abeb
commit bbbe8cbf9f
4 changed files with 150 additions and 8 deletions

View File

@ -67,3 +67,9 @@ bool gl_force_invalid = config_wgldisplay.GetBool("gl-force-invalid", false);
// requested. It only affects fullscreen windows.
bool gl_do_vidmemsize_check = config_wgldisplay.GetBool("gl-do-vidmemsize-check", true);
// For now, we fake offscreen rendering without using the
// poorly-supported pbuffer extension; we simply render into an
// invisible window. Some drivers don't like that, so for these
// drivers set show-pbuffers to true to force the window to be visible
// so you can at least get some work done.
bool show_pbuffers = config_wgldisplay.GetBool("show-pbuffers", false);

View File

@ -29,5 +29,6 @@ extern EXPCL_PANDAGL void init_libwgldisplay();
extern int gl_force_pixfmt;
extern bool gl_force_invalid;
extern bool gl_do_vidmemsize_check;
extern bool show_pbuffers;
#endif

View File

@ -103,20 +103,45 @@ void wglGraphicsBuffer::
begin_flip() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
make_current();
glFinish();
if (has_texture()) {
// Use glCopyTexImage2D to copy the framebuffer to the texture.
// This appears to be the only way to "render to a texture" in
// OpenGL; there's no interface to make the offscreen buffer
// itself be a texture.
DisplayRegion dr(_x_size, _y_size);
get_texture()->copy(_gsg, &dr, _gsg->get_render_buffer(RenderBuffer::T_back));
PT(DisplayRegion) dr = make_scratch_display_region(_x_size, _y_size);
get_texture()->copy(_gsg, dr, _gsg->get_render_buffer(RenderBuffer::T_back));
}
SwapBuffers(_window_dc);
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsBuffer::process_events
// Access: Public, Virtual
// Description: Do whatever processing is necessary to ensure that
// the window responds to user events. Also, honor any
// requests recently made via request_properties()
//
// This function is called only within the window
// thread.
////////////////////////////////////////////////////////////////////
void wglGraphicsBuffer::
process_events() {
GraphicsBuffer::process_events();
MSG msg;
// Handle all the messages on the queue in a row. Some of these
// might be for another window, but they will get dispatched
// appropriately.
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
process_1_event();
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsBuffer::close_buffer
// Access: Protected, Virtual
@ -150,13 +175,14 @@ open_buffer() {
// only are wgl extensions incredibly convoluted to get to, but the
// pbuffer extension turned out not be supported on the Intel card I
// tried it on, and crashed the driver for the nVidia card I tried
// it on. And it's not even supported on the software reference
// implementation. Not a good record.
// it on. And it's not even supported on the Microsoft software
// reference implementation. Not a good record.
// In lieu of the pbuffer extension, it appears that rendering to a
// window that is simply never shown works fine.
// window that is hidden works fine on some drivers (although it
// doesn't work on other drivers).
DWORD window_style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
DWORD window_style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW;
RECT win_rect;
SetRect(&win_rect, 0, 0, _x_size, _y_size);
@ -182,6 +208,11 @@ open_buffer() {
return false;
}
ShowWindow(_window, SW_SHOWNORMAL);
if (!show_pbuffers) {
ShowWindow(_window, SW_HIDE);
}
_window_dc = GetDC(_window);
wglGraphicsStateGuardian *wglgsg;
@ -195,8 +226,30 @@ open_buffer() {
}
_is_valid = true;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsBuffer::process_1_event
// Access: Private, Static
// Description: Handles one event from the message queue.
////////////////////////////////////////////////////////////////////
void wglGraphicsBuffer::
process_1_event() {
MSG msg;
if (!GetMessage(&msg, NULL, 0, 0)) {
// WM_QUIT received. We need a cleaner way to deal with this.
// DestroyAllWindows(false);
exit(msg.wParam); // this will invoke AtExitFn
}
// Translate virtual key messages
TranslateMessage(&msg);
// Call window_proc
DispatchMessage(&msg);
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsBuffer::register_window_class
@ -217,7 +270,7 @@ register_window_class() {
// Clear before filling in window structure!
ZeroMemory(&wc, sizeof(WNDCLASS));
wc.style = CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.lpfnWndProc = static_window_proc;
wc.hInstance = instance;
wc.lpszClassName = _window_class_name;
@ -233,10 +286,89 @@ register_window_class() {
// Function: wglGraphicsBuffer::static_window_proc
// Access: Private, Static
// Description: This is attached to the window class for all
// WinGraphicsWindow windows; it is called to handle
// wglGraphicsBuffer windows; it is called to handle
// window events.
////////////////////////////////////////////////////////////////////
LONG WINAPI wglGraphicsBuffer::
static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
return DefWindowProc(hwnd, msg, wparam, lparam);
}
/*
if (wglgsg->_supports_pixel_format) {
// Get ready to query for a suitable pixel format that meets our
// minimum requirements.
static const int MAX_ATTRIBS = 128;
static const int MAX_PFORMATS = 128;
int iattributes[2*MAX_ATTRIBS];
float fattributes[2*MAX_ATTRIBS];
int nfattribs = 0;
int niattribs = 0;
// Attribute arrays must be "0" terminated--for simplicity, first
// just zero-out the array then fill from left to right.
for ( int a = 0; a < 2*MAX_ATTRIBS; a++ )
{
iattributes[a] = 0;
fattributes[a] = 0;
}
// Since we are trying to create a pbuffer, the pixel format we
// request (and subsequently use) must be "pbuffer capable".
iattributes[2*niattribs ] = WGL_DRAW_TO_PBUFFER_ARB;
iattributes[2*niattribs+1] = true;
niattribs++;
// We require a minimum of 24-bit depth.
iattributes[2*niattribs ] = WGL_DEPTH_BITS_ARB;
iattributes[2*niattribs+1] = 24;
niattribs++;
// We require a minimum of 8-bits for each R, G, B, and A.
iattributes[2*niattribs ] = WGL_RED_BITS_ARB;
iattributes[2*niattribs+1] = 8;
niattribs++;
iattributes[2*niattribs ] = WGL_GREEN_BITS_ARB;
iattributes[2*niattribs+1] = 8;
niattribs++;
iattributes[2*niattribs ] = WGL_BLUE_BITS_ARB;
iattributes[2*niattribs+1] = 8;
niattribs++;
iattributes[2*niattribs ] = WGL_ALPHA_BITS_ARB;
iattributes[2*niattribs+1] = 8;
niattribs++;
// Now obtain a list of pixel formats that meet these minimum
// requirements.
int pformat[MAX_PFORMATS];
memset(pformat, 0, sizeof(pformat));
unsigned int nformats = 0;
if (!wglgsg->_wglChoosePixelFormatARB(_window_dc, iattributes, fattributes,
MAX_PFORMATS, pformat, &nformats)) {
cerr << "pbuffer creation error: Couldn't find a suitable pixel format.\n";
} else {
cerr << "Found " << nformats << " formats, selecting " << pformat[0] << "\n";
pbformat = pformat[0];
}
}
HPBUFFERARB _pbuffer;
wglMakeCurrent(_window_dc, wglgsg->get_context(_window_dc));
wglgsg->reset_if_new();
cerr << "Creating pbuffer(" << _window_dc << ", " << wglgsg->get_pfnum()
<< ", " << _x_size << ", " << _y_size << ", ...)\n";
int attrib_list[] = {
0,
};
HDC hdc = wglGetCurrentDC();
cerr << "current dc = " << hdc << " window dc = " << _window_dc << "\n";
_pbuffer = wglgsg->_wglCreatePbufferARB(hdc, pbformat,
_x_size, _y_size, attrib_list);
cerr << "pbuffer = " << (void *)_pbuffer << "\n";
if (_pbuffer == NULL) {
wgldisplay_cat.error()
<< "Attempt to create pbuffer failed.\n";
}
*/

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "graphicsBuffer.h"
#include "wglExtensions.h"
#include <windows.h>
@ -44,6 +45,7 @@ public:
virtual void release_gsg();
virtual void begin_flip();
virtual void process_events();
protected:
virtual void close_buffer();
@ -51,6 +53,7 @@ protected:
private:
bool make_window();
static void process_1_event();
static void register_window_class();
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);