Browse Source

support paged vertices in tinydisplay

David Rose 17 years ago
parent
commit
229a47528c

+ 1 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -1383,7 +1383,7 @@ bool GraphicsStateGuardian::
 begin_draw_primitives(const GeomPipelineReader *geom_reader,
                       const GeomMunger *munger,
                       const GeomVertexDataPipelineReader *data_reader,
-                      bool) {
+                      bool force) {
   _munger = munger;
   _data_reader = data_reader;
   return _data_reader->has_vertex();

+ 54 - 6
panda/src/gobj/geomVertexReader.I

@@ -119,11 +119,12 @@ GeomVertexReader(const GeomVertexArrayData *array_data, int column,
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexDataPipelineReader *data_reader,
-                 const InternalName *name) :
+                 const InternalName *name, bool force) :
   _vertex_data(data_reader->get_object()),
   _current_thread(data_reader->get_current_thread())
 {
   initialize();
+  _force = force;
   const GeomVertexFormat *format = data_reader->get_format();
   set_vertex_column(format->get_array_with(name),
                     format->get_column(name),
@@ -147,7 +148,8 @@ GeomVertexReader(const GeomVertexReader &copy) :
   _pointer_begin(copy._pointer_begin),
   _pointer_end(copy._pointer_end),
   _pointer(copy._pointer),
-  _start_row(copy._start_row)
+  _start_row(copy._start_row),
+  _force(copy._force)
 {
 }
 
@@ -169,6 +171,7 @@ operator = (const GeomVertexReader &copy) {
   _pointer_end = copy._pointer_end;
   _pointer = copy._pointer;
   _start_row = copy._start_row;
+  _force = copy._force;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -214,6 +217,38 @@ get_current_thread() const {
   return _current_thread;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexReader::set_force
+//       Access: Published
+//  Description: Sets the value of the force flag.  When this is true
+//               (the default), vertex data will be paged in from disk
+//               if necessary.  When this is false, the GeomVertexData
+//               will simply return a failure code when attempting to
+//               read vertex data that is not resident (but will put
+//               it on the queue to become resident later).
+//
+//               Normally, vertex data is always resident, so this
+//               will not be an issue.  It is only possible for vertex
+//               data to be nonresident if you have enabled vertex
+//               paging via the GeomVertexArrayData and VertexDataPage
+//               interfaces.
+////////////////////////////////////////////////////////////////////
+INLINE void GeomVertexReader::
+set_force(bool force) {
+  _force = force;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexReader::get_force
+//       Access: Published
+//  Description: Returns the value of the force flag.  See
+//               set_force().
+////////////////////////////////////////////////////////////////////
+INLINE bool GeomVertexReader::
+get_force() const {
+  return _force;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexReader::set_column
 //       Access: Published
@@ -306,7 +341,8 @@ clear() {
 //       Access: Published
 //  Description: Returns true if a valid data type has been
 //               successfully set, or false if the data type does not
-//               exist.
+//               exist (or if get_force() is false and the vertex data
+//               is nonresident).
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexReader::
 has_column() const {
@@ -511,12 +547,24 @@ get_packer() const {
 //  Description: Sets up the array pointers freshly from the source
 //               object (in case they have been reallocated recently),
 //               and sets the internal pointer to the indicated row.
+//
+//               Returns true if successful, or false if the vertex
+//               data is not resident.  If it returns false, the
+//               reader's internal column spec is cleared.  It is only
+//               possible to return false if get_force() is false.
 ////////////////////////////////////////////////////////////////////
-INLINE void GeomVertexReader::
+INLINE bool GeomVertexReader::
 set_pointer(int row) {
-  _pointer_begin = _handle->get_read_pointer(true);
+  _pointer_begin = _handle->get_read_pointer(_force);
+  if (_pointer_begin == NULL) {
+    // Vertex data is not resident.
+    set_column(0, NULL);
+    return false;
+  }
+
   _pointer_end = _pointer_begin + _handle->get_data_size_bytes();
   quick_set_pointer(row);
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -528,7 +576,7 @@ set_pointer(int row) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexReader::
 quick_set_pointer(int row) {
-  nassertv(has_column());
+  nassertv(has_column() && _pointer_begin != NULL);
 
 #if defined(_DEBUG)
   // Make sure we still have the same pointer as stored in the array.

+ 3 - 6
panda/src/gobj/geomVertexReader.cxx

@@ -92,6 +92,7 @@ initialize() {
   _pointer_end = NULL;
   _pointer = NULL;
   _start_row = 0;
+  _force = true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -120,9 +121,7 @@ set_vertex_column(int array, const GeomVertexColumn *column,
   _stride = _handle->get_array_format()->get_stride();
 
   _packer = column->_packer;
-  set_pointer(_start_row);
-  
-  return true;
+  return set_pointer(_start_row);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -144,7 +143,5 @@ set_array_column(const GeomVertexColumn *column) {
   _stride = _handle->get_array_format()->get_stride();
 
   _packer = column->_packer;
-  set_pointer(_start_row);
-  
-  return true;
+  return set_pointer(_start_row);
 }

+ 7 - 2
panda/src/gobj/geomVertexReader.h

@@ -72,7 +72,8 @@ PUBLISHED:
 
 public:
   INLINE GeomVertexReader(const GeomVertexDataPipelineReader *data_reader,
-                          const InternalName *name);
+                          const InternalName *name,
+                          bool force = true);
 
 PUBLISHED:
   INLINE GeomVertexReader(const GeomVertexReader &copy);
@@ -83,6 +84,9 @@ PUBLISHED:
   INLINE const GeomVertexArrayData *get_array_data() const;
   INLINE Thread *get_current_thread() const;
 
+  INLINE void set_force(bool force);
+  INLINE bool get_force() const;
+
   INLINE bool set_column(int column);
   INLINE bool set_column(const string &name);
   INLINE bool set_column(const InternalName *name);
@@ -117,7 +121,7 @@ protected:
 private:
   void initialize();
 
-  INLINE void set_pointer(int row);
+  INLINE bool set_pointer(int row);
   INLINE void quick_set_pointer(int row);
   INLINE const unsigned char *inc_pointer();
 
@@ -144,6 +148,7 @@ private:
   const unsigned char *_pointer;
 
   int _start_row;
+  bool _force;
 
 #ifndef NDEBUG
   // This is defined just for the benefit of having something non-NULL

+ 26 - 12
panda/src/gobj/vertexDataSaveFile.cxx

@@ -199,20 +199,24 @@ write_data(const unsigned char *data, size_t size, bool compressed) {
     memset(&overlapped, 0, sizeof(overlapped));
     overlapped.Offset = block->get_start();
 
-    WriteFile(_handle, data, size, NULL, &overlapped);
-    DWORD bytes_written;
-    while (!GetOverlappedResult(_handle, &overlapped, &bytes_written, false)) {
-      if (GetLastError() == ERROR_IO_INCOMPLETE) {
+    DWORD bytes_written = 0;
+    BOOL success = WriteFile(_handle, data, size, &bytes_written, &overlapped);
+    while (!success) {
+      DWORD error = GetLastError();
+      if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
         // Wait for more later.
         Thread::force_yield();
       } else {
         gobj_cat.error()
-          << "Error writing " << size << " bytes to save file.  Disk full?\n";
+          << "Error writing " << size
+          << " bytes to save file, windows error code 0x" << hex
+          << error << dec << ".  Disk full?\n";
         return NULL;
       }
+      success = GetOverlappedResult(_handle, &overlapped, &bytes_written, false);
     }
     nassertr(bytes_written == size, NULL);
-
+    
 #else
     // Posix case.
     if (lseek(_fd, block->get_start(), SEEK_SET) == -1) {
@@ -259,25 +263,35 @@ read_data(unsigned char *data, size_t size, VertexDataSaveBlock *block) {
 
   nassertr(size == block->get_size(), false);
 
+  /*
+  static ConfigVariableBool allow_mainthread_read("allow-mainthread-read", 1);
+  if (!allow_mainthread_read) {
+    nassertr(Thread::get_current_thread() != Thread::get_main_thread(), false);
+  }
+  */
+
 #ifdef _WIN32
   OVERLAPPED overlapped;
   memset(&overlapped, 0, sizeof(overlapped));
   overlapped.Offset = block->get_start();
 
-  ReadFile(_handle, data, size, NULL, &overlapped);
-  DWORD bytes_read;
-  while (!GetOverlappedResult(_handle, &overlapped, &bytes_read, false)) {
-    if (GetLastError() == ERROR_IO_INCOMPLETE) {
+  DWORD bytes_read = 0;
+  BOOL success = ReadFile(_handle, data, size, &bytes_read, &overlapped);
+  while (!success) {
+    DWORD error = GetLastError();
+    if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
       // Wait for more later.
       Thread::force_yield();
     } else {
       gobj_cat.error()
-        << "Error reading " << size << " bytes from save file.\n";
+        << "Error reading " << size
+        << " bytes from save file, windows error code 0x" << hex
+        << error << dec << ".\n";
       return NULL;
     }
+    success = GetOverlappedResult(_handle, &overlapped, &bytes_read, false);
   }
   nassertr(bytes_read == size, NULL);
-  
 #else
   // Posix case.
   if (lseek(_fd, block->get_start(), SEEK_SET) == -1) {

+ 10 - 4
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -548,7 +548,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
   int max_stage_index = _effective_texture->get_num_on_ff_stages();
   if (max_stage_index > 0) {
     TextureStage *stage = _effective_texture->get_on_ff_stage(0);
-    rtexcoord = GeomVertexReader(data_reader, stage->get_texcoord_name());
+    rtexcoord = GeomVertexReader(data_reader, stage->get_texcoord_name(),
+                                 force);
     rtexcoord.set_row(_min_vertex);
     needs_texcoord = rtexcoord.has_column();
 
@@ -560,7 +561,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 
   bool needs_color = false;
   if (_vertex_colors_enabled) {
-    rcolor = GeomVertexReader(data_reader, InternalName::get_color());
+    rcolor = GeomVertexReader(data_reader, InternalName::get_color(), force);
     rcolor.set_row(_min_vertex);
     needs_color = rcolor.has_column();
   }
@@ -576,14 +577,19 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 
   bool needs_normal = false;
   if (_c->lighting_enabled) {
-    rnormal = GeomVertexReader(data_reader, InternalName::get_normal());
+    rnormal = GeomVertexReader(data_reader, InternalName::get_normal(), force);
     rnormal.set_row(_min_vertex);
     needs_normal = rnormal.has_column();
   }
 
-  GeomVertexReader rvertex(data_reader, InternalName::get_vertex()); 
+  GeomVertexReader rvertex(data_reader, InternalName::get_vertex(), force); 
   rvertex.set_row(_min_vertex);
 
+  if (!rvertex.has_column()) {
+    // Whoops, guess the vertex data isn't resident.
+    return false;
+  }
+
   if (!needs_color && _color_material_flags) {
     if (_color_material_flags & CMF_ambient) {
       _c->materials[0].ambient = _c->current_color;