From 229a47528c1b9d40abdb4cdda2732c773ec2fe9a Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 9 Jul 2008 21:31:50 +0000 Subject: [PATCH] support paged vertices in tinydisplay --- panda/src/display/graphicsStateGuardian.cxx | 2 +- panda/src/gobj/geomVertexReader.I | 60 +++++++++++++++++-- panda/src/gobj/geomVertexReader.cxx | 9 +-- panda/src/gobj/geomVertexReader.h | 9 ++- panda/src/gobj/vertexDataSaveFile.cxx | 38 ++++++++---- .../tinydisplay/tinyGraphicsStateGuardian.cxx | 14 +++-- 6 files changed, 101 insertions(+), 31 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index d71d27d13c..20a6334eeb 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/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(); diff --git a/panda/src/gobj/geomVertexReader.I b/panda/src/gobj/geomVertexReader.I index 0d5d9efb12..5e76294fe9 100644 --- a/panda/src/gobj/geomVertexReader.I +++ b/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 ©) : _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 ©) { _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. diff --git a/panda/src/gobj/geomVertexReader.cxx b/panda/src/gobj/geomVertexReader.cxx index d3e53f0cfe..2920342ffd 100644 --- a/panda/src/gobj/geomVertexReader.cxx +++ b/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); } diff --git a/panda/src/gobj/geomVertexReader.h b/panda/src/gobj/geomVertexReader.h index b701775e29..c2cdb9b28e 100644 --- a/panda/src/gobj/geomVertexReader.h +++ b/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 ©); @@ -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 diff --git a/panda/src/gobj/vertexDataSaveFile.cxx b/panda/src/gobj/vertexDataSaveFile.cxx index 89933f230c..16c3275ecb 100644 --- a/panda/src/gobj/vertexDataSaveFile.cxx +++ b/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) { diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index 0fe2bfcb54..94a9995868 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/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;