mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
support multisample on windows
This commit is contained in:
parent
db232215f8
commit
415c129bb6
@ -17,6 +17,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wglGraphicsBuffer.h"
|
||||
#include "wglGraphicsPipe.h"
|
||||
#include "config_wgldisplay.h"
|
||||
#include "glgsg.h"
|
||||
#include "pStatTimer.h"
|
||||
@ -24,8 +25,6 @@
|
||||
#include <wingdi.h>
|
||||
|
||||
TypeHandle wglGraphicsBuffer::_type_handle;
|
||||
const char * const wglGraphicsBuffer::_window_class_name = "wglGraphicsBuffer";
|
||||
bool wglGraphicsBuffer::_window_class_registered = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::Constructor
|
||||
@ -38,8 +37,6 @@ wglGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
||||
int x_size, int y_size, bool want_texture) :
|
||||
GraphicsBuffer(pipe, gsg, name, x_size, y_size, want_texture)
|
||||
{
|
||||
_window = (HWND)0;
|
||||
_window_dc = (HDC)0;
|
||||
_pbuffer = (HPBUFFERARB)0;
|
||||
_pbuffer_dc = (HDC)0;
|
||||
|
||||
@ -196,15 +193,6 @@ process_events() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsBuffer::
|
||||
close_buffer() {
|
||||
if (_window_dc) {
|
||||
ReleaseDC(_window, _window_dc);
|
||||
_window_dc = 0;
|
||||
}
|
||||
if (_window) {
|
||||
DestroyWindow(_window);
|
||||
_window = 0;
|
||||
}
|
||||
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_V(wglgsg, _gsg);
|
||||
@ -231,15 +219,16 @@ close_buffer() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsBuffer::
|
||||
open_buffer() {
|
||||
if (!make_window()) {
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_R(wglgsg, _gsg, false);
|
||||
|
||||
HDC twindow_dc = wglgsg->get_twindow_dc();
|
||||
if (twindow_dc == 0) {
|
||||
// If we couldn't make a window, we can't get a GL context.
|
||||
return false;
|
||||
}
|
||||
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_R(wglgsg, _gsg, false);
|
||||
|
||||
wglMakeCurrent(_window_dc, wglgsg->get_context(_window_dc));
|
||||
wglMakeCurrent(twindow_dc, wglgsg->get_context(twindow_dc));
|
||||
wglgsg->reset_if_new();
|
||||
_needs_context = false;
|
||||
|
||||
@ -247,88 +236,25 @@ open_buffer() {
|
||||
// create a rendering context, we can attempt to create a pbuffer.
|
||||
// This might fail if the pbuffer extensions are not supported.
|
||||
|
||||
if (!make_pbuffer()) {
|
||||
if (!make_pbuffer(twindow_dc)) {
|
||||
wglMakeCurrent(0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
_pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
|
||||
wgldisplay_cat.info()
|
||||
<< "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n";
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n";
|
||||
}
|
||||
|
||||
wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc));
|
||||
wglgsg->report_my_gl_errors();
|
||||
|
||||
// Now that the pbuffer is created, we don't need the window any
|
||||
// more.
|
||||
if (_window_dc) {
|
||||
ReleaseDC(_window, _window_dc);
|
||||
_window_dc = 0;
|
||||
}
|
||||
if (_window) {
|
||||
DestroyWindow(_window);
|
||||
_window = 0;
|
||||
}
|
||||
|
||||
_is_valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::make_window
|
||||
// Access: Private
|
||||
// Description: Creates an invisible window to associate with the GL
|
||||
// context, even if we are not going to use it. This is
|
||||
// necessary because in the Windows OpenGL API, we have
|
||||
// to create window before we can create a GL
|
||||
// context--even before we can ask about what GL
|
||||
// extensions are available!
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsBuffer::
|
||||
make_window() {
|
||||
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);
|
||||
|
||||
// compute window size based on desired client area size
|
||||
if (!AdjustWindowRect(&win_rect, window_style, FALSE)) {
|
||||
wgldisplay_cat.error()
|
||||
<< "AdjustWindowRect failed!" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
register_window_class();
|
||||
HINSTANCE hinstance = GetModuleHandle(NULL);
|
||||
_window = CreateWindow(_window_class_name, "buffer", window_style,
|
||||
win_rect.left, win_rect.top,
|
||||
win_rect.right - win_rect.left,
|
||||
win_rect.bottom - win_rect.top,
|
||||
NULL, NULL, hinstance, 0);
|
||||
|
||||
if (!_window) {
|
||||
wgldisplay_cat.error()
|
||||
<< "CreateWindow() failed!" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(_window, SW_HIDE);
|
||||
|
||||
_window_dc = GetDC(_window);
|
||||
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_R(wglgsg, _gsg, false);
|
||||
int pfnum = wglgsg->get_pfnum();
|
||||
PIXELFORMATDESCRIPTOR pixelformat;
|
||||
if (!SetPixelFormat(_window_dc, pfnum, &pixelformat)) {
|
||||
wgldisplay_cat.error()
|
||||
<< "SetPixelFormat(" << pfnum << ") failed after window create\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::make_pbuffer
|
||||
// Access: Private
|
||||
@ -338,7 +264,7 @@ make_window() {
|
||||
// failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsBuffer::
|
||||
make_pbuffer() {
|
||||
make_pbuffer(HDC twindow_dc) {
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_R(wglgsg, _gsg, false);
|
||||
|
||||
@ -353,18 +279,47 @@ make_pbuffer() {
|
||||
if (wglgsg->_supports_pixel_format) {
|
||||
// Select a suitable pixel format that matches the GSG's existing
|
||||
// format, and also is appropriate for a pixel buffer.
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
|
||||
DescribePixelFormat(_window_dc, wglgsg->get_pfnum(),
|
||||
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
|
||||
|
||||
static const int max_attrib_list = 32;
|
||||
int iattrib_list[max_attrib_list];
|
||||
float fattrib_list[max_attrib_list];
|
||||
int ivalue_list[max_attrib_list];
|
||||
int ni = 0;
|
||||
|
||||
int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
|
||||
red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i,
|
||||
accum_red_bits_i, accum_green_bits_i, accum_blue_bits_i,
|
||||
accum_alpha_bits_i, depth_bits_i,
|
||||
stencil_bits_i, multisample_bits_i;
|
||||
|
||||
iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
|
||||
iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
|
||||
iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
|
||||
iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB;
|
||||
iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB;
|
||||
iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB;
|
||||
iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
|
||||
iattrib_list[accum_red_bits_i = ni++] = WGL_ACCUM_RED_BITS_ARB;
|
||||
iattrib_list[accum_green_bits_i = ni++] = WGL_ACCUM_GREEN_BITS_ARB;
|
||||
iattrib_list[accum_blue_bits_i = ni++] = WGL_ACCUM_BLUE_BITS_ARB;
|
||||
iattrib_list[accum_alpha_bits_i = ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
|
||||
iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
|
||||
iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
|
||||
|
||||
if (wglgsg->_supports_wgl_multisample) {
|
||||
iattrib_list[multisample_bits_i = ni++] = WGL_SAMPLES_ARB;
|
||||
}
|
||||
|
||||
// Terminate the list.
|
||||
nassertr(ni <= max_attrib_list, false);
|
||||
|
||||
if (!wglgsg->_wglGetPixelFormatAttribivARB(twindow_dc, pbformat, 0,
|
||||
ni, iattrib_list, ivalue_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ni = 0;
|
||||
float fattrib_list[max_attrib_list];
|
||||
int nf = 0;
|
||||
|
||||
// Since we are trying to create a pbuffer, the pixel format we
|
||||
@ -376,25 +331,39 @@ make_pbuffer() {
|
||||
|
||||
// Match up the framebuffer bits.
|
||||
iattrib_list[ni++] = WGL_RED_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cRedBits;
|
||||
iattrib_list[ni++] = ivalue_list[red_bits_i];
|
||||
iattrib_list[ni++] = WGL_GREEN_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cGreenBits;
|
||||
iattrib_list[ni++] = ivalue_list[green_bits_i];
|
||||
iattrib_list[ni++] = WGL_BLUE_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cBlueBits;
|
||||
iattrib_list[ni++] = ivalue_list[blue_bits_i];
|
||||
iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cAlphaBits;
|
||||
iattrib_list[ni++] = ivalue_list[alpha_bits_i];
|
||||
|
||||
iattrib_list[ni++] = WGL_ACCUM_RED_BITS_ARB;
|
||||
iattrib_list[ni++] = ivalue_list[accum_red_bits_i];
|
||||
iattrib_list[ni++] = WGL_ACCUM_GREEN_BITS_ARB;
|
||||
iattrib_list[ni++] = ivalue_list[accum_green_bits_i];
|
||||
iattrib_list[ni++] = WGL_ACCUM_BLUE_BITS_ARB;
|
||||
iattrib_list[ni++] = ivalue_list[accum_blue_bits_i];
|
||||
iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
|
||||
iattrib_list[ni++] = ivalue_list[accum_alpha_bits_i];
|
||||
|
||||
iattrib_list[ni++] = WGL_DEPTH_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cDepthBits;
|
||||
iattrib_list[ni++] = ivalue_list[depth_bits_i];
|
||||
|
||||
iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
|
||||
iattrib_list[ni++] = pfd.cStencilBits;
|
||||
iattrib_list[ni++] = ivalue_list[stencil_bits_i];
|
||||
|
||||
if (wglgsg->_supports_wgl_multisample) {
|
||||
iattrib_list[ni++] = WGL_SAMPLES_ARB;
|
||||
iattrib_list[ni++] = ivalue_list[multisample_bits_i];
|
||||
}
|
||||
|
||||
// Match up properties.
|
||||
iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
iattrib_list[ni++] = ((pfd.dwFlags & PFD_DOUBLEBUFFER) != 0);
|
||||
iattrib_list[ni++] = ivalue_list[double_buffer_i];
|
||||
iattrib_list[ni++] = WGL_STEREO_ARB;
|
||||
iattrib_list[ni++] = ((pfd.dwFlags & PFD_STEREO) != 0);
|
||||
iattrib_list[ni++] = ivalue_list[stereo_i];
|
||||
|
||||
// Terminate the lists.
|
||||
nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL);
|
||||
@ -403,17 +372,19 @@ make_pbuffer() {
|
||||
|
||||
// Now obtain a list of pixel formats that meet these minimum
|
||||
// requirements.
|
||||
static const int max_pformats = 32;
|
||||
static const unsigned int max_pformats = 32;
|
||||
int pformat[max_pformats];
|
||||
memset(pformat, 0, sizeof(pformat));
|
||||
unsigned int nformats = 0;
|
||||
if (!wglgsg->_wglChoosePixelFormatARB(_window_dc, iattrib_list, fattrib_list,
|
||||
if (!wglgsg->_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list,
|
||||
max_pformats, pformat, &nformats)) {
|
||||
wgldisplay_cat.info()
|
||||
<< "Couldn't find a suitable pixel format for creating a pbuffer.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
nformats = min(nformats, max_pformats);
|
||||
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Found " << nformats << " pbuffer formats: [";
|
||||
@ -425,16 +396,32 @@ make_pbuffer() {
|
||||
<< " ]\n";
|
||||
}
|
||||
|
||||
pbformat = pformat[0];
|
||||
// If one of the options is the original pixfmt, keep it.
|
||||
bool found_pbformat = false;
|
||||
for (unsigned int i = 0; i < nformats && !found_pbformat; i++) {
|
||||
if (pformat[i] == pbformat) {
|
||||
found_pbformat = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_pbformat) {
|
||||
// Otherwise, pick any of them.
|
||||
pbformat = pformat[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Chose pixfmt #" << pbformat << " for pbuffer\n";
|
||||
}
|
||||
|
||||
int attrib_list[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
_pbuffer = wglgsg->_wglCreatePbufferARB(_window_dc, pbformat,
|
||||
_pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pbformat,
|
||||
_x_size, _y_size, attrib_list);
|
||||
|
||||
|
||||
if (_pbuffer == 0) {
|
||||
wgldisplay_cat.info()
|
||||
<< "Attempt to create pbuffer failed.\n";
|
||||
@ -464,48 +451,5 @@ process_1_event() {
|
||||
// Call window_proc
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::register_window_class
|
||||
// Access: Private, Static
|
||||
// Description: Registers a Window class for all wglGraphicsBuffers.
|
||||
// This only needs to be done once per session.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsBuffer::
|
||||
register_window_class() {
|
||||
if (_window_class_registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
WNDCLASS wc;
|
||||
|
||||
HINSTANCE instance = GetModuleHandle(NULL);
|
||||
|
||||
// Clear before filling in window structure!
|
||||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.lpfnWndProc = static_window_proc;
|
||||
wc.hInstance = instance;
|
||||
wc.lpszClassName = _window_class_name;
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
wgldisplay_cat.error()
|
||||
<< "could not register window class!" << endl;
|
||||
return;
|
||||
}
|
||||
_window_class_registered = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::static_window_proc
|
||||
// Access: Private, Static
|
||||
// Description: This is attached to the window class for all
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,22 +59,13 @@ protected:
|
||||
virtual bool open_buffer();
|
||||
|
||||
private:
|
||||
bool make_window();
|
||||
bool make_pbuffer();
|
||||
bool make_pbuffer(HDC window_dc);
|
||||
|
||||
static void process_1_event();
|
||||
|
||||
static void register_window_class();
|
||||
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
HWND _window;
|
||||
HDC _window_dc;
|
||||
HPBUFFERARB _pbuffer;
|
||||
HDC _pbuffer_dc;
|
||||
|
||||
static const char * const _window_class_name;
|
||||
static bool _window_class_registered;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -15,3 +15,4 @@
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "wglGraphicsBuffer.h"
|
||||
|
||||
typedef enum {Software, MCD, ICD} OGLDriverType;
|
||||
static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
|
||||
|
||||
TypeHandle wglGraphicsPipe::_type_handle;
|
||||
|
||||
@ -100,30 +99,83 @@ make_gsg(const FrameBufferProperties &properties,
|
||||
DCAST_INTO_R(share_gsg, share_with, NULL);
|
||||
}
|
||||
|
||||
int frame_buffer_mode = 0;
|
||||
if (properties.has_frame_buffer_mode()) {
|
||||
frame_buffer_mode = properties.get_frame_buffer_mode();
|
||||
}
|
||||
|
||||
// We need a DC to examine the available pixel formats. We'll use
|
||||
// the screen DC.
|
||||
HDC hdc = GetDC(NULL);
|
||||
int pfnum = choose_pfnum(properties, hdc);
|
||||
int temp_pfnum;
|
||||
|
||||
if (gl_force_pixfmt != 0) {
|
||||
if (!gl_force_pixfmt.has_value()) {
|
||||
temp_pfnum = choose_pfnum(properties, hdc);
|
||||
|
||||
} else {
|
||||
wgldisplay_cat.info()
|
||||
<< "overriding pixfmt choice algorithm (" << pfnum
|
||||
<< ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n";
|
||||
pfnum = gl_force_pixfmt;
|
||||
<< "overriding pixfmt choice with gl-force-pixfmt("
|
||||
<< gl_force_pixfmt << ")\n";
|
||||
temp_pfnum = gl_force_pixfmt;
|
||||
}
|
||||
|
||||
FrameBufferProperties new_properties;
|
||||
get_properties(new_properties, hdc, pfnum);
|
||||
FrameBufferProperties temp_properties;
|
||||
get_properties(temp_properties, hdc, temp_pfnum);
|
||||
|
||||
// We're done with hdc now.
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Preliminary pixfmt #" << temp_pfnum << " = "
|
||||
<< temp_properties << "\n";
|
||||
}
|
||||
|
||||
// Now we need to create a temporary GSG to query the WGL
|
||||
// extensions, so we can look for more advanced properties like
|
||||
// multisampling.
|
||||
PT(wglGraphicsStateGuardian) temp_gsg =
|
||||
new wglGraphicsStateGuardian(temp_properties, share_gsg, temp_pfnum);
|
||||
|
||||
int pfnum = temp_pfnum;
|
||||
FrameBufferProperties new_properties = temp_properties;
|
||||
|
||||
// Actually, don't bother with the advanced stuff unless the
|
||||
// requested frame buffer requires multisample, since at the moment
|
||||
// that's the only reason we'd need to use the advanced query.
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_multisample) {
|
||||
HDC twindow_dc = temp_gsg->get_twindow_dc();
|
||||
if (twindow_dc != 0) {
|
||||
wglMakeCurrent(twindow_dc, temp_gsg->get_context(twindow_dc));
|
||||
temp_gsg->reset_if_new();
|
||||
|
||||
if (temp_gsg->_supports_pixel_format) {
|
||||
pfnum = choose_pfnum_advanced(properties, temp_gsg, twindow_dc,
|
||||
temp_pfnum);
|
||||
if (!get_properties_advanced(new_properties, temp_gsg, twindow_dc,
|
||||
pfnum)) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Unable to query properties using extension interface.\n";
|
||||
|
||||
get_properties(new_properties, twindow_dc, pfnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Picking pixfmt #" << pfnum << " = "
|
||||
<< new_properties << "\n";
|
||||
}
|
||||
|
||||
PT(wglGraphicsStateGuardian) gsg =
|
||||
new wglGraphicsStateGuardian(new_properties, share_gsg, pfnum);
|
||||
// Now create the actual GSG. If we happen to have ended up with
|
||||
// the same pfnum that we had the first time around, we can just
|
||||
// keep our initial, temporary GSG.
|
||||
PT(wglGraphicsStateGuardian) gsg = temp_gsg;
|
||||
if (pfnum != temp_pfnum) {
|
||||
gsg = new wglGraphicsStateGuardian(new_properties, share_gsg, pfnum);
|
||||
}
|
||||
|
||||
// Ideally, we should be able to detect whether the share_gsg will
|
||||
// be successful, and return NULL if it won't work. But we can't do
|
||||
@ -220,6 +272,134 @@ choose_pfnum(const FrameBufferProperties &properties, HDC hdc) {
|
||||
return pfnum;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsPipe::choose_pfnum_advanced
|
||||
// Access: Private, Static
|
||||
// Description: Uses the WGL extensions, if available, to find a
|
||||
// suitable pfnum. This requires having created a
|
||||
// temporary context first.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int wglGraphicsPipe::
|
||||
choose_pfnum_advanced(const FrameBufferProperties &properties,
|
||||
const wglGraphicsStateGuardian *wglgsg,
|
||||
HDC window_dc, int orig_pfnum) {
|
||||
int frame_buffer_mode = 0;
|
||||
|
||||
if (properties.has_frame_buffer_mode()) {
|
||||
frame_buffer_mode = properties.get_frame_buffer_mode();
|
||||
}
|
||||
|
||||
int want_depth_bits = properties.get_depth_bits();
|
||||
int want_color_bits = properties.get_color_bits();
|
||||
int want_alpha_bits = properties.get_alpha_bits();
|
||||
int want_stencil_bits = properties.get_stencil_bits();
|
||||
int want_multisample_bits = properties.get_multisample_bits();
|
||||
|
||||
static const int max_attrib_list = 32;
|
||||
int iattrib_list[max_attrib_list];
|
||||
float fattrib_list[max_attrib_list];
|
||||
int ni = 0;
|
||||
int nf = 0;
|
||||
|
||||
iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
|
||||
iattrib_list[ni++] = true;
|
||||
iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB;
|
||||
iattrib_list[ni++] = WGL_TYPE_RGBA_ARB;
|
||||
iattrib_list[ni++] = WGL_COLOR_BITS_ARB;
|
||||
iattrib_list[ni++] = want_color_bits;
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_alpha) {
|
||||
iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
|
||||
iattrib_list[ni++] = want_alpha_bits;
|
||||
}
|
||||
|
||||
switch (frame_buffer_mode & FrameBufferProperties::FM_buffer) {
|
||||
case FrameBufferProperties::FM_single_buffer:
|
||||
iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
iattrib_list[ni++] = false;
|
||||
break;
|
||||
|
||||
case FrameBufferProperties::FM_double_buffer:
|
||||
case FrameBufferProperties::FM_triple_buffer:
|
||||
iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
iattrib_list[ni++] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_stereo) {
|
||||
iattrib_list[ni++] = WGL_STEREO_ARB;
|
||||
iattrib_list[ni++] = true;
|
||||
} else {
|
||||
iattrib_list[ni++] = WGL_STEREO_ARB;
|
||||
iattrib_list[ni++] = false;
|
||||
}
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_depth) {
|
||||
iattrib_list[ni++] = WGL_DEPTH_BITS_ARB;
|
||||
iattrib_list[ni++] = want_depth_bits;
|
||||
}
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_stencil) {
|
||||
iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
|
||||
iattrib_list[ni++] = want_stencil_bits;
|
||||
}
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_accum) {
|
||||
iattrib_list[ni++] = WGL_ACCUM_BITS_ARB;
|
||||
iattrib_list[ni++] = want_color_bits;
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_alpha) {
|
||||
iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
|
||||
iattrib_list[ni++] = want_alpha_bits;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame_buffer_mode & FrameBufferProperties::FM_multisample) {
|
||||
iattrib_list[ni++] = WGL_SAMPLES_ARB;
|
||||
iattrib_list[ni++] = want_multisample_bits;
|
||||
}
|
||||
|
||||
// Terminate the lists.
|
||||
nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL);
|
||||
iattrib_list[ni] = 0;
|
||||
fattrib_list[nf] = 0;
|
||||
|
||||
// Now obtain a list of pixel formats that meet these minimum
|
||||
// requirements.
|
||||
static const unsigned int max_pformats = 32;
|
||||
int pformat[max_pformats];
|
||||
memset(pformat, 0, sizeof(pformat));
|
||||
unsigned int nformats = 0;
|
||||
if (!wglgsg->_wglChoosePixelFormatARB(window_dc, iattrib_list, fattrib_list,
|
||||
max_pformats, pformat, &nformats)) {
|
||||
wgldisplay_cat.info()
|
||||
<< "Couldn't find a suitable advanced pixel format.\n";
|
||||
return orig_pfnum;
|
||||
}
|
||||
|
||||
nformats = min(nformats, max_pformats);
|
||||
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Found " << nformats << " advanced formats: [";
|
||||
for (unsigned int i = 0; i < nformats; i++) {
|
||||
wgldisplay_cat.debug(false)
|
||||
<< " " << pformat[i];
|
||||
}
|
||||
wgldisplay_cat.debug(false)
|
||||
<< " ]\n";
|
||||
}
|
||||
|
||||
// If our original pfnum is on the list, take it.
|
||||
for (unsigned int i = 0; i < nformats; i++) {
|
||||
if (pformat[i] == orig_pfnum) {
|
||||
return orig_pfnum;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, return the first available.
|
||||
return pformat[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsPipe::find_pixfmtnum
|
||||
// Access: Private, Static
|
||||
@ -448,6 +628,93 @@ get_properties(FrameBufferProperties &properties, HDC hdc,
|
||||
properties.set_frame_buffer_mode(mode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsPipe::get_properties_advanced
|
||||
// Access: Private, Static
|
||||
// Description: Gets the FrameBufferProperties to match the
|
||||
// indicated pixel format descriptor, using the WGL
|
||||
// extensions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsPipe::
|
||||
get_properties_advanced(FrameBufferProperties &properties,
|
||||
wglGraphicsStateGuardian *wglgsg,
|
||||
HDC window_dc, int pfnum) {
|
||||
|
||||
static const int max_attrib_list = 32;
|
||||
int iattrib_list[max_attrib_list];
|
||||
int ivalue_list[max_attrib_list];
|
||||
int ni = 0;
|
||||
|
||||
int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
|
||||
color_bits_i, alpha_bits_i, accum_bits_i, depth_bits_i,
|
||||
stencil_bits_i, multisample_bits_i;
|
||||
|
||||
iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
|
||||
iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
|
||||
iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
|
||||
iattrib_list[color_bits_i = ni++] = WGL_COLOR_BITS_ARB;
|
||||
iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
|
||||
iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB;
|
||||
iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
|
||||
iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
|
||||
|
||||
if (wglgsg->_supports_wgl_multisample) {
|
||||
iattrib_list[multisample_bits_i = ni++] = WGL_SAMPLES_ARB;
|
||||
}
|
||||
|
||||
// Terminate the list.
|
||||
nassertr(ni <= max_attrib_list, false);
|
||||
|
||||
if (!wglgsg->_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0,
|
||||
ni, iattrib_list, ivalue_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int frame_buffer_mode = 0;
|
||||
if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_software;
|
||||
} else {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_hardware;
|
||||
}
|
||||
|
||||
if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_index;
|
||||
}
|
||||
if (ivalue_list[double_buffer_i]) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
|
||||
}
|
||||
if (ivalue_list[stereo_i]) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_stereo;
|
||||
}
|
||||
if (ivalue_list[alpha_bits_i] != 0) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_alpha;
|
||||
properties.set_alpha_bits(ivalue_list[alpha_bits_i]);
|
||||
}
|
||||
if (ivalue_list[accum_bits_i] != 0) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_accum;
|
||||
}
|
||||
if (ivalue_list[depth_bits_i] != 0) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_depth;
|
||||
properties.set_depth_bits(ivalue_list[depth_bits_i]);
|
||||
}
|
||||
if (ivalue_list[stencil_bits_i] != 0) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_stencil;
|
||||
properties.set_stencil_bits(ivalue_list[stencil_bits_i]);
|
||||
}
|
||||
if (wglgsg->_supports_wgl_multisample) {
|
||||
if (ivalue_list[multisample_bits_i] != 0) {
|
||||
frame_buffer_mode |= FrameBufferProperties::FM_multisample;
|
||||
properties.set_multisample_bits(ivalue_list[multisample_bits_i]);
|
||||
}
|
||||
}
|
||||
|
||||
properties.set_frame_buffer_mode(frame_buffer_mode);
|
||||
properties.set_color_bits(ivalue_list[color_bits_i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsPipe::format_pfd_flags
|
||||
// Access: Private, Static
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "pandabase.h"
|
||||
#include "winGraphicsPipe.h"
|
||||
|
||||
class wglGraphicsStateGuardian;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : wglGraphicsPipe
|
||||
// Description : This graphics pipe represents the interface for
|
||||
@ -46,10 +48,16 @@ protected:
|
||||
int x_size, int y_size, bool want_texture);
|
||||
private:
|
||||
static int choose_pfnum(const FrameBufferProperties &properties, HDC hdc);
|
||||
static int choose_pfnum_advanced(const FrameBufferProperties &properties,
|
||||
const wglGraphicsStateGuardian *wglgsg,
|
||||
HDC window_dc, int orig_pfnum);
|
||||
static int find_pixfmtnum(const FrameBufferProperties &properties, HDC hdc,
|
||||
bool bLookforHW);
|
||||
static void get_properties(FrameBufferProperties &properties, HDC hdc,
|
||||
int pfnum);
|
||||
static bool get_properties_advanced(FrameBufferProperties &properties,
|
||||
wglGraphicsStateGuardian *wglgsg,
|
||||
HDC window_dc, int pfnum);
|
||||
static string format_pfd_flags(DWORD pfd_flags);
|
||||
|
||||
public:
|
||||
|
@ -61,3 +61,19 @@ get_context(HDC hdc) {
|
||||
}
|
||||
return _context;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::get_twindow_dc
|
||||
// Access: Public
|
||||
// Description: Returns the DC associated with the temporary,
|
||||
// invisible window that was created with the gsg to
|
||||
// query WGL extensions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE HDC wglGraphicsStateGuardian::
|
||||
get_twindow_dc() {
|
||||
if (_twindow_dc == 0) {
|
||||
make_twindow();
|
||||
}
|
||||
return _twindow_dc;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
TypeHandle wglGraphicsStateGuardian::_type_handle;
|
||||
|
||||
const char * const wglGraphicsStateGuardian::_twindow_class_name = "wglGraphicsStateGuardian";
|
||||
bool wglGraphicsStateGuardian::_twindow_class_registered = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::Constructor
|
||||
// Access: Public
|
||||
@ -37,8 +40,12 @@ wglGraphicsStateGuardian(const FrameBufferProperties &properties,
|
||||
_made_context = false;
|
||||
_context = (HGLRC)NULL;
|
||||
|
||||
_twindow = (HWND)0;
|
||||
_twindow_dc = (HDC)0;
|
||||
|
||||
_supports_pbuffer = false;
|
||||
_supports_pixel_format = false;
|
||||
_supports_wgl_multisample = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -48,6 +55,7 @@ wglGraphicsStateGuardian(const FrameBufferProperties &properties,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
wglGraphicsStateGuardian::
|
||||
~wglGraphicsStateGuardian() {
|
||||
release_twindow();
|
||||
if (_context != (HGLRC)NULL) {
|
||||
wglDeleteContext(_context);
|
||||
_context = (HGLRC)NULL;
|
||||
@ -66,6 +74,7 @@ reset() {
|
||||
|
||||
_supports_pbuffer = has_extension("WGL_ARB_pbuffer");
|
||||
_supports_pixel_format = has_extension("WGL_ARB_pixel_format");
|
||||
_supports_wgl_multisample = has_extension("WGL_ARB_multisample");
|
||||
|
||||
_wglCreatePbufferARB =
|
||||
(PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
|
||||
@ -250,3 +259,96 @@ redirect_share_pool(wglGraphicsStateGuardian *share_with) {
|
||||
_share_with = share_with;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::make_twindow
|
||||
// Access: Private
|
||||
// Description: Creates an invisible window to associate with the GL
|
||||
// context, even if we are not going to use it. This is
|
||||
// necessary because in the Windows OpenGL API, we have
|
||||
// to create window before we can create a GL
|
||||
// context--even before we can ask about what GL
|
||||
// extensions are available!
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsStateGuardian::
|
||||
make_twindow() {
|
||||
release_twindow();
|
||||
|
||||
DWORD window_style = 0;
|
||||
|
||||
register_twindow_class();
|
||||
HINSTANCE hinstance = GetModuleHandle(NULL);
|
||||
_twindow = CreateWindow(_twindow_class_name, "twindow", window_style,
|
||||
0, 0, 1, 1, NULL, NULL, hinstance, 0);
|
||||
|
||||
if (!_twindow) {
|
||||
wgldisplay_cat.error()
|
||||
<< "CreateWindow() failed!" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(_twindow, SW_HIDE);
|
||||
|
||||
_twindow_dc = GetDC(_twindow);
|
||||
|
||||
PIXELFORMATDESCRIPTOR pixelformat;
|
||||
if (!SetPixelFormat(_twindow_dc, _pfnum, &pixelformat)) {
|
||||
wgldisplay_cat.error()
|
||||
<< "SetPixelFormat(" << _pfnum << ") failed after window create\n";
|
||||
release_twindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::release_twindow
|
||||
// Access: Private
|
||||
// Description: Closes and frees the resources associated with the
|
||||
// temporary window created by a previous call to
|
||||
// make_twindow().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsStateGuardian::
|
||||
release_twindow() {
|
||||
if (_twindow_dc) {
|
||||
ReleaseDC(_twindow, _twindow_dc);
|
||||
_twindow_dc = 0;
|
||||
}
|
||||
if (_twindow) {
|
||||
DestroyWindow(_twindow);
|
||||
_twindow = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::register_twindow_class
|
||||
// Access: Private, Static
|
||||
// Description: Registers a Window class for the twindow created by
|
||||
// all wglGraphicsPipes. This only needs to be done
|
||||
// once per session.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsStateGuardian::
|
||||
register_twindow_class() {
|
||||
if (_twindow_class_registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
WNDCLASS wc;
|
||||
|
||||
HINSTANCE instance = GetModuleHandle(NULL);
|
||||
|
||||
// Clear before filling in window structure!
|
||||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.hInstance = instance;
|
||||
wc.lpszClassName = _twindow_class_name;
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
wgldisplay_cat.error()
|
||||
<< "could not register window class!" << endl;
|
||||
return;
|
||||
}
|
||||
_twindow_class_registered = true;
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
|
||||
virtual void reset();
|
||||
|
||||
INLINE HDC get_twindow_dc();
|
||||
|
||||
protected:
|
||||
virtual void get_extra_extensions();
|
||||
virtual void *get_extension_func(const char *prefix, const char *name);
|
||||
@ -54,6 +56,11 @@ private:
|
||||
HGLRC get_share_context() const;
|
||||
void redirect_share_pool(wglGraphicsStateGuardian *share_with);
|
||||
|
||||
bool make_twindow();
|
||||
void release_twindow();
|
||||
|
||||
static void register_twindow_class();
|
||||
|
||||
// We have to save a pointer to the GSG we intend to share texture
|
||||
// context with, since we don't create our own context in the
|
||||
// constructor.
|
||||
@ -67,6 +74,12 @@ private:
|
||||
bool _made_context;
|
||||
HGLRC _context;
|
||||
|
||||
HWND _twindow;
|
||||
HDC _twindow_dc;
|
||||
|
||||
static const char * const _twindow_class_name;
|
||||
static bool _twindow_class_registered;
|
||||
|
||||
public:
|
||||
bool _supports_pbuffer;
|
||||
|
||||
@ -82,6 +95,8 @@ public:
|
||||
PFNWGLGETPIXELFORMATATTRIBFVARBPROC _wglGetPixelFormatAttribfvARB;
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC _wglChoosePixelFormatARB;
|
||||
|
||||
bool _supports_wgl_multisample;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
Loading…
x
Reference in New Issue
Block a user