support paged vertices in tinydisplay

This commit is contained in:
David Rose 2008-07-09 21:31:50 +00:00
parent b172f6ec50
commit 229a47528c
6 changed files with 101 additions and 31 deletions

View File

@ -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();

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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) {

View File

@ -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;