2
0
Эх сурвалжийг харах

add share_with to make_gsg()

David Rose 22 жил өмнө
parent
commit
a4f08870fa

+ 1 - 1
panda/src/display/graphicsEngine.I

@@ -77,7 +77,7 @@ get_auto_flip() const {
 ////////////////////////////////////////////////////////////////////
 INLINE PT(GraphicsStateGuardian) GraphicsEngine::
 make_gsg(GraphicsPipe *pipe) {
-  return make_gsg(pipe, get_frame_buffer_properties());
+  return make_gsg(pipe, get_frame_buffer_properties(), NULL);
 }
 
 

+ 3 - 2
panda/src/display/graphicsEngine.cxx

@@ -183,9 +183,10 @@ get_threading_model() const {
 //               runs one more time.
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsStateGuardian) GraphicsEngine::
-make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties) {
+make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
+         GraphicsStateGuardian *share_with) {
   // TODO: ask the draw thread to make the GSG.
-  PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties);
+  PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties, share_with);
   if (gsg != (GraphicsStateGuardian *)NULL) {
     gsg->_threading_model = get_threading_model();
     gsg->_pipe = pipe;

+ 2 - 1
panda/src/display/graphicsEngine.h

@@ -71,7 +71,8 @@ PUBLISHED:
 
   INLINE PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe);
   PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
-                                     const FrameBufferProperties &properties);
+                                     const FrameBufferProperties &properties,
+                                     GraphicsStateGuardian *share_with);
 
   GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name,
                               int sort);

+ 2 - 1
panda/src/display/graphicsPipe.cxx

@@ -124,7 +124,8 @@ make_device(void *scrn) {
 //               be called in the draw thread for the GSG.
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsStateGuardian) GraphicsPipe::
-make_gsg(const FrameBufferProperties &properties) {
+make_gsg(const FrameBufferProperties &properties, 
+         GraphicsStateGuardian *share_with) {
   display_cat.error()
     << "make_gsg() unimplemented by " << get_type() << "\n";
   return NULL;

+ 2 - 1
panda/src/display/graphicsPipe.h

@@ -93,7 +93,8 @@ protected:
   // The make_window() and make_gsg() interfaces on GraphicsPipe are
   // protected; don't try to call them directly.  Instead, use
   // the interface on GraphicsEngine to make a new window or gsg.
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual void close_gsg(GraphicsStateGuardian *gsg);
   virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, 
                                          const string &name);

+ 7 - 1
panda/src/dxgsg7/wdxGraphicsPipe7.cxx

@@ -85,7 +85,13 @@ make_window(GraphicsStateGuardian *gsg, const string &name) {
 
 
 PT(GraphicsStateGuardian) wdxGraphicsPipe7::
-make_gsg(const FrameBufferProperties &properties) {
+make_gsg(const FrameBufferProperties &properties,
+         GraphicsStateGuardian *share_with) {
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    wdxdisplay7_cat.error()
+      << "wdxGraphicsPipe7 does not presently support sharing texture contexts.\n";
+    return NULL;
+  }
 
   // FrameBufferProperties really belongs as part of the window/renderbuffer specification
   // put here because of GLX multithreading requirement

+ 2 - 1
panda/src/dxgsg7/wdxGraphicsPipe7.h

@@ -34,7 +34,8 @@ public:
 
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
 
 protected:
   virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, const string &name);

+ 7 - 2
panda/src/dxgsg8/wdxGraphicsPipe8.cxx

@@ -801,8 +801,13 @@ make_device(void *scrn) {
 ////////////////////////////////////////////////////////////////////
 
 PT(GraphicsStateGuardian) wdxGraphicsPipe8::
-make_gsg(const FrameBufferProperties &properties) {
-
+make_gsg(const FrameBufferProperties &properties, 
+         GraphicsStateGuardian *share_with) {
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    wdxdisplay8_cat.error()
+      << "wdxGraphicsPipe8 does not presently support sharing texture contexts.\n";
+    return NULL;
+  }
 
   // FrameBufferProperties really belongs as part of the window/renderbuffer specification
   // put here because of GLX multithreading requirement

+ 2 - 1
panda/src/dxgsg8/wdxGraphicsPipe8.h

@@ -48,7 +48,8 @@ public:
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
 
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsDevice) make_device(void *scrn);
 
   bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,

+ 7 - 2
panda/src/dxgsg9/wdxGraphicsPipe9.cxx

@@ -820,8 +820,13 @@ make_device(void *scrn) {
 ////////////////////////////////////////////////////////////////////
 
 PT(GraphicsStateGuardian) wdxGraphicsPipe9::
-make_gsg(const FrameBufferProperties &properties) {
-
+make_gsg(const FrameBufferProperties &properties,
+         GraphicsStateGuardian *share_with) {
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    wdxdisplay9_cat.error()
+      << "wdxGraphicsPipe9 does not presently support sharing texture contexts.\n";
+    return NULL;
+  }
 
   // FrameBufferProperties really belongs as part of the window/renderbuffer specification
   // put here because of GLX multithreading requirement

+ 2 - 1
panda/src/dxgsg9/wdxGraphicsPipe9.h

@@ -48,7 +48,8 @@ public:
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
 
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsDevice) make_device(void *scrn);
 
   bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,

+ 21 - 4
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -161,11 +161,27 @@ pipe_constructor() {
 //               be called in the draw thread for the GSG.
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsStateGuardian) glxGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties) {
+make_gsg(const FrameBufferProperties &properties,
+         GraphicsStateGuardian *share_with) {
   if (!_is_valid) {
     return NULL;
   }
-  
+
+  glxGraphicsStateGuardian *share_gsg = NULL;
+  GLXContext share_context = NULL;
+
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    if (!share_with->is_exact_type(glxGraphicsStateGuardian::get_class_type())) {
+      glxdisplay_cat.error()
+        << "Cannot share context between glxGraphicsStateGuardian and "
+        << share_with->get_type() << "\n";
+      return NULL;
+    }
+
+    DCAST_INTO_R(share_gsg, share_with, NULL);
+    share_context = share_gsg->_context;
+  }
+
   FrameBufferProperties new_properties = properties;
   GLXFBConfig fbconfig = choose_fbconfig(new_properties);
   if (fbconfig == None) {
@@ -174,7 +190,8 @@ make_gsg(const FrameBufferProperties &properties) {
 
   // Attempt to create a GL context.
   GLXContext context = 
-    glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE);
+    glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, share_context,
+                        GL_TRUE);
   if (context == NULL) {
     glxdisplay_cat.error()
       << "Could not create GL context.\n";
@@ -183,7 +200,7 @@ make_gsg(const FrameBufferProperties &properties) {
 
   // Now we can make a GSG.
   PT(glxGraphicsStateGuardian) gsg = 
-    new glxGraphicsStateGuardian(new_properties, NULL, context, fbconfig,
+    new glxGraphicsStateGuardian(new_properties, share_gsg, context, fbconfig,
                                  _display, _screen);
   return gsg.p();
 }

+ 2 - 1
panda/src/glxdisplay/glxGraphicsPipe.h

@@ -78,7 +78,8 @@ public:
   INLINE Atom get_wm_delete_window() const;
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
                                          const string &name);
   virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 

+ 17 - 2
panda/src/mesadisplay/osMesaGraphicsPipe.cxx

@@ -80,8 +80,23 @@ pipe_constructor() {
 //               be called in the draw thread for the GSG.
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsStateGuardian) OsMesaGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties) {
-  return new OSMesaGraphicsStateGuardian(properties);
+make_gsg(const FrameBufferProperties &properties, 
+         GraphicsStateGuardian *share_with) {
+
+  OSMesaGraphicsStateGuardian *share_gsg = NULL;
+
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    if (!share_with->is_exact_type(OSMesaGraphicsStateGuardian::get_class_type())) {
+      mesadisplay_cat.error()
+        << "Cannot share context between OSMesaGraphicsStateGuardian and "
+        << share_with->get_type() << "\n";
+      return NULL;
+    }
+
+    DCAST_INTO_R(share_gsg, share_with, NULL);
+  }
+
+  return new OSMesaGraphicsStateGuardian(properties, share_gsg);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/mesadisplay/osMesaGraphicsPipe.h

@@ -46,7 +46,8 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 
                                          const string &name,
                                          int x_size, int y_size, bool want_texture);

+ 9 - 2
panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx

@@ -26,10 +26,17 @@ TypeHandle OSMesaGraphicsStateGuardian::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 OSMesaGraphicsStateGuardian::
-OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties) : 
+OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
+                            OSMesaGraphicsStateGuardian *share_with) : 
   MesaGraphicsStateGuardian(properties)
 {
-  _context = OSMesaCreateContext(OSMESA_RGBA, NULL);
+  OSMesaContext share_context = NULL;
+  if (share_with != (OSMesaGraphicsStateGuardian *)NULL) {
+    share_context = share_with->_context;
+    _prepared_objects = share_with->get_prepared_objects();
+  }
+
+  _context = OSMesaCreateContext(OSMESA_RGBA, share_context);
 
   // I think OSMesa always creates single-buffered contexts.  I don't
   // see any documentation to this effect, but it seems to be the

+ 2 - 1
panda/src/mesadisplay/osMesaGraphicsStateGuardian.h

@@ -29,7 +29,8 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAMESA OSMesaGraphicsStateGuardian : public MesaGraphicsStateGuardian {
 public:
-  OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties);
+  OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
+                              OSMesaGraphicsStateGuardian *share_with);
   virtual ~OSMesaGraphicsStateGuardian();
 
   OSMesaContext _context;

+ 23 - 2
panda/src/wgldisplay/wglGraphicsPipe.cxx

@@ -81,11 +81,25 @@ pipe_constructor() {
 //               be called in the draw thread for the GSG.
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsStateGuardian) wglGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties) {
+make_gsg(const FrameBufferProperties &properties, 
+         GraphicsStateGuardian *share_with) {
   if (!_is_valid) {
     return NULL;
   }
 
+  wglGraphicsStateGuardian *share_gsg = NULL;
+
+  if (share_with != (GraphicsStateGuardian *)NULL) {
+    if (!share_with->is_exact_type(wglGraphicsStateGuardian::get_class_type())) {
+      wgldisplay_cat.error()
+        << "Cannot share context between wglGraphicsStateGuardian and "
+        << share_with->get_type() << "\n";
+      return NULL;
+    }
+
+    DCAST_INTO_R(share_gsg, share_with, NULL);
+  }
+
   // Make a copy of the supplied properties so we can possibly modify
   // them to suit our available properties.
   FrameBufferProperties new_properties = properties;
@@ -109,7 +123,14 @@ make_gsg(const FrameBufferProperties &properties) {
   }
 
   PT(wglGraphicsStateGuardian) gsg = 
-    new wglGraphicsStateGuardian(properties, pfnum);
+    new wglGraphicsStateGuardian(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
+  // that yet, because we can't try to actually share the gsg until we
+  // create the context, for which we need to have a window.  That
+  // means the app will just have to trust it will work; if it doesn't
+  // work, too bad.
 
   return gsg.p();
 }

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

@@ -37,7 +37,8 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
                                          const string &name);
   virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 

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

@@ -28,8 +28,10 @@ TypeHandle wglGraphicsStateGuardian::_type_handle;
 ////////////////////////////////////////////////////////////////////
 wglGraphicsStateGuardian::
 wglGraphicsStateGuardian(const FrameBufferProperties &properties,
+                         wglGraphicsStateGuardian *share_with,
                          int pfnum) : 
   GLGraphicsStateGuardian(properties),
+  _share_with(share_with),
   _pfnum(pfnum)
 {
   _made_context = false;
@@ -163,4 +165,72 @@ make_context(HDC hdc) {
       << "Could not create GL context.\n";
     return;
   }
+
+  // Now share texture context with the indicated GSG.
+  if (_share_with != (wglGraphicsStateGuardian *)NULL) {
+    HGLRC share_context = _share_with->get_share_context();
+    if (share_context == NULL) {
+      // Whoops, the target context hasn't yet made its own context.
+      // In that case, it will share context with us.
+      _share_with->redirect_share_pool(this);
+
+    } else {
+      if (!wglShareLists(share_context, _context)) {
+        wgldisplay_cat.error()
+          << "Could not share texture contexts between wglGraphicsStateGuardians.\n";
+        // Too bad we couldn't detect this error sooner.  Now there's
+        // really no way to tell the application it's hosed.
+
+      } else {
+        _prepared_objects = _share_with->get_prepared_objects();
+      }
+    }
+
+    _share_with = (wglGraphicsStateGuardian *)NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsStateGuardian::get_share_context
+//       Access: Private
+//  Description: Returns a wgl context handle for the purpose of
+//               sharing texture context with this GSG.  This will
+//               either be the GSG's own context handle, if it exists
+//               yet, or the context handle of some other GSG that
+//               this GSG is planning to share with.  If this returns
+//               NULL, none of the GSG's in this share pool have yet
+//               created their context.
+////////////////////////////////////////////////////////////////////
+HGLRC wglGraphicsStateGuardian::
+get_share_context() const {
+  if (_made_context) {
+    return _context;
+  }
+  if (_share_with != (wglGraphicsStateGuardian *)NULL) {
+    return _share_with->get_share_context();
+  }
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsStateGuardian::redirect_share_pool
+//       Access: Private
+//  Description: Directs the GSG (along with all GSG's it is planning
+//               to share a texture context with) to share texture
+//               context with the indicated GSG.
+//
+//               This assumes that this GSG's context has not yet been
+//               created, and neither have any of the GSG's it is
+//               planning to share texture context with; but the
+//               graphics context for the indicated GSG has already
+//               been created.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsStateGuardian::
+redirect_share_pool(wglGraphicsStateGuardian *share_with) {
+  nassertv(!_made_context);
+  if (_share_with != (wglGraphicsStateGuardian *)NULL) {
+    _share_with->redirect_share_pool(share_with);
+  } else {
+    _share_with = share_with;
+  }
 }

+ 10 - 1
panda/src/wgldisplay/wglGraphicsStateGuardian.h

@@ -34,7 +34,9 @@
 ////////////////////////////////////////////////////////////////////
 class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
 public:
-  wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum);
+  wglGraphicsStateGuardian(const FrameBufferProperties &properties, 
+                           wglGraphicsStateGuardian *share_with,
+                           int pfnum);
   virtual ~wglGraphicsStateGuardian();
 
   INLINE int get_pfnum() const;
@@ -48,6 +50,13 @@ protected:
 
 private:
   void make_context(HDC hdc);
+  HGLRC get_share_context() const;
+  void redirect_share_pool(wglGraphicsStateGuardian *share_with);
+
+  // 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.
+  PT(wglGraphicsStateGuardian) _share_with;
 
   // All windows that share a particular GL context must also share
   // the same pixel format; therefore, we store the pixel format