Browse Source

add support for render-to-texture

David Rose 21 years ago
parent
commit
7f609122ff

+ 251 - 142
panda/src/wgldisplay/wglGraphicsBuffer.cxx

@@ -43,6 +43,7 @@ wglGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   // Since the pbuffer never gets flipped, we get screenshots from the
   // Since the pbuffer never gets flipped, we get screenshots from the
   // same buffer we draw into.
   // same buffer we draw into.
   _screenshot_buffer_type = _draw_buffer_type;
   _screenshot_buffer_type = _draw_buffer_type;
+  _render_texture = false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -72,6 +73,12 @@ begin_frame() {
   wglGraphicsStateGuardian *wglgsg;
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_R(wglgsg, _gsg, false);
   DCAST_INTO_R(wglgsg, _gsg, false);
 
 
+  if (_render_texture) {
+    // Release the texture so we can render into the pbuffer.
+    //    wglgsg->_wglReleaseTexImageARB(_pbuffer, get_draw_buffer_type() == RenderBuffer::T_back ? WGL_BACK_LEFT_ARB : WGL_FRONT_LEFT_ARB);
+    wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
+  }
+
   if (_pbuffer_dc) {
   if (_pbuffer_dc) {
     int flag = 0;
     int flag = 0;
     wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
     wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
@@ -100,6 +107,7 @@ end_frame() {
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   _gsg->end_frame();
   _gsg->end_frame();
 
 
+
   if (_copy_texture) {
   if (_copy_texture) {
     wglGraphicsStateGuardian *wglgsg;
     wglGraphicsStateGuardian *wglgsg;
     DCAST_INTO_V(wglgsg, _gsg);
     DCAST_INTO_V(wglgsg, _gsg);
@@ -118,15 +126,29 @@ end_frame() {
       }
       }
     }
     }
 
 
-    // For now, we copy the framebuffer to the texture every frame.
-    // Eventually we can take advantage of the render_texture
-    // extension, if it is available, to render directly into a
-    // texture in the first place (but I don't have a card that
-    // supports that right now).
     nassertv(has_texture());
     nassertv(has_texture());
-
-    RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
-    _gsg->copy_texture(get_texture(), _default_display_region, buffer);
+    Texture *tex = get_texture();
+
+    if (_render_texture) {
+      // Bind the pbuffer to our associated texture.  This is a newer
+      // extension that might allow us to use the same memory directly
+      // without having to pay for a copy operation.  But we can't
+      // render again to the pbuffer while the texture is valid.
+      TextureContext *tc = tex->prepare_now(wglgsg->get_prepared_objects(), wglgsg);
+      nassertv(tc != (TextureContext *)NULL);
+      wglgsg->bind_texture(tc);
+
+      //      wglgsg->_wglBindTexImageARB(_pbuffer, get_draw_buffer_type() == RenderBuffer::T_back ? WGL_BACK_LEFT_ARB : WGL_FRONT_LEFT_ARB);
+      wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
+      
+    } else {
+      // Copy the contents of the frame buffer to our associated
+      // texture.  This is an older interface that guarantees a copy
+      // operation will take place, and it might even require
+      // reformatting pixels on the way, so it may be slower.
+      RenderBuffer buffer = wglgsg->get_render_buffer(get_draw_buffer_type());
+      wglgsg->copy_texture(tex, _default_display_region, buffer);
+    }
   }
   }
 }
 }
 
 
@@ -245,6 +267,13 @@ open_buffer() {
   if (wgldisplay_cat.is_debug()) {
   if (wgldisplay_cat.is_debug()) {
     wgldisplay_cat.debug()
     wgldisplay_cat.debug()
       << "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n";
       << "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n";
+    if (_render_texture) {
+      wgldisplay_cat.debug()
+        << "pbuffer renders directly to texture.\n";
+    } else if (_copy_texture) {
+      wgldisplay_cat.debug()
+        << "pbuffer copies indirectly into texture.\n";
+    }
   }
   }
   
   
   wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc));
   wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc));
@@ -277,162 +306,242 @@ make_pbuffer(HDC twindow_dc) {
   int pbformat = wglgsg->get_pfnum();
   int pbformat = wglgsg->get_pfnum();
 
 
   if (wglgsg->_supports_pixel_format) {
   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.
-
-    static const int max_attrib_list = 64;
-    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,
-      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, sample_buffers_i, multisamples_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[sample_buffers_i = ni++] = WGL_SAMPLE_BUFFERS_ARB;
-      iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
+    bool got_pbuffer_format = false;
+
+    if (_copy_texture && wglgsg->_supports_render_texture) {
+      // First, try to get a pbuffer format that supports
+      // render-to-texture.
+      int new_pbformat = choose_pbuffer_format(twindow_dc, true);
+      if (new_pbformat != 0) {
+        pbformat = new_pbformat;
+        got_pbuffer_format = true;
+        _render_texture = true;
+      }
     }
     }
 
 
-    // Terminate the list.
-    nassertr(ni <= max_attrib_list, false);
-
-    if (!wglgsg->_wglGetPixelFormatAttribivARB(twindow_dc, pbformat, 0,
-                                               ni, iattrib_list, ivalue_list)) {
-      return false;
+    if (!got_pbuffer_format) {
+      // Failing that, just get a matching pbuffer format.
+      int new_pbformat = choose_pbuffer_format(twindow_dc, false);
+      if (new_pbformat != 0) {
+        pbformat = new_pbformat;
+        got_pbuffer_format = true;
+      }
     }
     }
 
 
-    ni = 0;
-    float fattrib_list[max_attrib_list];
-    int nf = 0;
-
-    // Since we are trying to create a pbuffer, the pixel format we
-    // request (and subsequently use) must be "pbuffer capable".
-    iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
-    iattrib_list[ni++] = true;
-    iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
-    iattrib_list[ni++] = true;
-
-    // Match up the framebuffer bits.
-    iattrib_list[ni++] = WGL_RED_BITS_ARB;
-    iattrib_list[ni++] = ivalue_list[red_bits_i];
-    iattrib_list[ni++] = WGL_GREEN_BITS_ARB;
-    iattrib_list[ni++] = ivalue_list[green_bits_i];
-    iattrib_list[ni++] = WGL_BLUE_BITS_ARB;
-    iattrib_list[ni++] = ivalue_list[blue_bits_i];
-    iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
-    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++] = ivalue_list[depth_bits_i];
-
-    iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
-    iattrib_list[ni++] = ivalue_list[stencil_bits_i];
-
-    if (wglgsg->_supports_wgl_multisample) {
-      iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB;
-      iattrib_list[ni++] = ivalue_list[sample_buffers_i];
-      iattrib_list[ni++] = WGL_SAMPLES_ARB;
-      iattrib_list[ni++] = ivalue_list[multisamples_i];
+    if (wgldisplay_cat.is_debug()) {
+      FrameBufferProperties properties;
+      wglGraphicsPipe::get_properties_advanced(properties, wglgsg, 
+                                               twindow_dc, pbformat);
+      wgldisplay_cat.debug()
+        << "Chose pixfmt #" << pbformat << " for pbuffer = " 
+        << properties << "\n";
     }
     }
+  }
 
 
-    // Match up properties.
-    iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
-    iattrib_list[ni++] = ivalue_list[double_buffer_i];
-    iattrib_list[ni++] = WGL_STEREO_ARB;
-    iattrib_list[ni++] = ivalue_list[stereo_i];
-
-    // 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(twindow_dc, iattrib_list, fattrib_list,
-                                          max_pformats, pformat, &nformats)
-        || nformats == 0) {
-      wgldisplay_cat.info()
-        << "Couldn't find a suitable pixel format for creating a pbuffer.\n";
-      return false;
+  static const int max_attrib_list = 64;
+  int iattrib_list[max_attrib_list];
+  int ni = 0;
+
+  if (_render_texture) {
+    if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) {
+      iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
+      iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB;
+    } else {
+      iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
+      iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
     }
     }
+    iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
+  }    
+
+  // Terminate the list.
+  nassertr(ni <= max_attrib_list, false);
+  iattrib_list[ni] = 0;
+  
+  _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pbformat, 
+                                          _x_size, _y_size, iattrib_list);
+
+  if (_pbuffer == 0) {
+    wgldisplay_cat.info()
+      << "Attempt to create pbuffer failed.\n";
+    return false;
+  }
 
 
-    nformats = min(nformats, max_pformats);
+  return true;
+}
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsBuffer::choose_pbuffer_format
+//       Access: Private
+//  Description: Select a suitable pixel format that matches the GSG's
+//               existing format, and also is appropriate for a pixel
+//               buffer.  Returns the selected pfnum if successful, or
+//               0 on failure.
+////////////////////////////////////////////////////////////////////
+int wglGraphicsBuffer::
+choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture) {
+  if (wgldisplay_cat.is_debug()) {
+    wgldisplay_cat.debug()
+      << "choose_pbuffer_format(twindow_dc, draw_to_texture = " 
+      << draw_to_texture << ")\n";
+  }
+
+  wglGraphicsStateGuardian *wglgsg;
+  DCAST_INTO_R(wglgsg, _gsg, false);
+
+  int pbformat = wglgsg->get_pfnum();
+
+  static const int max_attrib_list = 64;
+  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,
+    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, sample_buffers_i, multisamples_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[sample_buffers_i = ni++] = WGL_SAMPLE_BUFFERS_ARB;
+    iattrib_list[multisamples_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)) {
     if (wgldisplay_cat.is_debug()) {
     if (wgldisplay_cat.is_debug()) {
       wgldisplay_cat.debug()
       wgldisplay_cat.debug()
-        << "Found " << nformats << " pbuffer formats: [";
-      for (unsigned int i = 0; i < nformats; i++) {
-        wgldisplay_cat.debug(false)
-          << " " << pformat[i];
-      }
-      wgldisplay_cat.debug(false)
-        << " ]\n";
+        << "Could not query old format " << pbformat << ".\n";
     }
     }
-
-    // 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;
-      }
+    return 0;
+  }
+  
+  ni = 0;
+  float fattrib_list[max_attrib_list];
+  int nf = 0;
+  
+  // Since we are trying to create a pbuffer, the pixel format we
+  // request (and subsequently use) must be "pbuffer capable".
+  iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
+  iattrib_list[ni++] = true;
+  iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
+  iattrib_list[ni++] = true;
+
+  if (draw_to_texture) {
+    // If we want to be able to render-to-texture, request that.
+    if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) {
+      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
+      iattrib_list[ni++] = true;
+    } else {
+      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB;
+      iattrib_list[ni++] = true;
     }
     }
-
-    if (!found_pbformat) {
-      // Otherwise, pick any of them.
-      pbformat = pformat[0];
+  }    
+  
+  // Match up the framebuffer bits.
+  iattrib_list[ni++] = WGL_RED_BITS_ARB;
+  iattrib_list[ni++] = ivalue_list[red_bits_i];
+  iattrib_list[ni++] = WGL_GREEN_BITS_ARB;
+  iattrib_list[ni++] = ivalue_list[green_bits_i];
+  iattrib_list[ni++] = WGL_BLUE_BITS_ARB;
+  iattrib_list[ni++] = ivalue_list[blue_bits_i];
+  iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
+  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++] = ivalue_list[depth_bits_i];
+  
+  iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
+  iattrib_list[ni++] = ivalue_list[stencil_bits_i];
+  
+  if (wglgsg->_supports_wgl_multisample) {
+    iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB;
+    iattrib_list[ni++] = ivalue_list[sample_buffers_i];
+    iattrib_list[ni++] = WGL_SAMPLES_ARB;
+    iattrib_list[ni++] = ivalue_list[multisamples_i];
+  }
+  
+  // Match up properties.
+  iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
+  iattrib_list[ni++] = ivalue_list[double_buffer_i];
+  iattrib_list[ni++] = WGL_STEREO_ARB;
+  iattrib_list[ni++] = ivalue_list[stereo_i];
+  
+  // 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(twindow_dc, iattrib_list, fattrib_list,
+                                        max_pformats, pformat, &nformats)
+      || nformats == 0) {
+    if (wgldisplay_cat.is_debug()) {
+      wgldisplay_cat.debug()
+        << "No formats meet the criteria.\n";
     }
     }
+    return 0;
   }
   }
-
+  
+  nformats = min(nformats, max_pformats);
+  
   if (wgldisplay_cat.is_debug()) {
   if (wgldisplay_cat.is_debug()) {
     wgldisplay_cat.debug()
     wgldisplay_cat.debug()
-      << "Chose pixfmt #" << pbformat << " for pbuffer\n";
+      << "Found " << nformats << " pbuffer formats: [";
+    for (unsigned int i = 0; i < nformats; i++) {
+      wgldisplay_cat.debug(false)
+        << " " << pformat[i];
+    }
+    wgldisplay_cat.debug(false)
+      << " ]\n";
   }
   }
   
   
-  int attrib_list[] = {
-    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;
+    }
+  }
   
   
-  _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pbformat, 
-                                          _x_size, _y_size, attrib_list);
-
-  if (_pbuffer == 0) {
-    wgldisplay_cat.info()
-      << "Attempt to create pbuffer failed.\n";
-    return false;
+  if (!found_pbformat) {
+    // Otherwise, pick any of them.
+    pbformat = pformat[0];
   }
   }
 
 
-  return true;
+  return pbformat;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -60,11 +60,13 @@ protected:
 
 
 private:
 private:
   bool make_pbuffer(HDC window_dc);
   bool make_pbuffer(HDC window_dc);
+  int choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture);
 
 
   static void process_1_event();
   static void process_1_event();
 
 
   HPBUFFERARB _pbuffer;
   HPBUFFERARB _pbuffer;
   HDC _pbuffer_dc;
   HDC _pbuffer_dc;
+  bool _render_texture;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 26 - 12
panda/src/wgldisplay/wglGraphicsPipe.cxx

@@ -329,6 +329,18 @@ int wglGraphicsPipe::
 try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode,
 try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode,
               int want_depth_bits, int want_color_bits,
               int want_depth_bits, int want_color_bits,
               int want_alpha_bits, int want_stencil_bits) {
               int want_alpha_bits, int want_stencil_bits) {
+  if (wgldisplay_cat.is_debug()) {
+    wgldisplay_cat.debug()
+      << "try_for_pfnum(hdc, hardware = " << hardware
+      << ", software = " << software
+      << ", frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec
+      << ", want_depth_bits = " << want_depth_bits
+      << ", want_color_bits = " << want_color_bits
+      << ", want_alpha_bits = " << want_alpha_bits
+      << ", want_stencil_bits = " << want_stencil_bits
+      << ")\n";
+  }
+
   PIXELFORMATDESCRIPTOR pfd;
   PIXELFORMATDESCRIPTOR pfd;
   ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
   ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
@@ -348,16 +360,6 @@ try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode,
     break;
     break;
   }
   }
 
 
-  wgldisplay_cat.debug()
-    << "try_for_pfnum(hdc, hardware = " << hardware
-    << ", software = " << software
-    << ", frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec
-    << ", want_depth_bits = " << want_depth_bits
-    << ", want_color_bits = " << want_color_bits
-    << ", want_alpha_bits = " << want_alpha_bits
-    << ", want_stencil_bits = " << want_stencil_bits
-    << ")\n";
-
   // We have to call DescribePixelFormat() once just to get the
   // We have to call DescribePixelFormat() once just to get the
   // highest pfnum available.  Then we can iterate through all of the
   // highest pfnum available.  Then we can iterate through all of the
   // pfnums.
   // pfnums.
@@ -647,6 +649,18 @@ try_for_pfnum_advanced(int orig_pfnum, const wglGraphicsStateGuardian *wglgsg,
                        int want_depth_bits, int want_color_bits,
                        int want_depth_bits, int want_color_bits,
                        int want_alpha_bits, int want_stencil_bits,
                        int want_alpha_bits, int want_stencil_bits,
                        int want_multisamples) {
                        int want_multisamples) {
+  if (wgldisplay_cat.is_debug()) {
+    wgldisplay_cat.debug()
+      << "try_for_pfnum_advanced(orig_pfnum = " << orig_pfnum 
+      << ", wglgsg, window_dc, frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec
+      << ", want_depth_bits = " << want_depth_bits
+      << ", want_color_bits = " << want_color_bits
+      << ", want_alpha_bits = " << want_alpha_bits
+      << ", want_stencil_bits = " << want_stencil_bits
+      << ", want_multisamples = " << want_multisamples
+      << ")\n";
+  }
+
   static const int max_attrib_list = 32;
   static const int max_attrib_list = 32;
   int iattrib_list[max_attrib_list];
   int iattrib_list[max_attrib_list];
   float fattrib_list[max_attrib_list];
   float fattrib_list[max_attrib_list];
@@ -727,8 +741,8 @@ try_for_pfnum_advanced(int orig_pfnum, const wglGraphicsStateGuardian *wglgsg,
                                         max_pformats, pformat, &nformats) ||
                                         max_pformats, pformat, &nformats) ||
       nformats == 0) {
       nformats == 0) {
     if (wgldisplay_cat.is_debug()) {
     if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat.info()
-        << "Couldn't find a suitable advanced pixel format.\n";
+      wgldisplay_cat.debug()
+        << "No formats meet the criteria.\n";
     }
     }
     return 0;
     return 0;
   }
   }

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

@@ -86,6 +86,8 @@ public:
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
+
+  friend class wglGraphicsBuffer;
 };
 };
 
 
 #include "wglGraphicsPipe.I"
 #include "wglGraphicsPipe.I"

+ 19 - 0
panda/src/wgldisplay/wglGraphicsStateGuardian.cxx

@@ -46,6 +46,7 @@ wglGraphicsStateGuardian(const FrameBufferProperties &properties,
   _supports_pbuffer = false;
   _supports_pbuffer = false;
   _supports_pixel_format = false;
   _supports_pixel_format = false;
   _supports_wgl_multisample = false;
   _supports_wgl_multisample = false;
+  _supports_render_texture = false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -75,6 +76,7 @@ reset() {
   _supports_pbuffer = has_extension("WGL_ARB_pbuffer");
   _supports_pbuffer = has_extension("WGL_ARB_pbuffer");
   _supports_pixel_format = has_extension("WGL_ARB_pixel_format");
   _supports_pixel_format = has_extension("WGL_ARB_pixel_format");
   _supports_wgl_multisample = has_extension("WGL_ARB_multisample");
   _supports_wgl_multisample = has_extension("WGL_ARB_multisample");
+  _supports_render_texture = has_extension("WGL_ARB_render_texture");
 
 
   _wglCreatePbufferARB = 
   _wglCreatePbufferARB = 
     (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
     (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
@@ -115,6 +117,23 @@ reset() {
       _supports_pixel_format = false;
       _supports_pixel_format = false;
     }
     }
   }
   }
+
+  _wglBindTexImageARB = 
+    (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB");
+  _wglReleaseTexImageARB = 
+    (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress("wglReleaseTexImageARB");
+  _wglSetPbufferAttribARB = 
+    (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress("wglSetPbufferAttribARB");
+
+  if (_supports_render_texture) {
+    if (_wglBindTexImageARB == NULL ||
+        _wglReleaseTexImageARB == NULL ||
+        _wglSetPbufferAttribARB == NULL) {
+      wgldisplay_cat.error()
+        << "Driver claims to support WGL_ARB_render_texture, but does not define all functions.\n";
+      _supports_render_texture = false;
+    }
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -82,7 +82,6 @@ private:
 
 
 public:
 public:
   bool _supports_pbuffer;
   bool _supports_pbuffer;
-
   PFNWGLCREATEPBUFFERARBPROC _wglCreatePbufferARB;
   PFNWGLCREATEPBUFFERARBPROC _wglCreatePbufferARB;
   PFNWGLGETPBUFFERDCARBPROC _wglGetPbufferDCARB;
   PFNWGLGETPBUFFERDCARBPROC _wglGetPbufferDCARB;
   PFNWGLRELEASEPBUFFERDCARBPROC _wglReleasePbufferDCARB;
   PFNWGLRELEASEPBUFFERDCARBPROC _wglReleasePbufferDCARB;
@@ -90,13 +89,17 @@ public:
   PFNWGLQUERYPBUFFERARBPROC _wglQueryPbufferARB;
   PFNWGLQUERYPBUFFERARBPROC _wglQueryPbufferARB;
 
 
   bool _supports_pixel_format;
   bool _supports_pixel_format;
-
   PFNWGLGETPIXELFORMATATTRIBIVARBPROC _wglGetPixelFormatAttribivARB;
   PFNWGLGETPIXELFORMATATTRIBIVARBPROC _wglGetPixelFormatAttribivARB;
   PFNWGLGETPIXELFORMATATTRIBFVARBPROC _wglGetPixelFormatAttribfvARB;
   PFNWGLGETPIXELFORMATATTRIBFVARBPROC _wglGetPixelFormatAttribfvARB;
   PFNWGLCHOOSEPIXELFORMATARBPROC _wglChoosePixelFormatARB;
   PFNWGLCHOOSEPIXELFORMATARBPROC _wglChoosePixelFormatARB;
 
 
   bool _supports_wgl_multisample;
   bool _supports_wgl_multisample;
 
 
+  bool _supports_render_texture;
+  PFNWGLBINDTEXIMAGEARBPROC _wglBindTexImageARB;
+  PFNWGLRELEASETEXIMAGEARBPROC _wglReleaseTexImageARB;
+  PFNWGLSETPBUFFERATTRIBARBPROC _wglSetPbufferAttribARB;
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
@@ -113,6 +116,8 @@ public:
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
+
+  friend class wglGraphicsBuffer;
 };
 };
 
 
 #include "wglGraphicsStateGuardian.I"
 #include "wglGraphicsStateGuardian.I"