浏览代码

don't prune nonresident geometry in cull--wait until draw

David Rose 18 年之前
父节点
当前提交
68c9ef5207
共有 46 个文件被更改,包括 610 次插入332 次删除
  1. 2 2
      panda/src/cull/cullBinBackToFront.cxx
  2. 1 1
      panda/src/cull/cullBinBackToFront.h
  3. 2 2
      panda/src/cull/cullBinFixed.cxx
  4. 1 1
      panda/src/cull/cullBinFixed.h
  5. 2 2
      panda/src/cull/cullBinFrontToBack.cxx
  6. 1 1
      panda/src/cull/cullBinFrontToBack.h
  7. 2 2
      panda/src/cull/cullBinStateSorted.cxx
  8. 1 1
      panda/src/cull/cullBinStateSorted.h
  9. 2 2
      panda/src/cull/cullBinUnsorted.cxx
  10. 1 1
      panda/src/cull/cullBinUnsorted.h
  11. 2 4
      panda/src/cull/drawCullHandler.cxx
  12. 20 13
      panda/src/display/graphicsStateGuardian.cxx
  13. 14 7
      panda/src/display/graphicsStateGuardian.h
  14. 108 50
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  15. 14 7
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  16. 110 53
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  17. 14 7
      panda/src/dxgsg9/dxGraphicsStateGuardian9.h
  18. 157 85
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  19. 28 14
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  20. 9 4
      panda/src/glstuff/glShaderContext_src.cxx
  21. 2 1
      panda/src/glstuff/glShaderContext_src.h
  22. 20 8
      panda/src/gobj/geom.cxx
  23. 5 4
      panda/src/gobj/geom.h
  24. 4 3
      panda/src/gobj/geomLines.cxx
  25. 3 2
      panda/src/gobj/geomLines.h
  26. 4 3
      panda/src/gobj/geomLinestrips.cxx
  27. 3 2
      panda/src/gobj/geomLinestrips.h
  28. 4 3
      panda/src/gobj/geomPoints.cxx
  29. 3 2
      panda/src/gobj/geomPoints.h
  30. 3 2
      panda/src/gobj/geomPrimitive.h
  31. 4 3
      panda/src/gobj/geomTriangles.cxx
  32. 3 2
      panda/src/gobj/geomTriangles.h
  33. 4 3
      panda/src/gobj/geomTrifans.cxx
  34. 3 2
      panda/src/gobj/geomTrifans.h
  35. 4 3
      panda/src/gobj/geomTristrips.cxx
  36. 3 2
      panda/src/gobj/geomTristrips.h
  37. 15 1
      panda/src/gobj/geomVertexArrayData.I
  38. 2 0
      panda/src/gobj/geomVertexArrayData.h
  39. 8 7
      panda/src/gsgbase/graphicsStateGuardianBase.h
  40. 1 1
      panda/src/pgraph/cullBin.h
  41. 3 3
      panda/src/pgraph/cullHandler.I
  42. 4 4
      panda/src/pgraph/cullHandler.cxx
  43. 2 2
      panda/src/pgraph/cullHandler.h
  44. 9 7
      panda/src/pgraph/cullResult.cxx
  45. 2 2
      panda/src/pgraph/cullableObject.I
  46. 1 1
      panda/src/pgraph/cullableObject.h

+ 2 - 2
panda/src/cull/cullBinBackToFront.cxx

@@ -101,12 +101,12 @@ finish_cull(SceneSetup *, Thread *current_thread) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinBackToFront::
-draw(Thread *current_thread) {
+draw(bool force, Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector, current_thread);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg, current_thread);
+    CullHandler::draw(object, _gsg, force, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinBackToFront.h

@@ -49,7 +49,7 @@ public:
 
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
-  virtual void draw(Thread *current_thread);
+  virtual void draw(bool force, Thread *current_thread);
 
 private:
   class ObjectData {

+ 2 - 2
panda/src/cull/cullBinFixed.cxx

@@ -87,12 +87,12 @@ finish_cull(SceneSetup *, Thread *current_thread) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinFixed::
-draw(Thread *current_thread) {
+draw(bool force, Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector, current_thread);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg, current_thread);
+    CullHandler::draw(object, _gsg, force, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinFixed.h

@@ -51,7 +51,7 @@ public:
 
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
-  virtual void draw(Thread *current_thread);
+  virtual void draw(bool force, Thread *current_thread);
 
 private:
   class ObjectData {

+ 2 - 2
panda/src/cull/cullBinFrontToBack.cxx

@@ -101,12 +101,12 @@ finish_cull(SceneSetup *, Thread *current_thread) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinFrontToBack::
-draw(Thread *current_thread) {
+draw(bool force, Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector, current_thread);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg, current_thread);
+    CullHandler::draw(object, _gsg, force, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinFrontToBack.h

@@ -49,7 +49,7 @@ public:
 
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
-  virtual void draw(Thread *current_thread);
+  virtual void draw(bool force, Thread *current_thread);
 
 private:
   class ObjectData {

+ 2 - 2
panda/src/cull/cullBinStateSorted.cxx

@@ -86,12 +86,12 @@ finish_cull(SceneSetup *, Thread *current_thread) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinStateSorted::
-draw(Thread *current_thread) {
+draw(bool force, Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector, current_thread);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg, current_thread);
+    CullHandler::draw(object, _gsg, force, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinStateSorted.h

@@ -53,7 +53,7 @@ public:
 
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
-  virtual void draw(Thread *current_thread);
+  virtual void draw(bool force, Thread *current_thread);
 
 private:
   class ObjectData {

+ 2 - 2
panda/src/cull/cullBinUnsorted.cxx

@@ -67,12 +67,12 @@ add_object(CullableObject *object, Thread *current_thread) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinUnsorted::
-draw(Thread *current_thread) {
+draw(bool force, Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector, current_thread);
   Objects::iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi);
-    CullHandler::draw(object, _gsg, current_thread);
+    CullHandler::draw(object, _gsg, force, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinUnsorted.h

@@ -43,7 +43,7 @@ public:
                            const PStatCollector &draw_region_pcollector);
 
   virtual void add_object(CullableObject *object, Thread *current_thread);
-  virtual void draw(Thread *current_thread);
+  virtual void draw(bool force, Thread *current_thread);
 
 private:
   typedef pvector<CullableObject *> Objects;

+ 2 - 4
panda/src/cull/drawCullHandler.cxx

@@ -40,10 +40,8 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
   Thread *current_thread = traverser->get_current_thread();
 
   if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
-    if (force || object->request_resident()) {
-      // Now we can immediately draw the object.
-      draw(object, _gsg, current_thread);
-    }
+    // Now we can immediately draw the object.
+    draw(object, _gsg, force, current_thread);
   }
 
   // Dispense with the object.

+ 20 - 13
panda/src/display/graphicsStateGuardian.cxx

@@ -1312,7 +1312,8 @@ finish_decal() {
 bool GraphicsStateGuardian::
 begin_draw_primitives(const GeomPipelineReader *geom_reader,
                       const GeomMunger *munger,
-                      const GeomVertexDataPipelineReader *data_reader) {
+                      const GeomVertexDataPipelineReader *data_reader,
+                      bool) {
   _munger = munger;
   _data_reader = data_reader;
   return _data_reader->has_vertex();
@@ -1323,8 +1324,9 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected triangles.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_triangles(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_triangles(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1332,8 +1334,9 @@ draw_triangles(const GeomPrimitivePipelineReader *) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle strips.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_tristrips(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_tristrips(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1341,8 +1344,9 @@ draw_tristrips(const GeomPrimitivePipelineReader *) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle fans.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_trifans(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_trifans(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1350,8 +1354,9 @@ draw_trifans(const GeomPrimitivePipelineReader *) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected line segments.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_lines(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_lines(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1359,8 +1364,9 @@ draw_lines(const GeomPrimitivePipelineReader *) {
 //       Access: Public, Virtual
 //  Description: Draws a series of line strips.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_linestrips(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_linestrips(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1368,8 +1374,9 @@ draw_linestrips(const GeomPrimitivePipelineReader *) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected points.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
-draw_points(const GeomPrimitivePipelineReader *) {
+bool GraphicsStateGuardian::
+draw_points(const GeomPrimitivePipelineReader *, bool) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 14 - 7
panda/src/display/graphicsStateGuardian.h

@@ -215,13 +215,20 @@ public:
 
   virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader,
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader);
-  virtual void draw_triangles(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_tristrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_trifans(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_lines(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_linestrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_points(const GeomPrimitivePipelineReader *reader);
+                                     const GeomVertexDataPipelineReader *data_reader,
+                                     bool force);
+  virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
+                            bool force);
+  virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
+                          bool force);
+  virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
+                               bool force);
+  virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
+                           bool force);
   virtual void end_draw_primitives();
 
   INLINE bool reset_if_new();

+ 108 - 50
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -797,9 +797,10 @@ end_frame(Thread *current_thread) {
 bool DXGraphicsStateGuardian8::
 begin_draw_primitives(const GeomPipelineReader *geom_reader,
                       const GeomMunger *munger,
-                      const GeomVertexDataPipelineReader *data_reader) {
+                      const GeomVertexDataPipelineReader *data_reader,
+                      bool force) {
   if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger,
-                                                    data_reader)) {
+                                                    data_reader, force)) {
     return false;
   }
   nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
@@ -903,8 +904,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected triangles.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_triangles(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian8::
+draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   _vertices_tri_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_tri_pcollector.add_level(1);
@@ -915,7 +916,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
       _d3d_device->DrawIndexedPrimitive
@@ -925,14 +926,20 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Indexed, client arrays.
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       draw_indexed_primitive_up
         (D3DPT_TRIANGLELIST,
          min_vertex, max_vertex,
          reader->get_num_primitives(),
-         reader->get_read_pointer(true),
-         index_type,
-         _data_reader->get_array_reader(0)->get_read_pointer(true),
+         index_pointer, index_type, vertex_pointer, 
          _data_reader->get_format()->get_array(0)->get_stride());
     }
   } else {
@@ -945,14 +952,18 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Nonindexed, client arrays.
-
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
                         reader->get_first_vertex(),
                         reader->get_num_vertices(),
-                        _data_reader->get_array_reader(0)->get_read_pointer(true),
+                        vertex_pointer,
                         _data_reader->get_format()->get_array(0)->get_stride());
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -960,8 +971,8 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle strips.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_tristrips(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian8::
+draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
     // One long triangle strip, connected by the degenerate vertices
@@ -975,7 +986,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
       if (_active_vbuffer != NULL) {
         // Indexed, vbuffers, one line triangle strip.
         IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-        nassertv(ibc != (IndexBufferContext *)NULL);
+        nassertr(ibc != (IndexBufferContext *)NULL, false);
         apply_index_buffer(ibc, reader);
 
         _d3d_device->DrawIndexedPrimitive
@@ -985,13 +996,20 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Indexed, client arrays, one long triangle strip.
+        const unsigned char *index_pointer = reader->get_read_pointer(force);
+        if (index_pointer == NULL) {
+          return false;
+        }
         D3DFORMAT index_type = get_index_type(reader->get_index_type());
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
         draw_indexed_primitive_up
           (D3DPT_TRIANGLESTRIP,
            min_vertex, max_vertex,
            reader->get_num_vertices() - 2,
-           reader->get_read_pointer(true), index_type,
-           _data_reader->get_array_reader(0)->get_read_pointer(true),
+           index_pointer, index_type, vertex_pointer,
            _data_reader->get_format()->get_array(0)->get_stride());
       }
     } else {
@@ -1004,11 +1022,15 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Indexed, client arrays, one long triangle strip.
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
         draw_primitive_up(D3DPT_TRIANGLESTRIP,
                           reader->get_num_vertices() - 2,
                           reader->get_first_vertex(),
                           reader->get_num_vertices(),
-                          _data_reader->get_array_reader(0)->get_read_pointer(true),
+                          vertex_pointer,
                           _data_reader->get_format()->get_array(0)->get_stride());
       }
     }
@@ -1026,13 +1048,13 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       GeomVertexReader mins(reader->get_mins(), 0);
       GeomVertexReader maxs(reader->get_maxs(), 0);
-      nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-               reader->get_maxs()->get_num_rows() == (int)ends.size());
+      nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+               reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
       if (_active_vbuffer != NULL) {
         // Indexed, vbuffers, individual triangle strips.
         IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-        nassertv(ibc != (IndexBufferContext *)NULL);
+        nassertr(ibc != (IndexBufferContext *)NULL, false);
         apply_index_buffer(ibc, reader);
 
         unsigned int start = 0;
@@ -1050,10 +1072,16 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Indexed, client arrays, individual triangle strips.
-        const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
         int stride = _data_reader->get_format()->get_array(0)->get_stride();
-        const unsigned char *vertices = reader->get_read_pointer(true);
+        const unsigned char *index_pointer = reader->get_read_pointer(force);
+        if (index_pointer == NULL) {
+          return false;
+        }
         D3DFORMAT index_type = get_index_type(reader->get_index_type());
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
 
         unsigned int start = 0;
         for (size_t i = 0; i < ends.size(); i++) {
@@ -1064,8 +1092,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
             (D3DPT_TRIANGLESTRIP,
              min, max,
              ends[i] - start - 2,
-             vertices + start * index_stride, index_type,
-             array_data, stride);
+             index_pointer + start * index_stride, index_type,
+             vertex_pointer, stride);
 
           start = ends[i] + 2;
         }
@@ -1087,7 +1115,10 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Nonindexed, client arrays, individual triangle strips.
-        const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
         int stride = _data_reader->get_format()->get_array(0)->get_stride();
 
         unsigned int start = 0;
@@ -1096,13 +1127,14 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
           draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
                             first_vertex + start,
                             ends[i] - start,
-                            array_data, stride);
+                            vertex_pointer, stride);
 
           start = ends[i] + 2;
         }
       }
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1110,8 +1142,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle fans.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_trifans(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian8::
+draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   CPTA_int ends = reader->get_ends();
   _primitive_batches_trifan_pcollector.add_level(ends.size());
@@ -1126,13 +1158,13 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     GeomVertexReader mins(reader->get_mins(), 0);
     GeomVertexReader maxs(reader->get_maxs(), 0);
-    nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-             reader->get_maxs()->get_num_rows() == (int)ends.size());
+    nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+             reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
       unsigned int start = 0;
@@ -1150,10 +1182,16 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Indexed, client arrays.
-      const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
       int stride = _data_reader->get_format()->get_array(0)->get_stride();
-      const unsigned char *vertices = reader->get_read_pointer(true);
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
 
       unsigned int start = 0;
       for (size_t i = 0; i < ends.size(); i++) {
@@ -1164,8 +1202,8 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
           (D3DPT_TRIANGLEFAN,
            min, max,
            ends[i] - start - 2,
-           vertices + start * index_stride, index_type,
-           array_data, stride);
+           index_pointer + start * index_stride, index_type,
+           vertex_pointer, stride);
 
         start = ends[i];
       }
@@ -1187,7 +1225,10 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Nonindexed, client arrays.
-      const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       int stride = _data_reader->get_format()->get_array(0)->get_stride();
 
       unsigned int start = 0;
@@ -1197,11 +1238,12 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
                           ends[i] - start - 2,
                           first_vertex,
                           ends[i] - start,
-                          array_data, stride);
+                          vertex_pointer, stride);
         start = ends[i];
       }
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1209,8 +1251,8 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected line segments.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_lines(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian8::
+draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
@@ -1222,7 +1264,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
       _d3d_device->DrawIndexedPrimitive
@@ -1232,15 +1274,21 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Indexed, client arrays.
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
 
       draw_indexed_primitive_up
         (D3DPT_LINELIST,
          min_vertex, max_vertex,
          reader->get_num_primitives(),
-         reader->get_read_pointer(true),
-         index_type,
-         _data_reader->get_array_reader(0)->get_read_pointer(true),
+         index_pointer, index_type, vertex_pointer,
          _data_reader->get_format()->get_array(0)->get_stride());
     }
   } else {
@@ -1253,13 +1301,18 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Nonindexed, client arrays.
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
                         reader->get_first_vertex(),
                         reader->get_num_vertices(),
-                        _data_reader->get_array_reader(0)->get_read_pointer(true),
+                        vertex_pointer,
                         _data_reader->get_format()->get_array(0)->get_stride());
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1267,9 +1320,9 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of line strips.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_linestrips(const GeomPrimitivePipelineReader *reader) {
-  PStatTimer timer(_draw_primitive_pcollector);
+bool DXGraphicsStateGuardian8::
+draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1277,15 +1330,15 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected points.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
-draw_points(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian8::
+draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
   // The munger should have protected us from indexed points--DirectX
   // doesn't support them.
-  nassertv(!reader->is_indexed());
+  nassertr(!reader->is_indexed(), false);
 
   if (_active_vbuffer != NULL) {
     // Nonindexed, vbuffers.
@@ -1296,12 +1349,17 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
 
   } else {
     // Nonindexed, client arrays.
+    const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+    if (vertex_pointer == NULL) {
+      return false;
+    }
     draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
                       reader->get_first_vertex(),
                       reader->get_num_vertices(),
-                      _data_reader->get_array_reader(0)->get_read_pointer(true),
+                      vertex_pointer,
                       _data_reader->get_format()->get_array(0)->get_stride());
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 14 - 7
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -84,13 +84,20 @@ public:
 
   virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader,
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader);
-  virtual void draw_triangles(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_tristrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_trifans(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_lines(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_linestrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_points(const GeomPrimitivePipelineReader *reader);
+                                     const GeomVertexDataPipelineReader *data_reader,
+                                     bool force);
+  virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
+                            bool force);
+  virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
+                          bool force);
+  virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
+                               bool force);
+  virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
+                           bool force);
   virtual void end_draw_primitives();
 
   virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,

+ 110 - 53
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -1227,9 +1227,10 @@ DBG_S dxgsg9_cat.debug ( ) << "@@@@@@@@@@ end_frame \n"; DBG_E
 bool DXGraphicsStateGuardian9::
 begin_draw_primitives(const GeomPipelineReader *geom_reader,
                       const GeomMunger *munger,
-                      const GeomVertexDataPipelineReader *data_reader) {
+                      const GeomVertexDataPipelineReader *data_reader,
+                      bool force) {
   if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger,
-                                                    data_reader)) {
+                                                    data_reader, force)) {
     return false;
   }
   nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
@@ -1458,8 +1459,8 @@ vertex_element_array -> vertex_element_type_array;
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected triangles.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_triangles(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian9::
+draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
 
 //  DBG_SH5 dxgsg9_cat.debug ( ) << "draw_triangles 1\n"; DBG_E
@@ -1473,7 +1474,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
 //DBG_SH2 dxgsg9_cat.debug ( ) << "DrawIndexedPrimitive \n"; DBG_E
@@ -1488,14 +1489,21 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 
 //DBG_SH2 dxgsg9_cat.debug ( ) << "draw_indexed_primitive_up \n"; DBG_E
 
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
+
       draw_indexed_primitive_up
         (D3DPT_TRIANGLELIST,
          min_vertex, max_vertex,
          reader->get_num_primitives(),
-         reader->get_read_pointer(true),
-         index_type,
-         _data_reader->get_array_reader(0)->get_read_pointer(true),
+         index_pointer, index_type, vertex_pointer,
          _data_reader->get_format()->get_array(0)->get_stride());
     }
   } else {
@@ -1513,16 +1521,20 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
       // Nonindexed, client arrays.
 
 //DBG_SH2 dxgsg9_cat.debug ( ) << "draw_primitive_up \n"; DBG_E
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
 
       draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
       reader->get_first_vertex(),
-      reader->get_num_vertices(),
-      _data_reader->get_array_reader(0)->get_read_pointer(true),
+      reader->get_num_vertices(), vertex_pointer,
       _data_reader->get_format()->get_array(0)->get_stride());
     }
   }
 
 //  DBG_SH5 dxgsg9_cat.debug ( ) << "end draw_triangles 1\n"; DBG_E
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1530,8 +1542,8 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle strips.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_tristrips(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian9::
+draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
 
   DBG_SH5 dxgsg9_cat.debug ( ) << "draw_tristrips\n"; DBG_E
@@ -1548,7 +1560,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
       if (_active_vbuffer != NULL) {
         // Indexed, vbuffers, one line triangle strip.
         IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-        nassertv(ibc != (IndexBufferContext *)NULL);
+        nassertr(ibc != (IndexBufferContext *)NULL, false);
         apply_index_buffer(ibc, reader);
 
 //dxgsg9_cat.error ( ) << "DrawIndexedPrimitive D3DPT_TRIANGLESTRIP VERTICES: " << reader->get_num_vertices ( ) << "\n";
@@ -1563,13 +1575,21 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 //dxgsg9_cat.error ( ) << "draw_indexed_primitive_up D3DPT_TRIANGLESTRIP VERTICES: " << reader->get_num_vertices ( ) << "\n";
 
         // Indexed, client arrays, one long triangle strip.
+        const unsigned char *index_pointer = reader->get_read_pointer(force);
+        if (index_pointer == NULL) {
+          return false;
+        }
         D3DFORMAT index_type = get_index_type(reader->get_index_type());
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
+
         draw_indexed_primitive_up
           (D3DPT_TRIANGLESTRIP,
            min_vertex, max_vertex,
            reader->get_num_vertices() - 2,
-           reader->get_read_pointer(true), index_type,
-           _data_reader->get_array_reader(0)->get_read_pointer(true),
+           index_pointer, index_type, vertex_pointer,
            _data_reader->get_format()->get_array(0)->get_stride());
       }
     } else {
@@ -1585,11 +1605,14 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Indexed, client arrays, one long triangle strip.
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
         draw_primitive_up(D3DPT_TRIANGLESTRIP,
         reader->get_num_vertices() - 2,
         reader->get_first_vertex(),
-        reader->get_num_vertices(),
-        _data_reader->get_array_reader(0)->get_read_pointer(true),
+        reader->get_num_vertices(), vertex_pointer,
         _data_reader->get_format()->get_array(0)->get_stride());
       }
     }
@@ -1607,13 +1630,13 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       GeomVertexReader mins(reader->get_mins(), 0);
       GeomVertexReader maxs(reader->get_maxs(), 0);
-      nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-               reader->get_maxs()->get_num_rows() == (int)ends.size());
+      nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+               reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
       if (_active_vbuffer != NULL) {
         // Indexed, vbuffers, individual triangle strips.
         IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-        nassertv(ibc != (IndexBufferContext *)NULL);
+        nassertr(ibc != (IndexBufferContext *)NULL, false);
         apply_index_buffer(ibc, reader);
 
         unsigned int start = 0;
@@ -1632,10 +1655,16 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Indexed, client arrays, individual triangle strips.
-        const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
         int stride = _data_reader->get_format()->get_array(0)->get_stride();
-        const unsigned char *vertices = reader->get_read_pointer(true);
+        const unsigned char *index_pointer = reader->get_read_pointer(force);
+        if (index_pointer == NULL) {
+          return false;
+        }
         D3DFORMAT index_type = get_index_type(reader->get_index_type());
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
 
         unsigned int start = 0;
         for (size_t i = 0; i < ends.size(); i++) {
@@ -1646,8 +1675,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
             (D3DPT_TRIANGLESTRIP,
              min, max,
              ends[i] - start - 2,
-             vertices + start * index_stride, index_type,
-             array_data, stride);
+             index_pointer + start * index_stride, index_type,
+             vertex_pointer, stride);
 
           start = ends[i] + 2;
         }
@@ -1669,7 +1698,10 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       } else {
         // Nonindexed, client arrays, individual triangle strips.
-        const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
+        const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+        if (vertex_pointer == NULL) {
+          return false;
+        }
         int stride = _data_reader->get_format()->get_array(0)->get_stride();
 
         unsigned int start = 0;
@@ -1678,13 +1710,14 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
           draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
           first_vertex + start,
           ends[i] - start,
-          array_data, stride);
+          vertex_pointer, stride);
 
           start = ends[i] + 2;
         }
       }
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1692,8 +1725,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle fans.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_trifans(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian9::
+draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
 
   DBG_SH5 dxgsg9_cat.debug ( ) << "draw_trifans\n"; DBG_E
@@ -1711,13 +1744,13 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     GeomVertexReader mins(reader->get_mins(), 0);
     GeomVertexReader maxs(reader->get_maxs(), 0);
-    nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-             reader->get_maxs()->get_num_rows() == (int)ends.size());
+    nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+             reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
       unsigned int start = 0;
@@ -1735,10 +1768,16 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Indexed, client arrays.
-      const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
       int stride = _data_reader->get_format()->get_array(0)->get_stride();
-      const unsigned char *vertices = reader->get_read_pointer(true);
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
 
       unsigned int start = 0;
       for (size_t i = 0; i < ends.size(); i++) {
@@ -1749,8 +1788,8 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
           (D3DPT_TRIANGLEFAN,
            min, max,
            ends[i] - start - 2,
-           vertices + start * index_stride, index_type,
-           array_data, stride);
+           index_pointer + start * index_stride, index_type,
+           vertex_pointer, stride);
 
         start = ends[i];
       }
@@ -1772,7 +1811,10 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Nonindexed, client arrays.
-      const unsigned char *array_data = _data_reader->get_array_reader(0)->get_read_pointer(true);
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       int stride = _data_reader->get_format()->get_array(0)->get_stride();
 
       unsigned int start = 0;
@@ -1782,11 +1824,12 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
         ends[i] - start - 2,
         first_vertex,
         ends[i] - start,
-        array_data, stride);
+        vertex_pointer, stride);
         start = ends[i];
       }
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1794,8 +1837,8 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected line segments.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_lines(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian9::
+draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
@@ -1807,7 +1850,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
     if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
-      nassertv(ibc != (IndexBufferContext *)NULL);
+      nassertr(ibc != (IndexBufferContext *)NULL, false);
       apply_index_buffer(ibc, reader);
 
       _d3d_device->DrawIndexedPrimitive
@@ -1818,15 +1861,21 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Indexed, client arrays.
+      const unsigned char *index_pointer = reader->get_read_pointer(force);
+      if (index_pointer == NULL) {
+        return false;
+      }
       D3DFORMAT index_type = get_index_type(reader->get_index_type());
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
 
       draw_indexed_primitive_up
         (D3DPT_LINELIST,
          min_vertex, max_vertex,
          reader->get_num_primitives(),
-         reader->get_read_pointer(true),
-         index_type,
-         _data_reader->get_array_reader(0)->get_read_pointer(true),
+         index_pointer, index_type, vertex_pointer,
          _data_reader->get_format()->get_array(0)->get_stride());
     }
   } else {
@@ -1839,13 +1888,17 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 
     } else {
       // Nonindexed, client arrays.
+      const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+      if (vertex_pointer == NULL) {
+        return false;
+      }
       draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
       reader->get_first_vertex(),
-      reader->get_num_vertices(),
-      _data_reader->get_array_reader(0)->get_read_pointer(true),
+      reader->get_num_vertices(), vertex_pointer,
       _data_reader->get_format()->get_array(0)->get_stride());
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1853,9 +1906,9 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of line strips.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_linestrips(const GeomPrimitivePipelineReader *reader) {
-  PStatTimer timer(_draw_primitive_pcollector);
+bool DXGraphicsStateGuardian9::
+draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1863,15 +1916,15 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected points.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian9::
-draw_points(const GeomPrimitivePipelineReader *reader) {
+bool DXGraphicsStateGuardian9::
+draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
   // The munger should have protected us from indexed points--DirectX
   // doesn't support them.
-  nassertv(!reader->is_indexed());
+  nassertr(!reader->is_indexed(), false);
 
   if (_active_vbuffer != NULL) {
     // Nonindexed, vbuffers.
@@ -1882,12 +1935,16 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
 
   } else {
     // Nonindexed, client arrays.
+    const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
+    if (vertex_pointer == NULL) {
+      return false;
+    }
     draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
                       reader->get_first_vertex(),
-                      reader->get_num_vertices(),
-                      _data_reader->get_array_reader(0)->get_read_pointer(true),
+                      reader->get_num_vertices(), vertex_pointer,
                       _data_reader->get_format()->get_array(0)->get_stride());
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 14 - 7
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -124,13 +124,20 @@ public:
 
   virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader,
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader);
-  virtual void draw_triangles(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_tristrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_trifans(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_lines(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_linestrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_points(const GeomPrimitivePipelineReader *reader);
+                                     const GeomVertexDataPipelineReader *data_reader,
+                                     bool force);
+  virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
+                            bool force);
+  virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
+                          bool force);
+  virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
+                               bool force);
+  virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
+                           bool force);
   virtual void end_draw_primitives();
 
   virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,

+ 157 - 85
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1468,14 +1468,15 @@ end_frame(Thread *current_thread) {
 bool CLP(GraphicsStateGuardian)::
 begin_draw_primitives(const GeomPipelineReader *geom_reader,
                       const GeomMunger *munger,
-                      const GeomVertexDataPipelineReader *data_reader) {
+                      const GeomVertexDataPipelineReader *data_reader,
+                      bool force) {
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam() << "begin_draw_primitives: " << *(data_reader->get_object()) << "\n";
   }
 #endif  // NDEBUG
 
-  if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger, data_reader)) {
+  if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger, data_reader, force)) {
     return false;
   }
   nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
@@ -1687,18 +1688,26 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 #endif
   if (_vertex_array_shader_context==0) {
     if (_current_shader_context==0) {
-      update_standard_vertex_arrays();
+      if (!update_standard_vertex_arrays(force)) {
+        return false;
+      }
     } else {
       disable_standard_vertex_arrays();
-      _current_shader_context->update_shader_vertex_arrays(NULL,this);
+      if (!_current_shader_context->update_shader_vertex_arrays(NULL, this, force)) {
+        return false;
+      }
     }
   } else {
     if (_current_shader_context==0) {
       _vertex_array_shader_context->disable_shader_vertex_arrays(this);
-      update_standard_vertex_arrays();
+      if (!update_standard_vertex_arrays(force)) {
+        return false;
+      }
     } else {
-      _current_shader_context->
-        update_shader_vertex_arrays(_vertex_array_shader_context,this);
+      if (!_current_shader_context->
+          update_shader_vertex_arrays(_vertex_array_shader_context, this, force)) {
+        return false;
+      }
     }
   }
   _vertex_array_shader_expansion = _current_shader_expansion;
@@ -1720,8 +1729,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 //               is about to be used - glShaderContexts are responsible
 //               for setting up their own vertex arrays.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-update_standard_vertex_arrays() {
+bool CLP(GraphicsStateGuardian)::
+update_standard_vertex_arrays(bool force) {
   const GeomVertexAnimationSpec &animation =
     _data_reader->get_format()->get_animation();
   bool hardware_animation = (animation.get_animation_type() == Geom::AT_hardware);
@@ -1804,6 +1813,7 @@ update_standard_vertex_arrays() {
   {
     // We may use vertex arrays or buffers to render primitives.
     const GeomVertexArrayDataHandle *array_reader;
+    const unsigned char *client_pointer;
     int num_values;
     Geom::NumericType numeric_type;
     int start;
@@ -1811,7 +1821,9 @@ update_standard_vertex_arrays() {
 
     if (_data_reader->get_normal_info(array_reader, numeric_type,
                                       start, stride)) {
-      const unsigned char *client_pointer = setup_array_data(array_reader);
+      if (!setup_array_data(client_pointer, array_reader, force)) {
+        return false;
+      }
       GLP(NormalPointer)(get_numeric_type(numeric_type), stride,
                          client_pointer + start);
       GLP(EnableClientState)(GL_NORMAL_ARRAY);
@@ -1822,7 +1834,9 @@ update_standard_vertex_arrays() {
     if (_data_reader->get_color_info(array_reader, num_values, numeric_type,
                                      start, stride) &&
         numeric_type != Geom::NT_packed_dabc) {
-      const unsigned char *client_pointer = setup_array_data(array_reader);
+      if (!setup_array_data(client_pointer, array_reader, force)) {
+        return false;
+      }
       GLP(ColorPointer)(num_values, get_numeric_type(numeric_type),
                         stride, client_pointer + start);
       GLP(EnableClientState)(GL_COLOR_ARRAY);
@@ -1855,7 +1869,9 @@ update_standard_vertex_arrays() {
         if (_data_reader->get_array_info(name, array_reader, num_values,
                                          numeric_type, start, stride)) {
           // The vertex data does have texcoords for this stage.
-          const unsigned char *client_pointer = setup_array_data(array_reader);
+          if (!setup_array_data(client_pointer, array_reader, force)) {
+            return false;
+          }
           GLP(TexCoordPointer)(num_values, get_numeric_type(numeric_type),
                                stride, client_pointer + start);
           GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY);
@@ -1887,7 +1903,9 @@ update_standard_vertex_arrays() {
         if (_data_reader->get_array_info(InternalName::get_transform_weight(),
                                          array_reader, num_values, numeric_type,
                                          start, stride)) {
-          const unsigned char *client_pointer = setup_array_data(array_reader);
+          if (!setup_array_data(client_pointer, array_reader, force)) {
+            return false;
+          }
           _glWeightPointerARB(num_values, get_numeric_type(numeric_type),
                               stride, client_pointer + start);
           GLP(EnableClientState)(GL_WEIGHT_ARRAY_ARB);
@@ -1900,7 +1918,9 @@ update_standard_vertex_arrays() {
           if (_data_reader->get_array_info(InternalName::get_transform_index(),
                                            array_reader, num_values, numeric_type,
                                            start, stride)) {
-            const unsigned char *client_pointer = setup_array_data(array_reader);
+            if (!setup_array_data(client_pointer, array_reader, force)) {
+              return false;
+            }
             _glMatrixIndexPointerARB(num_values, get_numeric_type(numeric_type),
                                      stride, client_pointer + start);
             GLP(EnableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
@@ -1921,12 +1941,15 @@ update_standard_vertex_arrays() {
     // anyway.
     if (_data_reader->get_vertex_info(array_reader, num_values, numeric_type,
                                       start, stride)) {
-      const unsigned char *client_pointer = setup_array_data(array_reader);
+      if (!setup_array_data(client_pointer, array_reader, force)) {
+        return false;
+      }
       GLP(VertexPointer)(num_values, get_numeric_type(numeric_type),
                          stride, client_pointer + start);
       GLP(EnableClientState)(GL_VERTEX_ARRAY);
     }
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1974,8 +1997,8 @@ disable_standard_vertex_arrays()
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected triangles.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_triangles(const GeomPrimitivePipelineReader *reader) {
+bool CLP(GraphicsStateGuardian)::
+draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 
 #ifndef NDEBUG
@@ -1996,7 +2019,10 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
     _primitive_batches_tri_pcollector.add_level(1);
 
     if (reader->is_indexed()) {
-      const unsigned char *client_pointer = setup_primitive(reader);
+      const unsigned char *client_pointer;
+      if (!setup_primitive(client_pointer, reader, force)) {
+        return false;
+      }
 
       _glDrawRangeElements(GL_TRIANGLES,
                            reader->get_min_vertex(),
@@ -2012,6 +2038,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2019,8 +2046,8 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle strips.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_tristrips(const GeomPrimitivePipelineReader *reader) {
+bool CLP(GraphicsStateGuardian)::
+draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 
   report_my_gl_errors();
@@ -2045,7 +2072,10 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
       _vertices_tristrip_pcollector.add_level(num_vertices);
       _primitive_batches_tristrip_pcollector.add_level(1);
       if (reader->is_indexed()) {
-        const unsigned char *client_pointer = setup_primitive(reader);
+        const unsigned char *client_pointer;
+        if (!setup_primitive(client_pointer, reader, force)) {
+          return false;
+        }
         _glDrawRangeElements(GL_TRIANGLE_STRIP,
                              reader->get_min_vertex(),
                              reader->get_max_vertex(),
@@ -2065,12 +2095,15 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 
       _primitive_batches_tristrip_pcollector.add_level(ends.size());
       if (reader->is_indexed()) {
-        const unsigned char *client_pointer = setup_primitive(reader);
+        const unsigned char *client_pointer;
+        if (!setup_primitive(client_pointer, reader, force)) {
+          return false;
+        }
         int index_stride = reader->get_index_stride();
         GeomVertexReader mins(reader->get_mins(), 0);
         GeomVertexReader maxs(reader->get_maxs(), 0);
-        nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-                 reader->get_maxs()->get_num_rows() == (int)ends.size());
+        nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+                 reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
         unsigned int start = 0;
         for (size_t i = 0; i < ends.size(); i++) {
@@ -2096,6 +2129,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2103,8 +2137,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of triangle fans.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_trifans(const GeomPrimitivePipelineReader *reader) {
+bool CLP(GraphicsStateGuardian)::
+draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
@@ -2124,12 +2158,15 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 
     _primitive_batches_trifan_pcollector.add_level(ends.size());
     if (reader->is_indexed()) {
-      const unsigned char *client_pointer = setup_primitive(reader);
+      const unsigned char *client_pointer;
+      if (!setup_primitive(client_pointer, reader, force)) {
+        return false;
+      }
       int index_stride = reader->get_index_stride();
       GeomVertexReader mins(reader->get_mins(), 0);
       GeomVertexReader maxs(reader->get_maxs(), 0);
-      nassertv(reader->get_mins()->get_num_rows() == (int)ends.size() &&
-               reader->get_maxs()->get_num_rows() == (int)ends.size());
+      nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
+               reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
 
       unsigned int start = 0;
       for (size_t i = 0; i < ends.size(); i++) {
@@ -2153,6 +2190,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2160,8 +2198,8 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected line segments.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_lines(const GeomPrimitivePipelineReader *reader) {
+bool CLP(GraphicsStateGuardian)::
+draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
@@ -2180,7 +2218,10 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
     _primitive_batches_other_pcollector.add_level(1);
 
     if (reader->is_indexed()) {
-      const unsigned char *client_pointer = setup_primitive(reader);
+      const unsigned char *client_pointer;
+      if (!setup_primitive(client_pointer, reader, force)) {
+        return false;
+      }
       _glDrawRangeElements(GL_LINES,
                            reader->get_min_vertex(),
                            reader->get_max_vertex(),
@@ -2195,6 +2236,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2202,15 +2244,9 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of line strips.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_linestrips(const GeomPrimitivePipelineReader *reader) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
-#ifndef NDEBUG
-  if (GLCAT.is_spam()) {
-    GLCAT.spam() << "draw_linestrips: " << *(reader->get_object()) << "\n";
-  }
-#endif  // NDEBUG
-
+bool CLP(GraphicsStateGuardian)::
+draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2218,8 +2254,8 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader) {
 //       Access: Public, Virtual
 //  Description: Draws a series of disconnected points.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-draw_points(const GeomPrimitivePipelineReader *reader) {
+bool CLP(GraphicsStateGuardian)::
+draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
   PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
@@ -2238,7 +2274,10 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
     _primitive_batches_other_pcollector.add_level(1);
 
     if (reader->is_indexed()) {
-      const unsigned char *client_pointer = setup_primitive(reader);
+      const unsigned char *client_pointer;
+      if (!setup_primitive(client_pointer, reader, force)) {
+        return false;
+      }
       _glDrawRangeElements(GL_POINTS,
                            reader->get_min_vertex(),
                            reader->get_max_vertex(),
@@ -2253,6 +2292,7 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2716,11 +2756,11 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
 //  Description: Makes the data the currently available data for
 //               rendering.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
+bool CLP(GraphicsStateGuardian)::
 apply_vertex_buffer(VertexBufferContext *vbc,
-                    const GeomVertexArrayDataHandle *reader) {
-  nassertv(_supports_buffers);
-  nassertv(reader->get_modified() != UpdateSeq::initial());
+                    const GeomVertexArrayDataHandle *reader, bool force) {
+  nassertr(_supports_buffers, false);
+  nassertr(reader->get_modified() != UpdateSeq::initial(), false);
 
   CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
 
@@ -2743,14 +2783,17 @@ apply_vertex_buffer(VertexBufferContext *vbc,
         << " bytes into vertex buffer " << gvbc->_index << "\n";
     }
     if (num_bytes != 0) {
+      const unsigned char *client_pointer = reader->get_read_pointer(force);
+      if (client_pointer == NULL) {
+        return false;
+      }
+
       if (gvbc->changed_size(reader) || gvbc->changed_usage_hint(reader)) {
-        _glBufferData(GL_ARRAY_BUFFER, num_bytes,
-                      reader->get_read_pointer(true),
+        _glBufferData(GL_ARRAY_BUFFER, num_bytes, client_pointer,
                       get_usage(reader->get_usage_hint()));
 
       } else {
-        _glBufferSubData(GL_ARRAY_BUFFER, 0, num_bytes,
-                         reader->get_read_pointer(true));
+        _glBufferSubData(GL_ARRAY_BUFFER, 0, num_bytes, client_pointer);
       }
       _data_transferred_pcollector.add_level(num_bytes);
     }
@@ -2759,6 +2802,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2809,17 +2853,24 @@ release_vertex_buffer(VertexBufferContext *vbc) {
 //               buffer object if it should be rendered from client
 //               memory.
 //
-//               If the buffer object is bound, this function returns
-//               NULL (representing the start of the buffer object in
-//               server memory); if the buffer object is not bound,
-//               this function returns the pointer to the data array
-//               in client memory, that is, the data array passed in.
-////////////////////////////////////////////////////////////////////
-const unsigned char *CLP(GraphicsStateGuardian)::
-setup_array_data(const GeomVertexArrayDataHandle *array_reader) {
+//               If the buffer object is bound, this function sets
+//               client_pointer to NULL (representing the start of the
+//               buffer object in server memory); if the buffer object
+//               is not bound, this function sets client_pointer the
+//               pointer to the data array in client memory, that is,
+//               the data array passed in.
+//
+//               If force is not true, the function may return false
+//               indicating the data is not currently available.
+////////////////////////////////////////////////////////////////////
+bool CLP(GraphicsStateGuardian)::
+setup_array_data(const unsigned char *&client_pointer,
+                 const GeomVertexArrayDataHandle *array_reader,
+                 bool force) {
   if (!_supports_buffers) {
     // No support for buffer objects; always render from client.
-    return array_reader->get_read_pointer(true);
+    client_pointer = array_reader->get_read_pointer(force);
+    return (client_pointer != NULL);
   }
   if (!vertex_buffers || _geom_display_list != 0 ||
       array_reader->get_usage_hint() == Geom::UH_client) {
@@ -2833,16 +2884,20 @@ setup_array_data(const GeomVertexArrayDataHandle *array_reader) {
       _glBindBuffer(GL_ARRAY_BUFFER, 0);
       _current_vbuffer_index = 0;
     }
-    return array_reader->get_read_pointer(true);
+    client_pointer = array_reader->get_read_pointer(force);
+    return (client_pointer != NULL);
   }
 
   // Prepare the buffer object and bind it.
   VertexBufferContext *vbc = ((GeomVertexArrayData *)array_reader->get_object())->prepare_now(get_prepared_objects(), this);
-  nassertr(vbc != (VertexBufferContext *)NULL, array_reader->get_read_pointer(true));
-  apply_vertex_buffer(vbc, array_reader);
+  nassertr(vbc != (VertexBufferContext *)NULL, false);
+  if (!apply_vertex_buffer(vbc, array_reader, force)) {
+    return false;
+  }
 
   // NULL is the OpenGL convention for the first byte of the buffer object.
-  return NULL;
+  client_pointer = NULL;
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2885,11 +2940,12 @@ prepare_index_buffer(GeomPrimitive *data) {
 //  Description: Makes the data the currently available data for
 //               rendering.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
+bool CLP(GraphicsStateGuardian)::
 apply_index_buffer(IndexBufferContext *ibc,
-                   const GeomPrimitivePipelineReader *reader) {
-  nassertv(_supports_buffers);
-  nassertv(reader->get_modified() != UpdateSeq::initial());
+                   const GeomPrimitivePipelineReader *reader,
+                   bool force) {
+  nassertr(_supports_buffers, false);
+  nassertr(reader->get_modified() != UpdateSeq::initial(), false);
 
   CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc);
 
@@ -2913,14 +2969,18 @@ apply_index_buffer(IndexBufferContext *ibc,
         << " bytes into index buffer " << gibc->_index << "\n";
     }
     if (num_bytes != 0) {
+      const unsigned char *client_pointer = reader->get_read_pointer(force);
+      if (client_pointer == NULL) {
+        return false;
+      }
+
       if (gibc->changed_size(reader) || gibc->changed_usage_hint(reader)) {
-        _glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_bytes,
-                      reader->get_read_pointer(true),
+        _glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_bytes, client_pointer,
                       get_usage(reader->get_usage_hint()));
 
       } else {
         _glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, num_bytes,
-                         reader->get_read_pointer(true));
+                         client_pointer);
       }
       _data_transferred_pcollector.add_level(num_bytes);
     }
@@ -2928,6 +2988,7 @@ apply_index_buffer(IndexBufferContext *ibc,
   }
 
   report_my_gl_errors();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2978,17 +3039,24 @@ release_index_buffer(IndexBufferContext *ibc) {
 //               to unbind a buffer object if it should be rendered
 //               from client memory.
 //
-//               If the buffer object is bound, this function returns
-//               NULL (reprsenting the start of the buffer object in
-//               server memory); if the buffer object is not bound,
-//               this function returns the pointer to the data array
-//               in client memory, that is, the data array passed in.
-////////////////////////////////////////////////////////////////////
-const unsigned char *CLP(GraphicsStateGuardian)::
-setup_primitive(const GeomPrimitivePipelineReader *reader) {
+//               If the buffer object is bound, this function sets
+//               client_pointer to NULL (representing the start of the
+//               buffer object in server memory); if the buffer object
+//               is not bound, this function sets client_pointer to to
+//               the data array in client memory, that is, the data
+//               array passed in.
+//
+//               If force is not true, the function may return false
+//               indicating the data is not currently available.
+////////////////////////////////////////////////////////////////////
+bool CLP(GraphicsStateGuardian)::
+setup_primitive(const unsigned char *&client_pointer,
+                const GeomPrimitivePipelineReader *reader,
+                bool force) {
   if (!_supports_buffers) {
     // No support for buffer objects; always render from client.
-    return reader->get_read_pointer(true);
+    client_pointer = reader->get_read_pointer(force);
+    return (client_pointer != NULL);
   }
   if (!vertex_buffers || _geom_display_list != 0 ||
       reader->get_usage_hint() == Geom::UH_client) {
@@ -3002,16 +3070,20 @@ setup_primitive(const GeomPrimitivePipelineReader *reader) {
       _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
       _current_ibuffer_index = 0;
     }
-    return reader->get_read_pointer(true);
+    client_pointer = reader->get_read_pointer(force);
+    return (client_pointer != NULL);
   }
 
   // Prepare the buffer object and bind it.
   IndexBufferContext *ibc = ((GeomPrimitive *)reader->get_object())->prepare_now(get_prepared_objects(), this);
-  nassertr(ibc != (IndexBufferContext *)NULL, reader->get_read_pointer(true));
-  apply_index_buffer(ibc, reader);
+  nassertr(ibc != (IndexBufferContext *)NULL, false);
+  if (!apply_index_buffer(ibc, reader, force)) {
+    return false;
+  }
 
   // NULL is the OpenGL convention for the first byte of the buffer object.
-  return NULL;
+  client_pointer = NULL;
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 28 - 14
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -108,13 +108,20 @@ public:
 
   virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader,
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader);
-  virtual void draw_triangles(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_tristrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_trifans(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_lines(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_linestrips(const GeomPrimitivePipelineReader *reader);
-  virtual void draw_points(const GeomPrimitivePipelineReader *reader);
+                                     const GeomVertexDataPipelineReader *data_reader,
+                                     bool force);
+  virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
+                              bool force);
+  virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
+                            bool force);
+  virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
+                          bool force);
+  virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
+                               bool force);
+  virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
+                           bool force);
   virtual void end_draw_primitives();
 
   INLINE bool draw_display_list(GeomContext *gc);
@@ -132,16 +139,23 @@ public:
   void record_deleted_display_list(GLuint index);
 
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
-  void apply_vertex_buffer(VertexBufferContext *vbc,
-                           const GeomVertexArrayDataHandle *reader);
+  bool apply_vertex_buffer(VertexBufferContext *vbc,
+                           const GeomVertexArrayDataHandle *reader,
+                           bool force);
   virtual void release_vertex_buffer(VertexBufferContext *vbc);
-  const unsigned char *setup_array_data(const GeomVertexArrayDataHandle *data);
+
+  bool setup_array_data(const unsigned char *&client_pointer,
+                        const GeomVertexArrayDataHandle *data,
+                        bool force);
 
   virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
-  void apply_index_buffer(IndexBufferContext *ibc,
-                          const GeomPrimitivePipelineReader *reader);
+  bool apply_index_buffer(IndexBufferContext *ibc,
+                          const GeomPrimitivePipelineReader *reader,
+                          bool force);
   virtual void release_index_buffer(IndexBufferContext *ibc);
-  const unsigned char *setup_primitive(const GeomPrimitivePipelineReader *reader);
+  bool setup_primitive(const unsigned char *&client_pointer,
+                       const GeomPrimitivePipelineReader *reader,
+                       bool force);
 
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
@@ -287,7 +301,7 @@ protected:
   static GLenum get_usage(Geom::UsageHint usage_hint);
 
   void disable_standard_vertex_arrays();
-  void update_standard_vertex_arrays();
+  bool update_standard_vertex_arrays(bool force);
   void disable_standard_texture_bindings();
   void update_standard_texture_bindings();
 

+ 9 - 4
panda/src/glstuff/glShaderContext_src.cxx

@@ -204,12 +204,13 @@ disable_shader_vertex_arrays(GSG *gsg) {
 //               it may unnecessarily disable arrays then immediately
 //               reenable them.  We may optimize this someday.
 ////////////////////////////////////////////////////////////////////
-void CLP(ShaderContext)::
-update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
+bool CLP(ShaderContext)::
+update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
+                            bool force) {
   if (prev) prev->disable_shader_vertex_arrays(gsg);
 #ifdef HAVE_CG
   if (_cg_context == 0) {
-    return;
+    return true;
   }
 
 #ifdef SUPPORT_IMMEDIATE_MODE
@@ -242,7 +243,10 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
       if (gsg->_data_reader->get_array_info(name,
                                             array_reader, num_values, numeric_type,
                                             start, stride)) {
-        const unsigned char *client_pointer = gsg->setup_array_data(array_reader);
+        const unsigned char *client_pointer;
+        if (!gsg->setup_array_data(client_pointer, array_reader, force)) {
+          return false;
+        }
         cgGLSetParameterPointer(p,
                                 num_values, gsg->get_numeric_type(numeric_type),
                                 stride, client_pointer + start);
@@ -253,6 +257,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
     }
   }
 #endif // HAVE_CG
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/glstuff/glShaderContext_src.h

@@ -43,7 +43,8 @@ public:
   void unbind();
   void issue_parameters(GSG *gsg, bool all);
   void disable_shader_vertex_arrays(GSG *gsg);
-  void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
+  bool update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
+                                   bool force);
   void disable_shader_texture_bindings(GSG *gsg);
   void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
 

+ 20 - 8
panda/src/gobj/geom.cxx

@@ -1063,17 +1063,24 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
 //  Description: Actually draws the Geom with the indicated GSG, using
 //               the indicated vertex data (which might have been
 //               pre-munged to support the GSG's needs).
+//
+//               Returns true if all of the primitives were drawn
+//               normally, false if there was a problem (for instance,
+//               some of the data was nonresident).  If force is
+//               passed true, it will wait for the data to become
+//               resident if necessary.
 ////////////////////////////////////////////////////////////////////
-void Geom::
+bool Geom::
 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
-     const GeomVertexData *vertex_data, Thread *current_thread) const {
+     const GeomVertexData *vertex_data, bool force,
+     Thread *current_thread) const {
   GeomPipelineReader geom_reader(this, current_thread);
   geom_reader.check_usage_hint();
 
   GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
   data_reader.check_array_readers();
 
-  geom_reader.draw(gsg, munger, &data_reader);
+  return geom_reader.draw(gsg, munger, &data_reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1611,11 +1618,12 @@ check_valid(const GeomVertexDataPipelineReader *data_reader) const {
 //       Access: Public
 //  Description: The implementation of Geom::draw().
 ////////////////////////////////////////////////////////////////////
-void GeomPipelineReader::
+bool GeomPipelineReader::
 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
-     const GeomVertexDataPipelineReader *data_reader) const {
+     const GeomVertexDataPipelineReader *data_reader, bool force) const {
   PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
-  if (gsg->begin_draw_primitives(this, munger, data_reader)) {
+  bool all_ok = gsg->begin_draw_primitives(this, munger, data_reader, force);
+  if (all_ok) {
     Geom::Primitives::const_iterator pi;
     for (pi = _cdata->_primitives.begin(); 
          pi != _cdata->_primitives.end();
@@ -1624,10 +1632,14 @@ draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
       GeomPrimitivePipelineReader reader(primitive, _current_thread);
       if (reader.get_num_vertices() != 0) {
         reader.check_minmax();
-        nassertv(reader.check_valid(data_reader));
-        primitive->draw(gsg, &reader);
+        nassertr(reader.check_valid(data_reader), false);
+        if (!primitive->draw(gsg, &reader, force)) {
+          all_ok = false;
+        }
       }
     }
     gsg->end_draw_primitives();
   }
+
+  return all_ok;
 }

+ 5 - 4
panda/src/gobj/geom.h

@@ -137,10 +137,10 @@ PUBLISHED:
                            GraphicsStateGuardianBase *gsg);
 
 public:
-  void draw(GraphicsStateGuardianBase *gsg, 
+  bool draw(GraphicsStateGuardianBase *gsg, 
             const GeomMunger *munger,
             const GeomVertexData *vertex_data,
-            Thread *current_thread) const;
+            bool force, Thread *current_thread) const;
 
   INLINE void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
 				bool &found_any, 
@@ -396,8 +396,9 @@ public:
 
   bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
 
-  void draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
-            const GeomVertexDataPipelineReader *data_reader) const;
+  bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
+            const GeomVertexDataPipelineReader *data_reader,
+            bool force) const;
 
 private:
   CPT(Geom) _object;

+ 4 - 3
panda/src/gobj/geomLines.cxx

@@ -116,9 +116,10 @@ get_min_num_vertices_per_primitive() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomLines::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_lines(reader);
+bool GeomLines::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_lines(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomLines.h

@@ -40,8 +40,9 @@ public:
   virtual int get_min_num_vertices_per_primitive() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 protected:
   virtual CPT(GeomVertexArrayData) rotate_impl() const;

+ 4 - 3
panda/src/gobj/geomLinestrips.cxx

@@ -116,9 +116,10 @@ get_min_num_vertices_per_primitive() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomLinestrips::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_linestrips(reader);
+bool GeomLinestrips::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_linestrips(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomLinestrips.h

@@ -39,8 +39,9 @@ public:
   virtual int get_min_num_vertices_per_primitive() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 protected:
   virtual CPT(GeomPrimitive) decompose_impl() const;

+ 4 - 3
panda/src/gobj/geomPoints.cxx

@@ -133,9 +133,10 @@ get_min_num_vertices_per_primitive() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomPoints::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_points(reader);
+bool GeomPoints::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_points(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomPoints.h

@@ -41,8 +41,9 @@ public:
   virtual int get_min_num_vertices_per_primitive() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 public:
   static void register_with_read_factory();

+ 3 - 2
panda/src/gobj/geomPrimitive.h

@@ -193,8 +193,9 @@ private:
   static int get_highest_index_value(NumericType index_type);
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const=0;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const=0;
 
   void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
                          bool &found_any, 

+ 4 - 3
panda/src/gobj/geomTriangles.cxx

@@ -104,9 +104,10 @@ get_num_vertices_per_primitive() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomTriangles::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_triangles(reader);
+bool GeomTriangles::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_triangles(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomTriangles.h

@@ -39,8 +39,9 @@ public:
   virtual int get_num_vertices_per_primitive() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 protected:
   virtual CPT(GeomVertexArrayData) rotate_impl() const;

+ 4 - 3
panda/src/gobj/geomTrifans.cxx

@@ -104,9 +104,10 @@ get_geom_rendering() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomTrifans::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_trifans(reader);
+bool GeomTrifans::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_trifans(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomTrifans.h

@@ -38,8 +38,9 @@ public:
   virtual int get_geom_rendering() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 protected:
   virtual CPT(GeomPrimitive) decompose_impl() const;

+ 4 - 3
panda/src/gobj/geomTristrips.cxx

@@ -119,9 +119,10 @@ get_num_unused_vertices_per_primitive() const {
 //  Description: Calls the appropriate method on the GSG to draw the
 //               primitive.
 ////////////////////////////////////////////////////////////////////
-void GeomTristrips::
-draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader) const {
-  gsg->draw_tristrips(reader);
+bool GeomTristrips::
+draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
+     bool force) const {
+  return gsg->draw_tristrips(reader, force);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/gobj/geomTristrips.h

@@ -39,8 +39,9 @@ public:
   virtual int get_num_unused_vertices_per_primitive() const;
 
 public:
-  virtual void draw(GraphicsStateGuardianBase *gsg,
-                    const GeomPrimitivePipelineReader *reader) const;
+  virtual bool draw(GraphicsStateGuardianBase *gsg,
+                    const GeomPrimitivePipelineReader *reader,
+                    bool force) const;
 
 protected:
   virtual CPT(GeomPrimitive) decompose_impl() const;

+ 15 - 1
panda/src/gobj/geomVertexArrayData.I

@@ -157,7 +157,7 @@ get_modified() const {
 INLINE bool GeomVertexArrayData::
 request_resident() const {
   CPT(GeomVertexArrayDataHandle) handle = get_handle();
-  return (handle->get_read_pointer(false) != (const unsigned char *)NULL);
+  return handle->request_resident();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -458,6 +458,20 @@ get_modified() const {
   return _cdata->_modified;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexArrayData::request_resident
+//       Access: Published
+//  Description: Returns true if the vertex data is currently resident
+//               in memory.  If this returns true, the next call to
+//               get_handle()->get_read_pointer() will probably not
+//               block.  If this returns false, the vertex data will
+//               be brought back into memory shortly; try again later.
+////////////////////////////////////////////////////////////////////
+INLINE bool GeomVertexArrayDataHandle::
+request_resident() const {
+  return (get_read_pointer(false) != (const unsigned char *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_data
 //       Access: Published

+ 2 - 0
panda/src/gobj/geomVertexArrayData.h

@@ -275,6 +275,8 @@ PUBLISHED:
   INLINE int get_data_size_bytes() const;
   INLINE UpdateSeq get_modified() const;
 
+  INLINE bool request_resident() const;
+
   void copy_data_from(const GeomVertexArrayDataHandle *other);
   void copy_subdata_from(size_t to_start, size_t to_size,
                          const GeomVertexArrayDataHandle *other,

+ 8 - 7
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -183,13 +183,14 @@ public:
 
   virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, 
                                      const GeomMunger *munger,
-                                     const GeomVertexDataPipelineReader *data_reader)=0;
-  virtual void draw_triangles(const GeomPrimitivePipelineReader *reader)=0;
-  virtual void draw_tristrips(const GeomPrimitivePipelineReader *reader)=0;
-  virtual void draw_trifans(const GeomPrimitivePipelineReader *reader)=0;
-  virtual void draw_lines(const GeomPrimitivePipelineReader *reader)=0;
-  virtual void draw_linestrips(const GeomPrimitivePipelineReader *reader)=0;
-  virtual void draw_points(const GeomPrimitivePipelineReader *reader)=0;
+                                     const GeomVertexDataPipelineReader *data_reader, 
+                                     bool force)=0;
+  virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)=0;
+  virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
+  virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, bool force)=0;
+  virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)=0;
+  virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
+  virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)=0;
   virtual void end_draw_primitives()=0;
 
   virtual void framebuffer_copy_to_texture

+ 1 - 1
panda/src/pgraph/cullBin.h

@@ -58,7 +58,7 @@ public:
   virtual void add_object(CullableObject *object, Thread *current_thread)=0;
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
 
-  virtual void draw(Thread *current_thread)=0;
+  virtual void draw(bool force, Thread *current_thread)=0;
 
   INLINE bool has_flash_color() const;
   INLINE const Colorf &get_flash_color() const;

+ 3 - 3
panda/src/pgraph/cullHandler.I

@@ -26,11 +26,11 @@
 ////////////////////////////////////////////////////////////////////
 INLINE void CullHandler::
 draw(CullableObject *object, GraphicsStateGuardianBase *gsg,
-     Thread *current_thread) {
+     bool force, Thread *current_thread) {
   if (object->_next != (CullableObject *)NULL) {
-    draw_with_decals(object, gsg, current_thread);
+    draw_with_decals(object, gsg, force, current_thread);
   } else {
     gsg->set_state_and_transform(object->_state, object->_internal_transform);
-    object->draw(gsg, current_thread);
+    object->draw(gsg, force, current_thread);
   }
 }

+ 4 - 4
panda/src/pgraph/cullHandler.cxx

@@ -58,7 +58,7 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
 ////////////////////////////////////////////////////////////////////
 void CullHandler::
 draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg,
-                 Thread *current_thread) {
+                 bool force, Thread *current_thread) {
   // We draw with a three-step process.
 
   // First, render all of the base geometry for the first pass.
@@ -67,7 +67,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg,
   CullableObject *base = object;
   while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
     gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
-    base->draw(gsg, current_thread);
+    base->draw(gsg, force, current_thread);
     
     base = base->_next;
   }
@@ -79,7 +79,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg,
     CullableObject *decal = base->_next;
     while (decal != (CullableObject *)NULL) {
       gsg->set_state_and_transform(decal->_state->compose(state), decal->_internal_transform);
-      decal->draw(gsg, current_thread);
+      decal->draw(gsg, force, current_thread);
       decal = decal->_next;
     }
   }
@@ -90,7 +90,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg,
     base = object;
     while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
       gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
-      base->draw(gsg, current_thread);
+      base->draw(gsg, force, current_thread);
       
       base = base->_next;
     }

+ 2 - 2
panda/src/pgraph/cullHandler.h

@@ -41,10 +41,10 @@ public:
 
   INLINE static void draw(CullableObject *object,
                           GraphicsStateGuardianBase *gsg,
-                          Thread *current_thread);
+                          bool force, Thread *current_thread);
   static void draw_with_decals(CullableObject *object,
                                GraphicsStateGuardianBase *gsg,
-                               Thread *current_thread);
+                               bool force, Thread *current_thread);
 };
 
 #include "cullHandler.I"

+ 9 - 7
panda/src/pgraph/cullResult.cxx

@@ -176,9 +176,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
 #ifndef NDEBUG
                 check_flash_bin(transparent_part->_state, bin);
 #endif
-                if (force || transparent_part->request_resident()) {
-                  bin->add_object(transparent_part, current_thread);
-                }
+                bin->add_object(transparent_part, current_thread);
               }
             }
           
@@ -213,9 +211,11 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
   // Munge vertices as needed for the GSG's requirements, and the
   // object's current state.
   if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
-    if (force || object->request_resident()) {
-      bin->add_object(object, current_thread);
-    }
+    // The object may or may not now be fully resident, but this may
+    // not matter, since the GSG may have the necessary buffers
+    // already loaded.  We'll let the GSG ultimately decide whether to
+    // render it.
+    bin->add_object(object, current_thread);
   }
 }
 
@@ -255,6 +255,8 @@ finish_cull(SceneSetup *scene_setup, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 void CullResult::
 draw(Thread *current_thread) {
+  bool force = !allow_incomplete_render;
+
   // Ask the bin manager for the correct order to draw all the bins.
   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
   int num_bins = bin_manager->get_num_bins();
@@ -263,7 +265,7 @@ draw(Thread *current_thread) {
     nassertv(bin_index >= 0);
 
     if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
-      _bins[bin_index]->draw(current_thread);
+      _bins[bin_index]->draw(force, current_thread);
     }
   }
 }

+ 2 - 2
panda/src/pgraph/cullableObject.I

@@ -126,8 +126,8 @@ has_decals() const {
 //               from the draw thread.
 ////////////////////////////////////////////////////////////////////
 INLINE void CullableObject::
-draw(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
-  _geom->draw(gsg, _munger, _munged_data, current_thread);
+draw(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread) {
+  _geom->draw(gsg, _munger, _munged_data, force, current_thread);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/pgraph/cullableObject.h

@@ -65,7 +65,7 @@ public:
                   GeomMunger *munger, const CullTraverser *traverser,
                   bool force);
   INLINE void draw(GraphicsStateGuardianBase *gsg,
-                   Thread *current_thread);
+                   bool force, Thread *current_thread);
 
   INLINE bool request_resident() const;
   INLINE static void flush_level();