ソースを参照

Support specifying custom gl-version or requesting debug context on Windows
Also works around NVIDIA driver bug where GL_VERSION is always reported as 1.2 for pview.exe

rdb 10 年 前
コミット
e91a9100ed

+ 52 - 13
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -6835,10 +6835,9 @@ show_gl_string(const string &name, GLenum id) {
   const GLubyte *text = glGetString(id);
 
   if (text == (const GLubyte *)NULL) {
-    if (GLCAT.is_debug()) {
-      GLCAT.debug()
-        << "Unable to query " << name << "\n";
-    }
+    GLCAT.warning()
+      << "Unable to query " << name << "\n";
+
   } else {
     result = (const char *)text;
     if (GLCAT.is_debug()) {
@@ -6859,20 +6858,60 @@ void CLP(GraphicsStateGuardian)::
 query_gl_version() {
   _gl_vendor = show_gl_string("GL_VENDOR", GL_VENDOR);
   _gl_renderer = show_gl_string("GL_RENDERER", GL_RENDERER);
+  _gl_version = show_gl_string("GL_VERSION", GL_VERSION);
 
   _gl_version_major = 0;
   _gl_version_minor = 0;
 
+    // This is the most preposterous driver bug: NVIDIA drivers will claim
+    // that the version is 1.2 as long as the process is named pview.exe!
+#ifndef OPENGLES
+  if (_gl_version.substr(0, 10) == "1.2 NVIDIA") {
+    Filename exec_name = ExecutionEnvironment::get_binary_name();
+    if (cmp_nocase(exec_name.get_basename(), "pview.exe") == 0) {
+      glGetIntegerv(GL_MAJOR_VERSION, &_gl_version_major);
+      glGetIntegerv(GL_MINOR_VERSION, &_gl_version_minor);
 
-  const GLubyte *text = glGetString(GL_VERSION);
-  if (text == (const GLubyte *)NULL) {
-    GLCAT.warning()
-      << "Unable to query GL_VERSION\n";
-  } else {
-    string version((const char *)text);
-    _gl_version = version;
+      if (glGetError() == GL_INVALID_ENUM) {
+        _gl_version_major = 1;
+        _gl_version_minor = 2;
+        GLCAT.warning()
+          << "Driver possibly misreported GL_VERSION!  Unable to detect "
+             "correct OpenGL version.\n";
 
-    string input = version;
+      } else if (_gl_version_major != 1 || _gl_version_minor != 2) {
+        GLCAT.debug()
+          << "Driver misreported GL_VERSION!  Correct version detected as "
+          << _gl_version_major << "." << _gl_version_minor << "\n";
+      }
+      return;
+    }
+  }
+#endif
+
+  // If we asked for a GL 3 context, let's first try and see if we
+  // can use the OpenGL 3 way to query version.
+  if (gl_version.get_num_words() > 0 && gl_version[0] >= 3) {
+    glGetIntegerv(GL_MAJOR_VERSION, &_gl_version_major);
+    glGetIntegerv(GL_MINOR_VERSION, &_gl_version_minor);
+
+    if (_gl_version_major >= 1) {
+      // Fair enough, seems to check out.
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Detected OpenGL version: "
+          << _gl_version_major << "." << _gl_version_minor << "\n";
+      }
+      return;
+    }
+  }
+
+  // Otherwise, parse the GL_VERSION string.
+  if (_gl_version.empty()) {
+    GLCAT.error() << "Unable to detect OpenGL version\n";
+
+  } else {
+    string input = _gl_version;
 
     // Skip any initial words that don't begin with a digit.
     while (!input.empty() && !isdigit(input[0])) {
@@ -6904,7 +6943,7 @@ query_gl_version() {
 
     if (GLCAT.is_debug()) {
       GLCAT.debug()
-        << "GL_VERSION = " << version << ", decoded to "
+        << "GL_VERSION decoded to: "
         << _gl_version_major << "." << _gl_version_minor
         << "\n";
     }

+ 38 - 1
panda/src/wgldisplay/wglGraphicsStateGuardian.cxx

@@ -47,6 +47,8 @@ wglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
   _supports_wgl_multisample = false;
   _supports_wgl_render_texture = false;
 
+  _wglCreateContextAttribsARB = NULL;
+
   get_gamma_table();
   atexit(atexit_function);
 }
@@ -345,6 +347,14 @@ choose_pixel_format(const FrameBufferProperties &properties,
   get_extra_extensions();
   _supports_pixel_format = has_extension("WGL_ARB_pixel_format");
   _supports_wgl_multisample = has_extension("WGL_ARB_multisample");
+
+  if (has_extension("WGL_ARB_create_context")) {
+    _wglCreateContextAttribsARB =
+      (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
+  } else {
+    _wglCreateContextAttribsARB = NULL;
+  }
+
   _extensions.clear();
 
   if (!_supports_pixel_format) {
@@ -614,7 +624,34 @@ make_context(HDC hdc) {
 
   // Attempt to create a context.
   wglGraphicsPipe::_current_valid = false;
-  _context = wglCreateContext(hdc);
+
+  if (_wglCreateContextAttribsARB != NULL) {
+    // We have a fancier version of wglCreateContext that allows us
+    // to specify what kind of OpenGL context we would like.
+    int attrib_list[32];
+    int n = 0;
+    attrib_list[0] = NULL;
+
+    if (gl_version.get_num_words() > 0) {
+      attrib_list[n++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+      attrib_list[n++] = gl_version[0];
+      if (gl_version.get_num_words() > 1) {
+        attrib_list[n++] = WGL_CONTEXT_MINOR_VERSION_ARB;
+        attrib_list[n++] = gl_version[1];
+      }
+    }
+    if (gl_debug) {
+      attrib_list[n++] = WGL_CONTEXT_FLAGS_ARB;
+      attrib_list[n++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+    }
+    attrib_list[n++] = WGL_CONTEXT_PROFILE_MASK_ARB;
+    attrib_list[n++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+    attrib_list[n] = NULL;
+
+    _context = _wglCreateContextAttribsARB(hdc, 0, attrib_list);
+  } else {
+    _context = wglCreateContext(hdc);
+  }
 
   if (_context == NULL) {
     wgldisplay_cat.error()

+ 2 - 0
panda/src/wgldisplay/wglGraphicsStateGuardian.h

@@ -118,6 +118,8 @@ public:
   PFNWGLRELEASETEXIMAGEARBPROC _wglReleaseTexImageARB;
   PFNWGLSETPBUFFERATTRIBARBPROC _wglSetPbufferAttribARB;
 
+  PFNWGLCREATECONTEXTATTRIBSARBPROC _wglCreateContextAttribsARB;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 11 - 1
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -304,8 +304,18 @@ open_window() {
   // Initializes _colormap
   setup_colormap(pixelformat);
 
+  // Make sure we have a context created.
+  HGLRC context = wglgsg->get_context(_hdc);
+  if (!context) {
+    // The context failed to create for some reason.
+    wgldisplay_cat.error()
+      << "Closing window because no valid context is available.\n";
+    close_window();
+    return false;
+  }
+
   // Initialize the gsg.
-  wglGraphicsPipe::wgl_make_current(_hdc, wglgsg->get_context(_hdc), &_make_current_pcollector);
+  wglGraphicsPipe::wgl_make_current(_hdc, context, &_make_current_pcollector);
   wglgsg->reset_if_new();
   wglgsg->report_my_gl_errors();
   if (!wglgsg->get_fb_properties().verify_hardware_software