ibuffers as well as vbuffers

This commit is contained in:
David Rose 2005-03-18 20:18:57 +00:00
parent 7a305f825f
commit dbed74e410
54 changed files with 1380 additions and 407 deletions

View File

@ -20,7 +20,8 @@
#include "graphicsStateGuardian.h"
#include "config_display.h"
#include "textureContext.h"
#include "dataContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
#include "renderBuffer.h"
#include "colorAttrib.h"
#include "colorScaleAttrib.h"
@ -48,7 +49,8 @@ PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage
PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffers");
PStatCollector GraphicsStateGuardian::_active_buffers_pcollector("Vertex buffers:Active");
PStatCollector GraphicsStateGuardian::_active_vertex_buffers_pcollector("Vertex buffers:Active vertex");
PStatCollector GraphicsStateGuardian::_active_index_buffers_pcollector("Vertex buffers:Active index");
PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes");
PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active");
PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory");
@ -271,25 +273,47 @@ release_geom(GeomContext *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::prepare_data
// Function: GraphicsStateGuardian::prepare_vertex_buffer
// Access: Public, Virtual
// Description: Prepares the indicated data array for retained-mode
// Description: Prepares the indicated buffer for retained-mode
// rendering.
////////////////////////////////////////////////////////////////////
DataContext *GraphicsStateGuardian::
prepare_data(qpGeomVertexArrayData *) {
return (DataContext *)NULL;
VertexBufferContext *GraphicsStateGuardian::
prepare_vertex_buffer(qpGeomVertexArrayData *) {
return (VertexBufferContext *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::release_data
// Function: GraphicsStateGuardian::release_vertex_buffer
// Access: Public, Virtual
// Description: Frees the resources previously allocated via a call
// to prepare_data(), including deleting the DataContext
// itself, if necessary.
// to prepare_data(), including deleting the
// VertexBufferContext itself, if necessary.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
release_data(DataContext *) {
release_vertex_buffer(VertexBufferContext *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::prepare_index_buffer
// Access: Public, Virtual
// Description: Prepares the indicated buffer for retained-mode
// rendering.
////////////////////////////////////////////////////////////////////
IndexBufferContext *GraphicsStateGuardian::
prepare_index_buffer(qpGeomPrimitive *) {
return (IndexBufferContext *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::release_index_buffer
// Access: Public, Virtual
// Description: Frees the resources previously allocated via a call
// to prepare_data(), including deleting the
// IndexBufferContext itself, if necessary.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
release_index_buffer(IndexBufferContext *) {
}
////////////////////////////////////////////////////////////////////
@ -1443,11 +1467,13 @@ init_frame_pstats() {
if (PStatClient::is_connected()) {
_current_textures.clear();
_current_geoms.clear();
_current_datas.clear();
_current_vertex_buffers.clear();
_current_index_buffers.clear();
_active_texusage_pcollector.clear_level();
_active_geom_pcollector.clear_level();
_active_geom_node_pcollector.clear_level();
_active_buffers_pcollector.clear_level();
_active_vertex_buffers_pcollector.clear_level();
_active_index_buffers_pcollector.clear_level();
// Also clear out our other counters while we're here.
_vertices_tristrip_pcollector.clear_level();
@ -1498,21 +1524,42 @@ add_to_geom_record(GeomContext *gc) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_data_record
// Function: GraphicsStateGuardian::add_to_vertex_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been drawn
// this frame. This function is only used to update the
// PStats active_buffers collector; it gets compiled out
// PStats active_vertex_buffers collector; it gets compiled out
// if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_data_record(DataContext *dc) {
if (dc != (DataContext *)NULL) {
int delta = dc->get_data()->get_num_bytes() - dc->get_num_bytes();
add_to_vertex_buffer_record(VertexBufferContext *vbc) {
if (vbc != (VertexBufferContext *)NULL) {
int delta = vbc->get_data()->get_data_size_bytes() - vbc->get_data_size_bytes();
_total_buffers_pcollector.add_level(delta);
if (PStatClient::is_connected()) {
if (_current_datas.insert(dc).second) {
_active_buffers_pcollector.add_level(dc->get_data()->get_num_bytes());
if (_current_vertex_buffers.insert(vbc).second) {
_active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes());
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_index_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been drawn
// this frame. This function is only used to update the
// PStats active_index_buffers collector; it gets compiled out
// if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_index_buffer_record(IndexBufferContext *ibc) {
if (ibc != (IndexBufferContext *)NULL) {
int delta = ibc->get_data()->get_data_size_bytes() - ibc->get_data_size_bytes();
_total_buffers_pcollector.add_level(delta);
if (PStatClient::is_connected()) {
if (_current_index_buffers.insert(ibc).second) {
_active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes());
}
}
}

View File

@ -107,8 +107,11 @@ public:
virtual GeomContext *prepare_geom(Geom *geom);
virtual void release_geom(GeomContext *gc);
virtual DataContext *prepare_data(qpGeomVertexArrayData *data);
virtual void release_data(DataContext *gc);
virtual VertexBufferContext *prepare_vertex_buffer(qpGeomVertexArrayData *data);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
@ -226,11 +229,13 @@ protected:
void init_frame_pstats();
void add_to_texture_record(TextureContext *tc);
void add_to_geom_record(GeomContext *gc);
void add_to_data_record(DataContext *dc);
void add_to_vertex_buffer_record(VertexBufferContext *vbc);
void add_to_index_buffer_record(IndexBufferContext *ibc);
pset<TextureContext *> _current_textures;
pset<GeomContext *> _current_geoms;
pset<DataContext *> _current_datas;
pset<VertexBufferContext *> _current_vertex_buffers;
pset<IndexBufferContext *> _current_index_buffers;
#else
INLINE void init_frame_pstats() { }
INLINE void add_to_texture_record(TextureContext *) { }
@ -314,7 +319,8 @@ public:
static PStatCollector _total_geom_pcollector;
static PStatCollector _active_geom_pcollector;
static PStatCollector _total_buffers_pcollector;
static PStatCollector _active_buffers_pcollector;
static PStatCollector _active_vertex_buffers_pcollector;
static PStatCollector _active_index_buffers_pcollector;
static PStatCollector _total_geom_node_pcollector;
static PStatCollector _active_geom_node_pcollector;
static PStatCollector _total_texmem_pcollector;

View File

@ -20,7 +20,7 @@
// need to install these due to external projects that link directly with libpandadx (bartop)
#define INSTALL_HEADERS \
dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \
dxDataContext8.h \
dxVertexBufferContext8.h \
dxTextureContext8.h \
dxGeomMunger8.h \
d3dfont8.h \
@ -37,7 +37,7 @@
#define INCLUDED_SOURCES \
config_dxgsg8.cxx \
dxDataContext8.cxx \
dxVertexBufferContext8.cxx \
dxTextureContext8.cxx \
dxGeomMunger8.cxx \
d3dfont8.cxx \

View File

@ -19,7 +19,7 @@
#include "config_dxgsg8.h"
#include "dxGraphicsStateGuardian8.h"
#include "dxTextureContext8.h"
#include "dxDataContext8.h"
#include "dxVertexBufferContext8.h"
#include "dxGeomMunger8.h"
#include "graphicsPipeSelection.h"
#include "wdxGraphicsWindow8.h"
@ -145,7 +145,7 @@ init_libdxgsg8() {
DXGraphicsStateGuardian8::init_type();
DXTextureContext8::init_type();
DXDataContext8::init_type();
DXVertexBufferContext8::init_type();
DXGeomMunger8::init_type();
wdxGraphicsPipe8::init_type();

View File

@ -56,7 +56,7 @@
#include "qpgeomTrifans.h"
#include "dxGeomMunger8.h"
#include "config_gobj.h"
#include "dxDataContext8.h"
#include "dxVertexBufferContext8.h"
#ifdef DO_PSTATS
#include "pStatTimer.h"
@ -2620,8 +2620,8 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
// the first array.
const qpGeomVertexArrayData *data = _vertex_data->get_array(0);
DataContext *dc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
nassertr(dc != (DataContext *)NULL, false);
VertexBufferContext *dc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
nassertr(dc != (VertexBufferContext *)NULL, false);
apply_data(dc);
return true;
@ -2903,79 +2903,79 @@ release_texture(TextureContext *tc) {
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::prepare_data
// Function: DXGraphicsStateGuardian8::prepare_vertex_buffer
// Access: Public, Virtual
// Description: Creates a new retained-mode representation of the
// given data, and returns a newly-allocated
// DataContext pointer to reference it. It is the
// VertexBufferContext pointer to reference it. It is the
// responsibility of the calling function to later
// call release_data() with this same pointer (which
// call release_vertex_buffer() with this same pointer (which
// will also delete the pointer).
//
// This function should not be called directly to
// prepare a data. Instead, call Data::prepare().
////////////////////////////////////////////////////////////////////
DataContext *DXGraphicsStateGuardian8::
prepare_data(qpGeomVertexArrayData *data) {
VertexBufferContext *DXGraphicsStateGuardian8::
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "prepare_data(" << (void *)data << ")\n";
<< "prepare_vertex_buffer(" << (void *)data << ")\n";
}
DXDataContext8 *ddc = new DXDataContext8(data);
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
if (vertex_buffers) {
ddc->create_vbuffer(*_pScrn);
ddc->mark_loaded();
dvbc->create_vbuffer(*_pScrn);
dvbc->mark_loaded();
}
return ddc;
return dvbc;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::apply_data
// Function: DXGraphicsStateGuardian8::apply_vertex_buffer
// Access: Public
// Description: Makes the data the currently available data for
// rendering.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
apply_data(DataContext *dc) {
DXDataContext8 *ddc = DCAST(DXDataContext8, dc);
apply_vertex_buffer(VertexBufferContext *vbc) {
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
if (ddc->_vbuffer != NULL) {
add_to_data_record(ddc);
if (dvbc->_vbuffer != NULL) {
add_to_vertex_buffer_record(dvbc);
if (ddc->was_modified()) {
if (dvbc->was_modified()) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "apply_data(" << (void *)dc->get_data() << ")\n";
<< "apply_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
}
if (ddc->changed_size()) {
if (dvbc->changed_size()) {
// Here we have to destroy the old vertex buffer and create a
// new one.
ddc->create_vbuffer(*_pScrn);
dvbc->create_vbuffer(*_pScrn);
} else {
// Here we just copy the new data to the vertex buffer.
ddc->upload_data();
dvbc->upload_data();
}
ddc->mark_loaded();
dvbc->mark_loaded();
}
_pD3DDevice->SetStreamSource
(0, ddc->_vbuffer, ddc->get_data()->get_array_format()->get_stride());
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
_vbuffer_active = true;
} else {
_vbuffer_active = false;
}
set_vertex_format(ddc->_fvf);
set_vertex_format(dvbc->_fvf);
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::release_data
// Function: DXGraphicsStateGuardian8::release_vertex_buffer
// Access: Public, Virtual
// Description: Frees the GL resources previously allocated for the
// data. This function should never be called
@ -2983,14 +2983,14 @@ apply_data(DataContext *dc) {
// let the Data destruct).
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
release_data(DataContext *dc) {
release_vertex_buffer(VertexBufferContext *vbc) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "release_data(" << (void *)dc->get_data() << ")\n";
<< "release_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
}
DXDataContext8 *ddc = DCAST(DXDataContext8, dc);
delete ddc;
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
delete dvbc;
}
////////////////////////////////////////////////////////////////////

View File

@ -99,9 +99,9 @@ public:
virtual void apply_texture(TextureContext *tc);
virtual void release_texture(TextureContext *tc);
virtual DataContext *prepare_data(qpGeomVertexArrayData *data);
void apply_data(DataContext *dc);
virtual void release_data(DataContext *dc);
virtual VertexBufferContext *prepare_vertex_buffer(qpGeomVertexArrayData *data);
void apply_vertex_buffer(VertexBufferContext *vbc);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);

View File

@ -1,4 +1,4 @@
// Filename: dxDataContext8.I
// Filename: dxVertexBufferContext8.I
// Created by: drose (18Mar05)
//
////////////////////////////////////////////////////////////////////

View File

@ -1,4 +1,4 @@
// Filename: dxDataContext8.cxx
// Filename: dxVertexBufferContext8.cxx
// Created by: drose (18Mar05)
//
////////////////////////////////////////////////////////////////////
@ -16,23 +16,23 @@
//
////////////////////////////////////////////////////////////////////
#include "dxDataContext8.h"
#include "dxVertexBufferContext8.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomVertexArrayFormat.h"
#include "internalName.h"
#include "config_dxgsg8.h"
#include <d3dx8.h>
TypeHandle DXDataContext8::_type_handle;
TypeHandle DXVertexBufferContext8::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::Constructor
// Function: DXVertexBufferContext8::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXDataContext8::
DXDataContext8(qpGeomVertexArrayData *data) :
DataContext(data),
DXVertexBufferContext8::
DXVertexBufferContext8(qpGeomVertexArrayData *data) :
VertexBufferContext(data),
_vbuffer(NULL)
{
// Now fill in the FVF code.
@ -88,12 +88,12 @@ DXDataContext8(qpGeomVertexArrayData *data) :
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::Destructor
// Function: DXVertexBufferContext8::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXDataContext8::
~DXDataContext8() {
DXVertexBufferContext8::
~DXVertexBufferContext8() {
if (_vbuffer != NULL) {
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
_vbuffer = NULL;
@ -101,11 +101,11 @@ DXDataContext8::
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::create_vbuffer
// Function: DXVertexBufferContext8::create_vbuffer
// Access: Public
// Description: Creates a new vertex buffer and uploads data to it.
////////////////////////////////////////////////////////////////////
void DXDataContext8::
void DXVertexBufferContext8::
create_vbuffer(DXScreenData &scrn) {
if (_vbuffer != NULL) {
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
@ -113,7 +113,7 @@ create_vbuffer(DXScreenData &scrn) {
}
HRESULT hr = scrn.pD3DDevice->CreateVertexBuffer
(get_data()->get_num_bytes(), D3DUSAGE_WRITEONLY,
(get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY,
_fvf, D3DPOOL_MANAGED, &_vbuffer);
if (FAILED(hr)) {
dxgsg8_cat.warning()
@ -126,24 +126,26 @@ create_vbuffer(DXScreenData &scrn) {
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::upload_data
// Function: DXVertexBufferContext8::upload_data
// Access: Public
// Description: Copies the latest data from the client store to
// DirectX.
////////////////////////////////////////////////////////////////////
void DXDataContext8::
void DXVertexBufferContext8::
upload_data() {
nassertv(_vbuffer != NULL);
int data_size = get_data()->get_data_size_bytes();
BYTE *local_pointer;
HRESULT hr = _vbuffer->Lock(0, 0, &local_pointer, 0);
HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, 0);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
return;
}
memcpy(local_pointer, get_data()->get_data(), get_data()->get_num_bytes());
memcpy(local_pointer, get_data()->get_data(), data_size);
_vbuffer->Unlock();
}

View File

@ -1,4 +1,4 @@
// Filename: dxDataContext8.h
// Filename: dxVertexBufferContext8.h
// Created by: drose (18Mar05)
//
////////////////////////////////////////////////////////////////////
@ -16,22 +16,22 @@
//
////////////////////////////////////////////////////////////////////
#ifndef DXDATACONTEXT8_H
#define DXDATACONTEXT8_H
#ifndef DXVERTEXBUFFERCONTEXT8_H
#define DXVERTEXBUFFERCONTEXT8_H
#include "pandabase.h"
#include "dxgsg8base.h"
#include "dataContext.h"
#include "vertexBufferContext.h"
////////////////////////////////////////////////////////////////////
// Class : DXDataContext8
// Class : DXVertexBufferContext8
// Description : Caches a GeomVertexArrayData in the DirectX device as
// a vertex buffer.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXDataContext8 : public DataContext {
class EXPCL_PANDADX DXVertexBufferContext8 : public VertexBufferContext {
public:
DXDataContext8(qpGeomVertexArrayData *data);
virtual ~DXDataContext8();
DXVertexBufferContext8(qpGeomVertexArrayData *data);
virtual ~DXVertexBufferContext8();
void create_vbuffer(DXScreenData &scrn);
void upload_data();
@ -44,9 +44,9 @@ public:
return _type_handle;
}
static void init_type() {
DataContext::init_type();
register_type(_type_handle, "DXDataContext8",
DataContext::get_class_type());
VertexBufferContext::init_type();
register_type(_type_handle, "DXVertexBufferContext8",
VertexBufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -57,7 +57,7 @@ private:
static TypeHandle _type_handle;
};
#include "dxDataContext8.I"
#include "dxVertexBufferContext8.I"
#endif

View File

@ -1,7 +1,7 @@
#include "dxgsg8base.h"
#include "config_dxgsg8.cxx"
#include "dxTextureContext8.cxx"
#include "dxDataContext8.cxx"
#include "dxVertexBufferContext8.cxx"
#include "dxGeomMunger8.cxx"
#include "d3dfont8.cxx"
#include "wdxGraphicsPipe8.cxx"

View File

@ -1926,7 +1926,7 @@ make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) {
// Now create a new GeomVertexData using the indicated format.
PT(qpGeomVertexData) vertex_data =
new qpGeomVertexData(format, qpGeomVertexArrayData::UH_static);
new qpGeomVertexData(format, qpGeomUsageHint::UH_static);
// And fill the data from the vertex pool.
EggVertexPool::const_iterator vi;
@ -1979,10 +1979,10 @@ make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim,
PT(qpGeomPrimitive) primitive;
if (egg_prim->is_of_type(EggPolygon::get_class_type())) {
if (egg_prim->size() == 3) {
primitive = new qpGeomTriangles;
primitive = new qpGeomTriangles(qpGeomUsageHint::UH_static);
}
} else if (egg_prim->is_of_type(EggTriangleStrip::get_class_type())) {
primitive = new qpGeomTristrips;
primitive = new qpGeomTristrips(qpGeomUsageHint::UH_static);
}
if (primitive == (qpGeomPrimitive *)NULL) {

View File

@ -634,7 +634,7 @@ load_default_model(const NodePath &parent) {
// New, experimental Geom code.
PT(qpGeomVertexData) vdata = new qpGeomVertexData
(qpGeomVertexFormat::get_v3n3cpt2(),
qpGeomVertexArrayData::UH_static);
qpGeomUsageHint::UH_static);
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator normal(vdata, InternalName::get_normal());
qpGeomVertexIterator color(vdata, InternalName::get_color());
@ -656,7 +656,7 @@ load_default_model(const NodePath &parent) {
texcoord.set_data2(1.0, 0.0);
texcoord.set_data2(0.0, 1.0);
PT(qpGeomTriangles) tri = new qpGeomTriangles;
PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static);
tri->add_consecutive_vertices(0, 3);
tri->close_primitive();
@ -1061,7 +1061,7 @@ load_image_as_model(const Filename &filename) {
if (use_qpgeom) {
PT(qpGeomVertexData) vdata = new qpGeomVertexData
(qpGeomVertexFormat::get_v3t2(),
qpGeomVertexArrayData::UH_static);
qpGeomUsageHint::UH_static);
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
@ -1075,7 +1075,7 @@ load_image_as_model(const Filename &filename) {
texcoord.set_data2(1.0f, 1.0f);
texcoord.set_data2(1.0f, 0.0f);
PT(qpGeomTristrips) strip = new qpGeomTristrips;
PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static);
strip->add_consecutive_vertices(0, 4);
strip->close_primitive();

View File

@ -19,9 +19,12 @@
glstuff_src.cxx \
glstuff_src.h \
glstuff_undef_src.h \
glDataContext_src.cxx \
glDataContext_src.I \
glDataContext_src.h \
glVertexBufferContext_src.cxx \
glVertexBufferContext_src.I \
glVertexBufferContext_src.h \
glIndexBufferContext_src.cxx \
glIndexBufferContext_src.I \
glIndexBufferContext_src.h \
glGeomContext_src.cxx \
glGeomContext_src.I \
glGeomContext_src.h \

View File

@ -596,6 +596,18 @@ reset() {
GLCAT.debug()
<< "max_elements_vertices = " << max_elements_vertices
<< ", max_elements_indices = " << max_elements_indices << "\n";
if (_supports_buffers) {
if (vertex_buffers) {
GLCAT.debug()
<< "vertex buffer objects are supported.\n";
} else {
GLCAT.debug()
<< "vertex buffer objects are supported (but not enabled).\n";
}
} else {
GLCAT.debug()
<< "vertex buffer objects are NOT supported.\n";
}
}
report_my_gl_errors();
@ -2107,11 +2119,14 @@ void CLP(GraphicsStateGuardian)::
draw_triangles(const qpGeomTriangles *primitive) {
setup_antialias_polygon();
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_TRIANGLES,
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, primitive->get_flat_last_vertices());
GL_UNSIGNED_SHORT, client_pointer);
report_my_gl_errors();
}
@ -2125,7 +2140,9 @@ void CLP(GraphicsStateGuardian)::
draw_tristrips(const qpGeomTristrips *primitive) {
setup_antialias_polygon();
CPTA_ushort vertices = primitive->get_flat_last_vertices();
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
CPTA_int ends = primitive->get_ends();
CPTA_ushort mins = primitive->get_mins();
CPTA_ushort maxs = primitive->get_maxs();
@ -2135,7 +2152,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
for (size_t i = 0; i < ends.size(); i++) {
_glDrawRangeElements(GL_TRIANGLE_STRIP,
mins[i], maxs[i], ends[i] - start,
GL_UNSIGNED_SHORT, vertices + start);
GL_UNSIGNED_SHORT, client_pointer + start);
start = ends[i];
}
@ -2334,83 +2351,74 @@ release_geom(GeomContext *gc) {
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::prepare_data
// Function: CLP(GraphicsStateGuardian)::prepare_vertex_buffer
// Access: Public, Virtual
// Description: Creates a new retained-mode representation of the
// given data, and returns a newly-allocated
// DataContext pointer to reference it. It is the
// VertexBufferContext pointer to reference it. It is the
// responsibility of the calling function to later
// call release_data() with this same pointer (which
// call release_vertex_buffer() with this same pointer (which
// will also delete the pointer).
//
// This function should not be called directly to
// prepare a data. Instead, call Data::prepare().
////////////////////////////////////////////////////////////////////
DataContext *CLP(GraphicsStateGuardian)::
prepare_data(qpGeomVertexArrayData *data) {
VertexBufferContext *CLP(GraphicsStateGuardian)::
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "prepare_data(" << (void *)data << ")\n";
<< "prepare_vertex_buffer(" << (void *)data << ")\n";
}
if (_supports_buffers) {
CLP(DataContext) *gdc = new CLP(DataContext)(data);
_glGenBuffers(1, &gdc->_index);
/*
_glBindBuffer(GL_ARRAY_BUFFER, gdc->_index);
_glBufferData(GL_ARRAY_BUFFER, gdc->get_data()->get_num_bytes(),
gdc->get_data()->get_data(),
get_usage(gdc->get_data()->get_usage_hint()));
add_to_data_record(gdc);
gdc->mark_loaded();
*/
CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(data);
_glGenBuffers(1, &gvbc->_index);
report_my_gl_errors();
return gdc;
return gvbc;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::apply_data
// Function: CLP(GraphicsStateGuardian)::apply_vertex_buffer
// Access: Public
// Description: Makes the data the currently available data for
// rendering.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
apply_data(DataContext *dc) {
apply_vertex_buffer(VertexBufferContext *vbc) {
nassertv(_supports_buffers);
CLP(DataContext) *gdc = DCAST(CLP(DataContext), dc);
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
_glBindBuffer(GL_ARRAY_BUFFER, gdc->_index);
_glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
add_to_data_record(gdc);
if (gdc->was_modified()) {
add_to_vertex_buffer_record(gvbc);
if (gvbc->was_modified()) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "apply_data(" << (void *)dc->get_data() << ")\n";
<< "apply_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
}
if (gdc->changed_size()) {
_glBufferData(GL_ARRAY_BUFFER, gdc->get_data()->get_num_bytes(),
gdc->get_data()->get_data(),
get_usage(gdc->get_data()->get_usage_hint()));
if (gvbc->changed_size()) {
_glBufferData(GL_ARRAY_BUFFER, gvbc->get_data()->get_data_size_bytes(),
gvbc->get_data()->get_data(),
get_usage(gvbc->get_data()->get_usage_hint()));
} else {
_glBufferSubData(GL_ARRAY_BUFFER, 0, gdc->get_num_bytes(),
gdc->get_data()->get_data());
_glBufferSubData(GL_ARRAY_BUFFER, 0, gvbc->get_data_size_bytes(),
gvbc->get_data()->get_data());
}
gdc->mark_loaded();
gvbc->mark_loaded();
}
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::release_data
// Function: CLP(GraphicsStateGuardian)::release_vertex_buffer
// Access: Public, Virtual
// Description: Frees the GL resources previously allocated for the
// data. This function should never be called
@ -2418,22 +2426,22 @@ apply_data(DataContext *dc) {
// let the Data destruct).
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
release_data(DataContext *dc) {
release_vertex_buffer(VertexBufferContext *vbc) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "release_data(" << (void *)dc->get_data() << ")\n";
<< "release_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
}
nassertv(_supports_buffers);
CLP(DataContext) *gdc = DCAST(CLP(DataContext), dc);
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
_glDeleteBuffers(1, &gdc->_index);
_glDeleteBuffers(1, &gvbc->_index);
report_my_gl_errors();
gdc->_index = 0;
gvbc->_index = 0;
delete gdc;
delete gvbc;
}
////////////////////////////////////////////////////////////////////
@ -2457,7 +2465,7 @@ setup_array_data(const qpGeomVertexArrayData *data) {
return data->get_data();
}
if (!vertex_buffers ||
data->get_usage_hint() == qpGeomVertexArrayData::UH_client) {
data->get_usage_hint() == qpGeomUsageHint::UH_client) {
// The array specifies client rendering only, or buffer objects
// are configured off.
_glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -2465,28 +2473,144 @@ setup_array_data(const qpGeomVertexArrayData *data) {
}
// Prepare the buffer object and bind it.
DataContext *dc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
nassertr(dc != (DataContext *)NULL, data->get_data());
apply_data(dc);
VertexBufferContext *vbc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
nassertr(vbc != (VertexBufferContext *)NULL, data->get_data());
apply_vertex_buffer(vbc);
// NULL is the OpenGL convention for the first byte of the buffer.
return NULL;
}
#if 0
static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
4096, 0 };
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::prepare_index_buffer
// Access: Public, Virtual
// Description: Creates a new retained-mode representation of the
// given data, and returns a newly-allocated
// IndexBufferContext pointer to reference it. It is the
// responsibility of the calling function to later
// call release_index_buffer() with this same pointer (which
// will also delete the pointer).
//
// This function should not be called directly to
// prepare a data. Instead, call Data::prepare().
////////////////////////////////////////////////////////////////////
IndexBufferContext *CLP(GraphicsStateGuardian)::
prepare_index_buffer(qpGeomPrimitive *data) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "prepare_index_buffer(" << (void *)data << ")\n";
}
// This function returns the smallest power of two greater than or
// equal to x.
static int binary_log_cap(const int x) {
int i = 0;
for (; (x > logs[i]) && (logs[i] != 0); ++i);
if (logs[i] == 0)
return 4096;
return logs[i];
if (_supports_buffers) {
CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(data);
_glGenBuffers(1, &gibc->_index);
report_my_gl_errors();
return gibc;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::apply_index_buffer
// Access: Public
// Description: Makes the data the currently available data for
// rendering.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
apply_index_buffer(IndexBufferContext *ibc) {
nassertv(_supports_buffers);
CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc);
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index);
add_to_index_buffer_record(gibc);
if (gibc->was_modified()) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "apply_index_buffer(" << (void *)ibc->get_data() << ")\n";
}
if (gibc->changed_size()) {
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(),
gibc->get_data()->get_vertices(),
get_usage(gibc->get_data()->get_usage_hint()));
} else {
_glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, gibc->get_data_size_bytes(),
gibc->get_data()->get_vertices());
}
gibc->mark_loaded();
}
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::release_index_buffer
// Access: Public, Virtual
// Description: Frees the GL resources previously allocated for the
// data. This function should never be called
// directly; instead, call Data::release() (or simply
// let the Data destruct).
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
release_index_buffer(IndexBufferContext *ibc) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "release_index_buffer(" << (void *)ibc->get_data() << ")\n";
}
nassertv(_supports_buffers);
CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc);
_glDeleteBuffers(1, &gibc->_index);
report_my_gl_errors();
gibc->_index = 0;
delete gibc;
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::setup_primitive
// Access: Public
// Description: Internal function to bind a buffer object for the
// indicated primitive's index list, if appropriate, or
// 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 short *CLP(GraphicsStateGuardian)::
setup_primitive(const qpGeomPrimitive *data) {
if (!_supports_buffers) {
// No support for buffer objects; always render from client.
return data->get_vertices();
}
if (!vertex_buffers ||
data->get_usage_hint() == qpGeomUsageHint::UH_client) {
// The array specifies client rendering only, or buffer objects
// are configured off.
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return data->get_vertices();
}
// Prepare the buffer object and bind it.
IndexBufferContext *ibc = ((qpGeomPrimitive *)data)->prepare_now(get_prepared_objects(), this);
nassertr(ibc != (IndexBufferContext *)NULL, data->get_vertices());
apply_index_buffer(ibc);
// NULL is the OpenGL convention for the first byte of the buffer.
return NULL;
}
#endif
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_geom_munger
@ -4598,18 +4722,18 @@ get_blend_func(ColorBlendAttrib::Operand operand) {
// Description: Maps from UsageHint to the GL symbol.
////////////////////////////////////////////////////////////////////
GLenum CLP(GraphicsStateGuardian)::
get_usage(qpGeomVertexArrayData::UsageHint usage_hint) {
get_usage(qpGeomUsageHint::UsageHint usage_hint) {
switch (usage_hint) {
case qpGeomVertexArrayData::UH_stream:
case qpGeomUsageHint::UH_stream:
return GL_STREAM_DRAW;
case qpGeomVertexArrayData::UH_static:
case qpGeomUsageHint::UH_static:
return GL_STATIC_DRAW;
case qpGeomVertexArrayData::UH_dynamic:
case qpGeomUsageHint::UH_dynamic:
return GL_DYNAMIC_DRAW;
case qpGeomVertexArrayData::UH_client:
case qpGeomUsageHint::UH_client:
break;
}

View File

@ -104,11 +104,16 @@ public:
virtual GeomContext *prepare_geom(Geom *geom);
virtual void release_geom(GeomContext *gc);
virtual DataContext *prepare_data(qpGeomVertexArrayData *data);
void apply_data(DataContext *dc);
virtual void release_data(DataContext *dc);
virtual VertexBufferContext *prepare_vertex_buffer(qpGeomVertexArrayData *data);
void apply_vertex_buffer(VertexBufferContext *vbc);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
const unsigned char *setup_array_data(const qpGeomVertexArrayData *data);
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data);
void apply_index_buffer(IndexBufferContext *ibc);
virtual void release_index_buffer(IndexBufferContext *ibc);
const unsigned short *setup_primitive(const qpGeomPrimitive *data);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual void framebuffer_copy_to_texture
@ -242,7 +247,7 @@ protected:
static GLenum get_fog_mode_type(Fog::Mode m);
static GLenum get_blend_equation_type(ColorBlendAttrib::Mode mode);
static GLenum get_blend_func(ColorBlendAttrib::Operand operand);
static GLenum get_usage(qpGeomVertexArrayData::UsageHint usage_hint);
static GLenum get_usage(qpGeomUsageHint::UsageHint usage_hint);
static CPT(RenderState) get_untextured_state();
static CPT(RenderState) get_smooth_state();

View File

@ -1,4 +1,4 @@
// Filename: glDataContext_src.I
// Filename: glIndexBufferContext_src.I
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -18,13 +18,13 @@
////////////////////////////////////////////////////////////////////
// Function: CLP(DataContext)::Constructor
// Function: CLP(IndexBufferContext)::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(DataContext)::
CLP(DataContext)(qpGeomVertexArrayData *data) :
DataContext(data)
INLINE CLP(IndexBufferContext)::
CLP(IndexBufferContext)(qpGeomPrimitive *data) :
IndexBufferContext(data)
{
_index = 0;
}

View File

@ -1,4 +1,4 @@
// Filename: glDataContext_src.cxx
// Filename: glIndexBufferContext_src.cxx
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -16,4 +16,4 @@
//
////////////////////////////////////////////////////////////////////
TypeHandle CLP(DataContext)::_type_handle;
TypeHandle CLP(IndexBufferContext)::_type_handle;

View File

@ -0,0 +1,53 @@
// Filename: glIndexBufferContext_src.h
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "indexBufferContext.h"
////////////////////////////////////////////////////////////////////
// Class : GLIndexBufferContext
// Description : Caches a GeomPrimitive on the GL as a buffer
// object.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(IndexBufferContext) : public IndexBufferContext {
public:
INLINE CLP(IndexBufferContext)(qpGeomPrimitive *data);
// This is the GL "name" of the data object.
GLuint _index;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
IndexBufferContext::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "IndexBufferContext",
IndexBufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "glIndexBufferContext_src.I"

View File

@ -0,0 +1,30 @@
// Filename: glVertexBufferContext_src.I
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CLP(VertexBufferContext)::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(VertexBufferContext)::
CLP(VertexBufferContext)(qpGeomVertexArrayData *data) :
VertexBufferContext(data)
{
_index = 0;
}

View File

@ -1,4 +1,4 @@
// Filename: dataContext.cxx
// Filename: glVertexBufferContext_src.cxx
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -16,6 +16,4 @@
//
////////////////////////////////////////////////////////////////////
#include "dataContext.h"
TypeHandle DataContext::_type_handle;
TypeHandle CLP(VertexBufferContext)::_type_handle;

View File

@ -1,4 +1,4 @@
// Filename: glDataContext_src.h
// Filename: glVertexBufferContext_src.h
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -17,16 +17,16 @@
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "dataContext.h"
#include "vertexBufferContext.h"
////////////////////////////////////////////////////////////////////
// Class : GLDataContext
// Class : GLVertexBufferContext
// Description : Caches a GeomVertexArrayData on the GL as a buffer
// object.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(DataContext) : public DataContext {
class EXPCL_GL CLP(VertexBufferContext) : public VertexBufferContext {
public:
INLINE CLP(DataContext)(qpGeomVertexArrayData *data);
INLINE CLP(VertexBufferContext)(qpGeomVertexArrayData *data);
// This is the GL "name" of the data object.
GLuint _index;
@ -36,9 +36,9 @@ public:
return _type_handle;
}
static void init_type() {
DataContext::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "DataContext",
DataContext::get_class_type());
VertexBufferContext::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "VertexBufferContext",
VertexBufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -49,5 +49,5 @@ private:
static TypeHandle _type_handle;
};
#include "glDataContext_src.I"
#include "glVertexBufferContext_src.I"

View File

@ -63,7 +63,8 @@ void CLP(init_classes)() {
CLP(GraphicsStateGuardian)::init_type();
CLP(TextureContext)::init_type();
CLP(GeomContext)::init_type();
CLP(DataContext)::init_type();
CLP(VertexBufferContext)::init_type();
CLP(IndexBufferContext)::init_type();
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->add_system(GLSYSTEM_NAME);

View File

@ -23,7 +23,8 @@
#include "glmisc_src.cxx"
#include "glTextureContext_src.cxx"
#include "glDataContext_src.cxx"
#include "glVertexBufferContext_src.cxx"
#include "glIndexBufferContext_src.cxx"
#include "glGeomContext_src.cxx"
#include "glGeomMunger_src.cxx"
#include "glCgShaderContext_src.cxx"

View File

@ -41,7 +41,8 @@
#include "glmisc_src.h"
#include "glTextureContext_src.h"
#include "glDataContext_src.h"
#include "glVertexBufferContext_src.h"
#include "glIndexBufferContext_src.h"
#include "glGeomContext_src.h"
#include "glGeomMunger_src.h"
#include "glCgShaderContext_src.h"

View File

@ -12,7 +12,6 @@
#define SOURCES \
boundedObject.I boundedObject.h \
config_gobj.h \
dataContext.I dataContext.h \
drawable.h \
geom.I geom.h \
geomContext.I geomContext.h \
@ -25,6 +24,7 @@
qpgeomTriangles.h \
qpgeomTristrips.h \
qpgeomTrifans.h \
qpgeomUsageHint.h \
qpgeomVertexArrayData.h qpgeomVertexArrayData.I \
qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \
qpgeomVertexCacheManager.h qpgeomVertexCacheManager.I \
@ -32,6 +32,7 @@
qpgeomVertexDataType.h qpgeomVertexDataType.I \
qpgeomVertexFormat.h qpgeomVertexFormat.I \
qpgeomVertexIterator.h qpgeomVertexIterator.I \
indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \
material.I material.h materialPool.I materialPool.h \
matrixLens.I matrixLens.h \
@ -43,12 +44,12 @@
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
textureStage.I textureStage.h
textureStage.I textureStage.h \
vertexBufferContext.I vertexBufferContext.h
#define INCLUDED_SOURCES \
boundedObject.cxx \
config_gobj.cxx \
dataContext.cxx \
drawable.cxx geom.cxx \
geomContext.cxx \
geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \
@ -67,6 +68,7 @@
qpgeomVertexDataType.cxx \
qpgeomVertexFormat.cxx \
qpgeomVertexIterator.cxx \
indexBufferContext.cxx \
material.cxx \
internalName.cxx \
materialPool.cxx matrixLens.cxx orthographicLens.cxx \
@ -74,12 +76,12 @@
preparedGraphicsObjects.cxx \
lens.cxx \
savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \
textureStage.cxx
textureStage.cxx \
vertexBufferContext.cxx
#define INSTALL_HEADERS \
boundedObject.I boundedObject.h \
config_gobj.h \
dataContext.I dataContext.h \
drawable.h geom.I geom.h \
textureContext.I textureContext.h \
geomLine.h \
@ -92,6 +94,7 @@
qpgeomTriangles.h \
qpgeomTristrips.h \
qpgeomTrifans.h \
qpgeomUsageHint.h \
qpgeomVertexArrayData.h qpgeomVertexArrayData.I \
qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \
qpgeomVertexCacheManager.h qpgeomVertexCacheManager.I \
@ -99,6 +102,7 @@
qpgeomVertexDataType.h qpgeomVertexDataType.I \
qpgeomVertexFormat.h qpgeomVertexFormat.I \
qpgeomVertexIterator.h qpgeomVertexIterator.I \
indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \
material.I material.h \
materialPool.I materialPool.h matrixLens.I matrixLens.h \
@ -110,7 +114,9 @@
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
textureStage.I textureStage.h
textureStage.I textureStage.h \
vertexBufferContext.I vertexBufferContext.h
#define IGATESCAN all

View File

@ -41,7 +41,8 @@
#include "textureStage.h"
#include "textureContext.h"
#include "geomContext.h"
#include "dataContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
#include "internalName.h"
#include "dconfig.h"
@ -182,7 +183,8 @@ ConfigureFn(config_gobj) {
qpGeomVertexFormat::init_type();
TextureContext::init_type();
GeomContext::init_type();
DataContext::init_type();
VertexBufferContext::init_type();
IndexBufferContext::init_type();
Material::init_type();
OrthographicLens::init_type();
MatrixLens::init_type();

View File

@ -1,6 +1,5 @@
#include "boundedObject.cxx"
#include "dataContext.cxx"
#include "geom.cxx"
#include "geomLine.cxx"
#include "geomLinestrip.cxx"

View File

@ -2,16 +2,18 @@
#include "config_gobj.cxx"
#include "drawable.cxx"
#include "geomContext.cxx"
#include "indexBufferContext.cxx"
#include "internalName.cxx"
#include "lens.cxx"
#include "material.cxx"
#include "materialPool.cxx"
#include "orthographicLens.cxx"
#include "matrixLens.cxx"
#include "orthographicLens.cxx"
#include "perspectiveLens.cxx"
#include "preparedGraphicsObjects.cxx"
#include "lens.cxx"
#include "savedContext.cxx"
#include "texture.cxx"
#include "textureContext.cxx"
#include "texturePool.cxx"
#include "textureStage.cxx"
#include "vertexBufferContext.cxx"

View File

@ -1,4 +1,4 @@
// Filename: dataContext.I
// Filename: indexBufferContext.I
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -18,74 +18,74 @@
////////////////////////////////////////////////////////////////////
// Function: DataContext::Constructor
// Function: IndexBufferContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE DataContext::
DataContext(qpGeomVertexArrayData *data) :
INLINE IndexBufferContext::
IndexBufferContext(qpGeomPrimitive *data) :
_data(data),
// Initially, the number of bytes is zero, until the data has been
// loaded (and mark_loaded() is called).
_num_bytes(0)
_data_size_bytes(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::get_data
// Function: IndexBufferContext::get_data
// Access: Public
// Description: Returns the pointer to the client-side array data
// object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData *DataContext::
INLINE qpGeomPrimitive *IndexBufferContext::
get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::get_num_bytes
// Function: IndexBufferContext::get_data_size_bytes
// Access: Public
// Description: Returns the number of bytes previously reported for
// the data object. This is used to track changes in
// the data object's allocated size; if it changes from
// this, we need to create a new buffer.
////////////////////////////////////////////////////////////////////
INLINE int DataContext::
get_num_bytes() const {
return _num_bytes;
INLINE int IndexBufferContext::
get_data_size_bytes() const {
return _data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::changed_size
// Function: IndexBufferContext::changed_size
// Access: Public
// Description: Returns true if the data has changed size since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool DataContext::
INLINE bool IndexBufferContext::
changed_size() const {
return get_num_bytes() != _data->get_num_bytes();
return get_data_size_bytes() != _data->get_data_size_bytes();
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::was_modified
// Function: IndexBufferContext::was_modified
// Access: Public
// Description: Returns true if the data has been modified since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool DataContext::
INLINE bool IndexBufferContext::
was_modified() const {
return _modified != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::mark_loaded
// Function: IndexBufferContext::mark_loaded
// Access: Public
// Description: Should be called after the DataContext has been
// Description: Should be called after the IndexBufferContext has been
// loaded into graphics memory, this updates the
// internal flags for changed_size() and modified().
////////////////////////////////////////////////////////////////////
INLINE void DataContext::
INLINE void IndexBufferContext::
mark_loaded() {
_num_bytes = _data->get_num_bytes();
_data_size_bytes = _data->get_data_size_bytes();
_modified = _data->get_modified();
}

View File

@ -0,0 +1,21 @@
// Filename: indexBufferContext.cxx
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "indexBufferContext.h"
TypeHandle IndexBufferContext::_type_handle;

View File

@ -0,0 +1,82 @@
// Filename: indexBufferContext.h
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef INDEXBUFFERCONTEXT_H
#define INDEXBUFFERCONTEXT_H
#include "pandabase.h"
#include "savedContext.h"
#include "updateSeq.h"
#include "qpgeomPrimitive.h"
////////////////////////////////////////////////////////////////////
// Class : IndexBufferContext
// Description : This is a special class object that holds all the
// information returned by a particular GSG to indicate
// the vertex data array's internal context identifier.
//
// This allows the GSG to cache the vertex data array in
// whatever way makes sense. For instance, DirectX can
// allocate a vertex buffer for the array. OpenGL can
// create a buffer object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA IndexBufferContext : public SavedContext {
public:
INLINE IndexBufferContext(qpGeomPrimitive *data);
INLINE qpGeomPrimitive *get_data() const;
INLINE int get_data_size_bytes() const;
INLINE bool changed_size() const;
INLINE bool was_modified() const;
INLINE void mark_loaded();
private:
// This cannot be a PT(qpGeomPrimitive), because the data and
// the GSG both own their IndexBufferContexts! That would create a
// circular reference count.
qpGeomPrimitive *_data;
UpdateSeq _modified;
int _data_size_bytes;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
SavedContext::init_type();
register_type(_type_handle, "IndexBufferContext",
SavedContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
#include "indexBufferContext.I"
#endif

View File

@ -18,9 +18,12 @@
#include "preparedGraphicsObjects.h"
#include "textureContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
#include "texture.h"
#include "geom.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomPrimitive.h"
#include "mutexHolder.h"
PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
@ -74,18 +77,31 @@ PreparedGraphicsObjects::
_released_geoms.clear();
_enqueued_geoms.clear();
Datas::iterator dci;
for (dci = _prepared_datas.begin();
dci != _prepared_datas.end();
++dci) {
DataContext *dc = (*dci);
_total_texusage_pcollector.sub_level(dc->get_num_bytes());
dc->_data->clear_prepared(this);
VertexBuffers::iterator vbci;
for (vbci = _prepared_vertex_buffers.begin();
vbci != _prepared_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (*vbci);
_total_texusage_pcollector.sub_level(vbc->get_data_size_bytes());
vbc->_data->clear_prepared(this);
}
_prepared_datas.clear();
_released_datas.clear();
_enqueued_datas.clear();
_prepared_vertex_buffers.clear();
_released_vertex_buffers.clear();
_enqueued_vertex_buffers.clear();
IndexBuffers::iterator ibci;
for (ibci = _prepared_index_buffers.begin();
ibci != _prepared_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (*ibci);
_total_texusage_pcollector.sub_level(ibc->get_data_size_bytes());
ibc->_data->clear_prepared(this);
}
_prepared_index_buffers.clear();
_released_index_buffers.clear();
_enqueued_index_buffers.clear();
}
@ -375,78 +391,78 @@ prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg) {
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::enqueue_data
// Function: PreparedGraphicsObjects::enqueue_vertex_buffer
// Access: Public
// Description: Indicates that a data array would like to be put on the
// Description: Indicates that a buffer would like to be put on the
// list to be prepared when the GSG is next ready to
// do this (presumably at the next frame).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
enqueue_data(qpGeomVertexArrayData *data) {
enqueue_vertex_buffer(qpGeomVertexArrayData *data) {
MutexHolder holder(_lock);
_enqueued_datas.insert(data);
_enqueued_vertex_buffers.insert(data);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::dequeue_data
// Function: PreparedGraphicsObjects::dequeue_vertex_buffer
// Access: Public
// Description: Removes a data array from the queued list of data
// Description: Removes a buffer from the queued list of data
// arrays to be prepared. Normally it is not necessary
// to call this, unless you change your mind about
// preparing it at the last minute, since the data will
// automatically be dequeued and prepared at the next
// frame.
//
// The return value is true if the data array is
// The return value is true if the buffer is
// successfully dequeued, false if it had not been
// queued.
////////////////////////////////////////////////////////////////////
bool PreparedGraphicsObjects::
dequeue_data(qpGeomVertexArrayData *data) {
dequeue_vertex_buffer(qpGeomVertexArrayData *data) {
MutexHolder holder(_lock);
EnqueuedDatas::iterator qi = _enqueued_datas.find(data);
if (qi != _enqueued_datas.end()) {
_enqueued_datas.erase(qi);
EnqueuedVertexBuffers::iterator qi = _enqueued_vertex_buffers.find(data);
if (qi != _enqueued_vertex_buffers.end()) {
_enqueued_vertex_buffers.erase(qi);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_data
// Function: PreparedGraphicsObjects::release_vertex_buffer
// Access: Public
// Description: Indicates that a data context, created by a
// previous call to prepare_data(), is no longer
// previous call to prepare_vertex_buffer(), is no longer
// needed. The driver resources will not be freed until
// some GSG calls update(), indicating it is at a
// stage where it is ready to release datas--this
// prevents conflicts from threading or multiple GSG's
// sharing datas (we have no way of knowing which
// graphics context is currently active, or what state
// it's in, at the time release_data is called).
// it's in, at the time release_vertex_buffer is called).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
release_data(DataContext *dc) {
release_vertex_buffer(VertexBufferContext *vbc) {
MutexHolder holder(_lock);
dc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(dc->get_num_bytes());
vbc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
// We have to set the Data pointer to NULL at this point, since
// the Data itself might destruct at any time after it has been
// released.
dc->_data = (qpGeomVertexArrayData *)NULL;
vbc->_data = (qpGeomVertexArrayData *)NULL;
bool removed = (_prepared_datas.erase(dc) != 0);
bool removed = (_prepared_vertex_buffers.erase(vbc) != 0);
nassertv(removed);
_released_datas.insert(dc);
_released_vertex_buffers.insert(vbc);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_all_datas
// Function: PreparedGraphicsObjects::release_all_vertex_buffers
// Access: Public
// Description: Releases all datas at once. This will force them
// to be reloaded into data memory for all GSG's that
@ -454,71 +470,218 @@ release_data(DataContext *dc) {
// released.
////////////////////////////////////////////////////////////////////
int PreparedGraphicsObjects::
release_all_datas() {
release_all_vertex_buffers() {
MutexHolder holder(_lock);
int num_datas = (int)_prepared_datas.size();
int num_vertex_buffers = (int)_prepared_vertex_buffers.size();
Datas::iterator dci;
for (dci = _prepared_datas.begin();
dci != _prepared_datas.end();
++dci) {
DataContext *dc = (*dci);
dc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(dc->get_num_bytes());
dc->_data = (qpGeomVertexArrayData *)NULL;
VertexBuffers::iterator vbci;
for (vbci = _prepared_vertex_buffers.begin();
vbci != _prepared_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (*vbci);
vbc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
vbc->_data = (qpGeomVertexArrayData *)NULL;
_released_datas.insert(dc);
_released_vertex_buffers.insert(vbc);
}
_prepared_datas.clear();
_prepared_vertex_buffers.clear();
return num_datas;
return num_vertex_buffers;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::prepare_data_now
// Function: PreparedGraphicsObjects::prepare_vertex_buffer_now
// Access: Public
// Description: Immediately creates a new DataContext for the
// Description: Immediately creates a new VertexBufferContext for the
// indicated data and returns it. This assumes that
// the GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// datas. If this is not necessarily the case, you
// should use enqueue_data() instead.
// should use enqueue_vertex_buffer() instead.
//
// Normally, this function is not called directly. Call
// Data::prepare_now() instead.
//
// The DataContext contains all of the pertinent
// The VertexBufferContext contains all of the pertinent
// information needed by the GSG to keep track of this
// one particular data, and will exist as long as the
// data is ready to be rendered.
//
// When either the Data or the
// PreparedGraphicsObjects object destructs, the
// DataContext will be deleted.
// VertexBufferContext will be deleted.
////////////////////////////////////////////////////////////////////
DataContext *PreparedGraphicsObjects::
prepare_data_now(qpGeomVertexArrayData *data, GraphicsStateGuardianBase *gsg) {
VertexBufferContext *PreparedGraphicsObjects::
prepare_vertex_buffer_now(qpGeomVertexArrayData *data, GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// Ask the GSG to create a brand new DataContext. There might
// Ask the GSG to create a brand new VertexBufferContext. There might
// be several GSG's sharing the same set of datas; if so, it
// doesn't matter which of them creates the context (since they're
// all shared anyway).
DataContext *dc = gsg->prepare_data(data);
VertexBufferContext *vbc = gsg->prepare_vertex_buffer(data);
if (dc != (DataContext *)NULL) {
bool prepared = _prepared_datas.insert(dc).second;
nassertr(prepared, dc);
if (vbc != (VertexBufferContext *)NULL) {
bool prepared = _prepared_vertex_buffers.insert(vbc).second;
nassertr(prepared, vbc);
// The size has already been counted by
// GraphicsStateGuardian::add_to_data_record(); we don't need to
// GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to
// count it again here.
//_total_buffers_pcollector.add_level(dc->get_num_bytes());
//_total_buffers_pcollector.add_level(vbc->get_data_size_bytes());
}
return dc;
return vbc;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::enqueue_index_buffer
// Access: Public
// Description: Indicates that a buffer would like to be put on the
// list to be prepared when the GSG is next ready to
// do this (presumably at the next frame).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
enqueue_index_buffer(qpGeomPrimitive *data) {
MutexHolder holder(_lock);
_enqueued_index_buffers.insert(data);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::dequeue_index_buffer
// Access: Public
// Description: Removes a buffer from the queued list of data
// arrays to be prepared. Normally it is not necessary
// to call this, unless you change your mind about
// preparing it at the last minute, since the data will
// automatically be dequeued and prepared at the next
// frame.
//
// The return value is true if the buffer is
// successfully dequeued, false if it had not been
// queued.
////////////////////////////////////////////////////////////////////
bool PreparedGraphicsObjects::
dequeue_index_buffer(qpGeomPrimitive *data) {
MutexHolder holder(_lock);
EnqueuedIndexBuffers::iterator qi = _enqueued_index_buffers.find(data);
if (qi != _enqueued_index_buffers.end()) {
_enqueued_index_buffers.erase(qi);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_index_buffer
// Access: Public
// Description: Indicates that a data context, created by a
// previous call to prepare_index_buffer(), is no longer
// needed. The driver resources will not be freed until
// some GSG calls update(), indicating it is at a
// stage where it is ready to release datas--this
// prevents conflicts from threading or multiple GSG's
// sharing datas (we have no way of knowing which
// graphics context is currently active, or what state
// it's in, at the time release_index_buffer is called).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
release_index_buffer(IndexBufferContext *ibc) {
MutexHolder holder(_lock);
ibc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
// We have to set the Data pointer to NULL at this point, since
// the Data itself might destruct at any time after it has been
// released.
ibc->_data = (qpGeomPrimitive *)NULL;
bool removed = (_prepared_index_buffers.erase(ibc) != 0);
nassertv(removed);
_released_index_buffers.insert(ibc);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_all_index_buffers
// Access: Public
// Description: Releases all datas at once. This will force them
// to be reloaded into data memory for all GSG's that
// share this object. Returns the number of datas
// released.
////////////////////////////////////////////////////////////////////
int PreparedGraphicsObjects::
release_all_index_buffers() {
MutexHolder holder(_lock);
int num_index_buffers = (int)_prepared_index_buffers.size();
IndexBuffers::iterator ibci;
for (ibci = _prepared_index_buffers.begin();
ibci != _prepared_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (*ibci);
ibc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
ibc->_data = (qpGeomPrimitive *)NULL;
_released_index_buffers.insert(ibc);
}
_prepared_index_buffers.clear();
return num_index_buffers;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::prepare_index_buffer_now
// Access: Public
// Description: Immediately creates a new IndexBufferContext for the
// indicated data and returns it. This assumes that
// the GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// datas. If this is not necessarily the case, you
// should use enqueue_index_buffer() instead.
//
// Normally, this function is not called directly. Call
// Data::prepare_now() instead.
//
// The IndexBufferContext contains all of the pertinent
// information needed by the GSG to keep track of this
// one particular data, and will exist as long as the
// data is ready to be rendered.
//
// When either the Data or the
// PreparedGraphicsObjects object destructs, the
// IndexBufferContext will be deleted.
////////////////////////////////////////////////////////////////////
IndexBufferContext *PreparedGraphicsObjects::
prepare_index_buffer_now(qpGeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// Ask the GSG to create a brand new IndexBufferContext. There might
// be several GSG's sharing the same set of datas; if so, it
// doesn't matter which of them creates the context (since they're
// all shared anyway).
IndexBufferContext *ibc = gsg->prepare_index_buffer(data);
if (ibc != (IndexBufferContext *)NULL) {
bool prepared = _prepared_index_buffers.insert(ibc).second;
nassertr(prepared, ibc);
// The size has already been counted by
// GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to
// count it again here.
//_total_buffers_pcollector.add_level(ibc->get_data_size_bytes());
}
return ibc;
}
////////////////////////////////////////////////////////////////////
@ -537,7 +700,7 @@ void PreparedGraphicsObjects::
update(GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// First, release all the textures, geoms, and data arrays awaiting
// First, release all the textures, geoms, and buffers awaiting
// release.
Textures::iterator tci;
for (tci = _released_textures.begin();
@ -559,17 +722,27 @@ update(GraphicsStateGuardianBase *gsg) {
_released_geoms.clear();
Datas::iterator dci;
for (dci = _released_datas.begin();
dci != _released_datas.end();
++dci) {
DataContext *dc = (*dci);
gsg->release_data(dc);
VertexBuffers::iterator vbci;
for (vbci = _released_vertex_buffers.begin();
vbci != _released_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (*vbci);
gsg->release_vertex_buffer(vbc);
}
_released_datas.clear();
_released_vertex_buffers.clear();
// Now prepare all the textures, geoms, and data arrays awaiting
IndexBuffers::iterator ibci;
for (ibci = _released_index_buffers.begin();
ibci != _released_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (*ibci);
gsg->release_index_buffer(ibc);
}
_released_index_buffers.clear();
// Now prepare all the textures, geoms, and buffers awaiting
// preparation.
EnqueuedTextures::iterator qti;
for (qti = _enqueued_textures.begin();
@ -589,13 +762,25 @@ update(GraphicsStateGuardianBase *gsg) {
geom->prepare_now(this, gsg);
}
EnqueuedDatas::iterator qdi;
for (qdi = _enqueued_datas.begin();
qdi != _enqueued_datas.end();
++qdi) {
qpGeomVertexArrayData *data = (*qdi);
_enqueued_geoms.clear();
EnqueuedVertexBuffers::iterator qvbi;
for (qvbi = _enqueued_vertex_buffers.begin();
qvbi != _enqueued_vertex_buffers.end();
++qvbi) {
qpGeomVertexArrayData *data = (*qvbi);
data->prepare_now(this, gsg);
}
_enqueued_datas.clear();
_enqueued_vertex_buffers.clear();
EnqueuedIndexBuffers::iterator qibi;
for (qibi = _enqueued_index_buffers.begin();
qibi != _enqueued_index_buffers.end();
++qibi) {
qpGeomPrimitive *data = (*qibi);
data->prepare_now(this, gsg);
}
_enqueued_index_buffers.clear();
}

View File

@ -24,6 +24,7 @@
#include "texture.h"
#include "geom.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomPrimitive.h"
#include "pointerTo.h"
#include "pStatCollector.h"
#include "pset.h"
@ -31,7 +32,8 @@
class TextureContext;
class GeomContext;
class DataContext;
class VertexBufferContext;
class IndexBufferContext;
class GraphicsStateGuardianBase;
////////////////////////////////////////////////////////////////////
@ -72,13 +74,23 @@ public:
GeomContext *prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg);
void enqueue_data(qpGeomVertexArrayData *data);
bool dequeue_data(qpGeomVertexArrayData *data);
void release_data(DataContext *gc);
int release_all_datas();
void enqueue_vertex_buffer(qpGeomVertexArrayData *data);
bool dequeue_vertex_buffer(qpGeomVertexArrayData *data);
void release_vertex_buffer(VertexBufferContext *vbc);
int release_all_vertex_buffers();
DataContext *prepare_data_now(qpGeomVertexArrayData *data,
GraphicsStateGuardianBase *gsg);
VertexBufferContext *
prepare_vertex_buffer_now(qpGeomVertexArrayData *data,
GraphicsStateGuardianBase *gsg);
void enqueue_index_buffer(qpGeomPrimitive *data);
bool dequeue_index_buffer(qpGeomPrimitive *data);
void release_index_buffer(IndexBufferContext *ibc);
int release_all_index_buffers();
IndexBufferContext *
prepare_index_buffer_now(qpGeomPrimitive *data,
GraphicsStateGuardianBase *gsg);
void update(GraphicsStateGuardianBase *gsg);
@ -87,16 +99,20 @@ private:
typedef phash_set< PT(Texture) > EnqueuedTextures;
typedef phash_set<GeomContext *, pointer_hash> Geoms;
typedef phash_set< PT(Geom) > EnqueuedGeoms;
typedef phash_set<DataContext *, pointer_hash> Datas;
typedef phash_set< PT(qpGeomVertexArrayData) > EnqueuedDatas;
typedef phash_set<VertexBufferContext *, pointer_hash> VertexBuffers;
typedef phash_set< PT(qpGeomVertexArrayData) > EnqueuedVertexBuffers;
typedef phash_set<IndexBufferContext *, pointer_hash> IndexBuffers;
typedef phash_set< PT(qpGeomPrimitive) > EnqueuedIndexBuffers;
Mutex _lock;
Textures _prepared_textures, _released_textures;
EnqueuedTextures _enqueued_textures;
Geoms _prepared_geoms, _released_geoms;
EnqueuedGeoms _enqueued_geoms;
Datas _prepared_datas, _released_datas;
EnqueuedDatas _enqueued_datas;
VertexBuffers _prepared_vertex_buffers, _released_vertex_buffers;
EnqueuedVertexBuffers _enqueued_vertex_buffers;
IndexBuffers _prepared_index_buffers, _released_index_buffers;
EnqueuedIndexBuffers _enqueued_index_buffers;
static PStatCollector _total_texusage_pcollector;
static PStatCollector _total_buffers_pcollector;

View File

@ -17,6 +17,27 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_usage_hint
// Access: Published
// Description: Returns the usage hint for this primitive. See
// GeomUsageHint. This has nothing to do with the usage
// hint associated with the primitive's vertices; this
// only specifies how often the vertex indices that
// define the primitive will be modified.
//
// It is perfectly legal (and, in fact, common) for a
// GeomPrimitive to have UH_static on itself, while
// referencing vertex data with UH_dynamic. This means
// that the vertices themselves will be animated, but
// the primitive will always reference the same set of
// vertices from the pool.
////////////////////////////////////////////////////////////////////
INLINE qpGeomUsageHint::UsageHint qpGeomPrimitive::
get_usage_hint() const {
return _usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_shade_model
// Access: Published
@ -196,6 +217,31 @@ get_maxs() const {
return cdata->_maxs;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_data_size_bytes
// Access: Published
// Description: Returns the number of bytes stored in the vertices
// array.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_data_size_bytes() const {
CDReader cdata(_cycler);
return cdata->_vertices.size() * sizeof(short);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_modified
// Access: Published
// Description: Returns a sequence number which is guaranteed to
// change at least every time the vertex index array is
// modified.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq qpGeomPrimitive::
get_modified() const {
CDReader cdata(_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_vertex
// Access: Published

View File

@ -21,6 +21,7 @@
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexCacheManager.h"
#include "preparedGraphicsObjects.h"
#include "internalName.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -36,7 +37,9 @@ PStatCollector qpGeomPrimitive::_rotate_pcollector("Draw:Rotate");
// Description:
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
qpGeomPrimitive() {
qpGeomPrimitive(qpGeomUsageHint::UsageHint usage_hint) :
_usage_hint(usage_hint)
{
}
////////////////////////////////////////////////////////////////////
@ -47,6 +50,7 @@ qpGeomPrimitive() {
qpGeomPrimitive::
qpGeomPrimitive(const qpGeomPrimitive &copy) :
TypedWritableReferenceCount(copy),
_usage_hint(copy._usage_hint),
_cycler(copy._cycler)
{
}
@ -75,6 +79,8 @@ qpGeomPrimitive::
_cycler.release_write_stage(i, cdata);
}
}
release_all();
}
////////////////////////////////////////////////////////////////////
@ -527,6 +533,134 @@ clear_cache() {
cache_mgr->remove_primitive(this);
cdata->_decomposed = NULL;
}
// This, on the other hand, should be applied to the current
// pipeline stage.
++(cdata->_modified);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::prepare
// Access: Published
// Description: Indicates that the data should be enqueued to be
// prepared in the indicated prepared_objects at the
// beginning of the next frame. This will ensure the
// data is already loaded into the GSG if it is expected
// to be rendered soon.
//
// Use this function instead of prepare_now() to preload
// datas from a user interface standpoint.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
prepare(PreparedGraphicsObjects *prepared_objects) {
prepared_objects->enqueue_index_buffer(this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::prepare_now
// Access: Public
// Description: Creates a context for the data on the particular
// GSG, if it does not already exist. Returns the new
// (or old) IndexBufferContext. This assumes that the
// GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// datas. If this is not necessarily the case, you
// should use prepare() instead.
//
// Normally, this is not called directly except by the
// GraphicsStateGuardian; a data does not need to be
// explicitly prepared by the user before it may be
// rendered.
////////////////////////////////////////////////////////////////////
IndexBufferContext *qpGeomPrimitive::
prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg) {
Contexts::const_iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
return (*ci).second;
}
IndexBufferContext *ibc = prepared_objects->prepare_index_buffer_now(this, gsg);
if (ibc != (IndexBufferContext *)NULL) {
_contexts[prepared_objects] = ibc;
}
return ibc;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::release
// Access: Public
// Description: Frees the data context only on the indicated object,
// if it exists there. Returns true if it was released,
// false if it had not been prepared.
////////////////////////////////////////////////////////////////////
bool qpGeomPrimitive::
release(PreparedGraphicsObjects *prepared_objects) {
Contexts::iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
IndexBufferContext *ibc = (*ci).second;
prepared_objects->release_index_buffer(ibc);
return true;
}
// Maybe it wasn't prepared yet, but it's about to be.
return prepared_objects->dequeue_index_buffer(this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::release_all
// Access: Public
// Description: Frees the context allocated on all objects for which
// the data has been declared. Returns the number of
// contexts which have been freed.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
release_all() {
// We have to traverse a copy of the _contexts list, because the
// PreparedGraphicsObjects object will call clear_prepared() in response
// to each release_index_buffer(), and we don't want to be modifying the
// _contexts list while we're traversing it.
Contexts temp = _contexts;
int num_freed = (int)_contexts.size();
Contexts::const_iterator ci;
for (ci = temp.begin(); ci != temp.end(); ++ci) {
PreparedGraphicsObjects *prepared_objects = (*ci).first;
IndexBufferContext *ibc = (*ci).second;
prepared_objects->release_index_buffer(ibc);
}
// Now that we've called release_index_buffer() on every known context,
// the _contexts list should have completely emptied itself.
nassertr(_contexts.empty(), num_freed);
return num_freed;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::clear_prepared
// Access: Private
// Description: Removes the indicated PreparedGraphicsObjects table
// from the data array's table, without actually
// releasing the data array. This is intended to be
// called only from
// PreparedGraphicsObjects::release_index_buffer(); it should
// never be called by user code.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
clear_prepared(PreparedGraphicsObjects *prepared_objects) {
Contexts::iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
_contexts.erase(ci);
} else {
// If this assertion fails, clear_prepared() was given a
// prepared_objects which the data array didn't know about.
nassertv(false);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -20,8 +20,10 @@
#define qpGEOMPRIMITIVE_H
#include "pandabase.h"
#include "qpgeomUsageHint.h"
#include "typedWritableReferenceCount.h"
#include "luse.h"
#include "updateSeq.h"
#include "pointerTo.h"
#include "pta_ushort.h"
#include "pta_int.h"
@ -32,8 +34,9 @@
#include "pipelineCycler.h"
class qpGeomVertexData;
class PreparedGraphicsObjects;
class IndexBufferContext;
class GraphicsStateGuardianBase;
class GeomContext;
class FactoryParams;
////////////////////////////////////////////////////////////////////
@ -61,7 +64,7 @@ class FactoryParams;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomPrimitive : public TypedWritableReferenceCount {
PUBLISHED:
qpGeomPrimitive();
qpGeomPrimitive(qpGeomUsageHint::UsageHint usage_hint);
qpGeomPrimitive(const qpGeomPrimitive &copy);
virtual ~qpGeomPrimitive();
@ -88,6 +91,8 @@ PUBLISHED:
SM_flat_last_vertex,
};
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
INLINE ShadeModel get_shade_model() const;
INLINE void set_shade_model(ShadeModel shade_model);
@ -112,6 +117,8 @@ PUBLISHED:
INLINE CPTA_ushort get_maxs() const;
int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
INLINE int get_min_vertex() const;
INLINE int get_min_vertex(int i) const;
@ -132,6 +139,17 @@ PUBLISHED:
void clear_cache();
void prepare(PreparedGraphicsObjects *prepared_objects);
public:
IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
public:
virtual void draw(GraphicsStateGuardianBase *gsg) const=0;
@ -151,6 +169,16 @@ protected:
static PStatCollector _rotate_pcollector;
private:
qpGeomUsageHint::UsageHint _usage_hint;
// A GeomPrimitive keeps a list (actually, a map) of all the
// PreparedGraphicsObjects tables that it has been prepared into.
// Each PGO conversely keeps a list (a set) of all the Geoms that
// have been prepared there. When either destructs, it removes
// itself from the other's list.
typedef pmap<PreparedGraphicsObjects *, IndexBufferContext *> Contexts;
Contexts _contexts;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
@ -167,6 +195,7 @@ private:
PTA_int _ends;
PTA_ushort _mins;
PTA_ushort _maxs;
UpdateSeq _modified;
bool _got_minmax;
unsigned short _min_vertex;
@ -206,6 +235,7 @@ private:
friend class qpGeom;
friend class qpGeomVertexCacheManager;
friend class PreparedGraphicsObjects;
};
#include "qpgeomPrimitive.I"

View File

@ -29,7 +29,9 @@ TypeHandle qpGeomTriangles::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTriangles::
qpGeomTriangles() {
qpGeomTriangles(qpGeomUsageHint::UsageHint usage_hint) :
qpGeomPrimitive(usage_hint)
{
}
////////////////////////////////////////////////////////////////////
@ -158,7 +160,7 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTriangles::
make_from_bam(const FactoryParams &params) {
qpGeomTriangles *object = new qpGeomTriangles;
qpGeomTriangles *object = new qpGeomTriangles(qpGeomUsageHint::UH_client);
DatagramIterator scan;
BamReader *manager;

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTriangles : public qpGeomPrimitive {
PUBLISHED:
qpGeomTriangles();
qpGeomTriangles(qpGeomUsageHint::UsageHint usage_hint);
qpGeomTriangles(const qpGeomTriangles &copy);
virtual ~qpGeomTriangles();

View File

@ -29,7 +29,9 @@ TypeHandle qpGeomTrifans::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTrifans::
qpGeomTrifans() {
qpGeomTrifans(qpGeomUsageHint::UsageHint usage_hint) :
qpGeomPrimitive(usage_hint)
{
}
////////////////////////////////////////////////////////////////////
@ -89,7 +91,7 @@ draw(GraphicsStateGuardianBase *gsg) const {
////////////////////////////////////////////////////////////////////
CPT(qpGeomPrimitive) qpGeomTrifans::
decompose_impl() const {
PT(qpGeomTriangles) triangles = new qpGeomTriangles;
PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint());
triangles->set_shade_model(get_shade_model());
CPTA_ushort vertices = get_vertices();
CPTA_int ends = get_ends();
@ -154,7 +156,7 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTrifans::
make_from_bam(const FactoryParams &params) {
qpGeomTrifans *object = new qpGeomTrifans;
qpGeomTrifans *object = new qpGeomTrifans(qpGeomUsageHint::UH_client);
DatagramIterator scan;
BamReader *manager;

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTrifans : public qpGeomPrimitive {
PUBLISHED:
qpGeomTrifans();
qpGeomTrifans(qpGeomUsageHint::UsageHint usage_hint);
qpGeomTrifans(const qpGeomTrifans &copy);
virtual ~qpGeomTrifans();

View File

@ -30,7 +30,9 @@ TypeHandle qpGeomTristrips::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTristrips::
qpGeomTristrips() {
qpGeomTristrips(qpGeomUsageHint::UsageHint usage_hint) :
qpGeomPrimitive(usage_hint)
{
}
////////////////////////////////////////////////////////////////////
@ -90,7 +92,7 @@ draw(GraphicsStateGuardianBase *gsg) const {
////////////////////////////////////////////////////////////////////
CPT(qpGeomPrimitive) qpGeomTristrips::
decompose_impl() const {
PT(qpGeomTriangles) triangles = new qpGeomTriangles;
PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint());
triangles->set_shade_model(get_shade_model());
CPTA_ushort vertices = get_vertices();
CPTA_int ends = get_ends();
@ -240,7 +242,7 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTristrips::
make_from_bam(const FactoryParams &params) {
qpGeomTristrips *object = new qpGeomTristrips;
qpGeomTristrips *object = new qpGeomTristrips(qpGeomUsageHint::UH_client);
DatagramIterator scan;
BamReader *manager;

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTristrips : public qpGeomPrimitive {
PUBLISHED:
qpGeomTristrips();
qpGeomTristrips(qpGeomUsageHint::UsageHint usage_hint);
qpGeomTristrips(const qpGeomTristrips &copy);
virtual ~qpGeomTristrips();

View File

@ -0,0 +1,77 @@
// Filename: qpgeomUsageHint.h
// Created by: drose (18Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMUSAGEHINT_H
#define qpGEOMUSAGEHINT_H
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomUsageHint
// Description : This class exists just to provide scoping for the
// UsageHint enumerated type, which is used by
// GeomVertexData, GeomVertexArrayData, and
// GeomPrimitive.
//
// The usage hint describes to the rendering backend how
// often the data in question will be modified and/or
// rendered. It allows the backend to make appropriate
// choices about what part of memory the data should be
// stored in.
//
// The hint is provided as a performance optimization
// only, and does not constraing actual usage; although
// it may be an important optimization.
//
// In general, the hint may only be specified at the
// time the data object is constructed. If you need to
// change it, you must create a new object (but in many
// cases you can just assign the same internal data
// pointer to the new object, to keep the same
// client-side memory).
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomUsageHint {
PUBLISHED:
enum UsageHint {
// UH_client: don't attempt to upload the data; always keep it on
// the client.
UH_client,
// UH_stream: the data will be created once, used to render a few
// times, and then discarded. This should be used for short-lived
// temporary arrays.
UH_stream,
// UH_static: the data will be created once, and used to render
// many times, without modification. This is the most common
// case, since typically vertex data is not directly animated
// (this is not related to scene graph animation, e.g. from
// adjusting transforms on a node).
UH_static,
// UH_dynamic: the data will be repeatedly modified and
// re-rendered. This is for data that will be modified at
// runtime, such as animated or soft-skinned vertices.
UH_dynamic,
};
};
#endif

View File

@ -32,17 +32,9 @@ get_array_format() const {
// Access: Published
// Description: Returns the usage hint that describes to the
// rendering backend how often the vertex data will be
// modified and/or rendered. This is provided as a
// performance optimization only, and does not
// constraing actual usage; although it may be an
// important optimization.
//
// This may only be specified to the GeomVertexArrayData
// constructor. If you need to change it, you must
// create a new GeomVertexArrayData object (but you can
// just assign the same data pointer to the new object).
// modified and/or rendered. See GeomUsageHint.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData::UsageHint qpGeomVertexArrayData::
INLINE qpGeomUsageHint::UsageHint qpGeomVertexArrayData::
get_usage_hint() const {
return _usage_hint;
}
@ -107,7 +99,7 @@ set_data(CPTA_uchar array) {
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayData::
get_num_vertices() const {
return get_num_bytes() / _array_format->get_stride();
return get_data_size_bytes() / _array_format->get_stride();
}
////////////////////////////////////////////////////////////////////
@ -122,12 +114,12 @@ clear_vertices() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::get_num_bytes
// Function: qpGeomVertexArrayData::get_data_size_bytes
// Access: Published
// Description: Returns the number of bytes stored in the array.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayData::
get_num_bytes() const {
get_data_size_bytes() const {
CDReader cdata(_cycler);
return cdata->_data.size();
}

View File

@ -41,7 +41,7 @@ qpGeomVertexArrayData() {
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayData::
qpGeomVertexArrayData(const qpGeomVertexArrayFormat *array_format,
qpGeomVertexArrayData::UsageHint usage_hint) :
qpGeomUsageHint::UsageHint usage_hint) :
_array_format(array_format),
_usage_hint(usage_hint)
{
@ -147,7 +147,7 @@ set_num_vertices(int n) {
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayData::
prepare(PreparedGraphicsObjects *prepared_objects) {
prepared_objects->enqueue_data(this);
prepared_objects->enqueue_vertex_buffer(this);
}
////////////////////////////////////////////////////////////////////
@ -155,7 +155,7 @@ prepare(PreparedGraphicsObjects *prepared_objects) {
// Access: Public
// Description: Creates a context for the data on the particular
// GSG, if it does not already exist. Returns the new
// (or old) DataContext. This assumes that the
// (or old) VertexBufferContext. This assumes that the
// GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// datas. If this is not necessarily the case, you
@ -166,7 +166,7 @@ prepare(PreparedGraphicsObjects *prepared_objects) {
// explicitly prepared by the user before it may be
// rendered.
////////////////////////////////////////////////////////////////////
DataContext *qpGeomVertexArrayData::
VertexBufferContext *qpGeomVertexArrayData::
prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg) {
Contexts::const_iterator ci;
@ -175,11 +175,11 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
return (*ci).second;
}
DataContext *dc = prepared_objects->prepare_data_now(this, gsg);
if (dc != (DataContext *)NULL) {
_contexts[prepared_objects] = dc;
VertexBufferContext *vbc = prepared_objects->prepare_vertex_buffer_now(this, gsg);
if (vbc != (VertexBufferContext *)NULL) {
_contexts[prepared_objects] = vbc;
}
return dc;
return vbc;
}
////////////////////////////////////////////////////////////////////
@ -194,13 +194,13 @@ release(PreparedGraphicsObjects *prepared_objects) {
Contexts::iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
DataContext *dc = (*ci).second;
prepared_objects->release_data(dc);
VertexBufferContext *vbc = (*ci).second;
prepared_objects->release_vertex_buffer(vbc);
return true;
}
// Maybe it wasn't prepared yet, but it's about to be.
return prepared_objects->dequeue_data(this);
return prepared_objects->dequeue_vertex_buffer(this);
}
////////////////////////////////////////////////////////////////////
@ -214,7 +214,7 @@ int qpGeomVertexArrayData::
release_all() {
// We have to traverse a copy of the _contexts list, because the
// PreparedGraphicsObjects object will call clear_prepared() in response
// to each release_data(), and we don't want to be modifying the
// to each release_vertex_buffer(), and we don't want to be modifying the
// _contexts list while we're traversing it.
Contexts temp = _contexts;
int num_freed = (int)_contexts.size();
@ -222,11 +222,11 @@ release_all() {
Contexts::const_iterator ci;
for (ci = temp.begin(); ci != temp.end(); ++ci) {
PreparedGraphicsObjects *prepared_objects = (*ci).first;
DataContext *dc = (*ci).second;
prepared_objects->release_data(dc);
VertexBufferContext *vbc = (*ci).second;
prepared_objects->release_vertex_buffer(vbc);
}
// Now that we've called release_data() on every known context,
// Now that we've called release_vertex_buffer() on every known context,
// the _contexts list should have completely emptied itself.
nassertr(_contexts.empty(), num_freed);
@ -240,7 +240,7 @@ release_all() {
// from the data array's table, without actually
// releasing the data array. This is intended to be
// called only from
// PreparedGraphicsObjects::release_data(); it should
// PreparedGraphicsObjects::release_vertex_buffer(); it should
// never be called by user code.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayData::

View File

@ -22,6 +22,7 @@
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomUsageHint.h"
#include "pta_uchar.h"
#include "updateSeq.h"
#include "cycleData.h"
@ -31,7 +32,7 @@
#include "pmap.h"
class PreparedGraphicsObjects;
class DataContext;
class VertexBufferContext;
class GraphicsStateGuardianBase;
////////////////////////////////////////////////////////////////////
@ -53,26 +54,8 @@ private:
qpGeomVertexArrayData();
PUBLISHED:
enum UsageHint {
// UH_client: don't attempt to upload the data as a "vertex
// buffer"; always keep it on the client.
UH_client,
// UH_stream: the data will be created once, used to render a few
// times, and then discarded.
UH_stream,
// UH_static: the data will be created once, and used to render
// many times, without modification.
UH_static,
// UH_dynamic: the data will be repeatedly modified and
// re-rendered.
UH_dynamic,
};
qpGeomVertexArrayData(const qpGeomVertexArrayFormat *array_format,
UsageHint usage_hint);
qpGeomUsageHint::UsageHint usage_hint);
qpGeomVertexArrayData(const qpGeomVertexArrayData &copy);
private:
void operator = (const qpGeomVertexArrayData &copy);
@ -80,7 +63,7 @@ PUBLISHED:
virtual ~qpGeomVertexArrayData();
INLINE const qpGeomVertexArrayFormat *get_array_format() const;
INLINE UsageHint get_usage_hint() const;
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
INLINE CPTA_uchar get_data() const;
INLINE PTA_uchar modify_data();
@ -90,14 +73,14 @@ PUBLISHED:
bool set_num_vertices(int n);
INLINE void clear_vertices();
INLINE int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
public:
DataContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
VertexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
@ -105,14 +88,14 @@ private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
CPT(qpGeomVertexArrayFormat) _array_format;
UsageHint _usage_hint;
qpGeomUsageHint::UsageHint _usage_hint;
// A GeomVertexArrayData keeps a list (actually, a map) of all the
// PreparedGraphicsObjects tables that it has been prepared into.
// Each PGO conversely keeps a list (a set) of all the Geoms that
// have been prepared there. When either destructs, it removes
// itself from the other's list.
typedef pmap<PreparedGraphicsObjects *, DataContext *> Contexts;
typedef pmap<PreparedGraphicsObjects *, VertexBufferContext *> Contexts;
Contexts _contexts;
// This is the data that must be cycled between pipeline stages.

View File

@ -33,14 +33,16 @@ get_format() const {
// Access: Published
// Description: Returns the usage hint that was passed to the
// constructor, and which will be passed to each array
// data object created initially. However, each
// individual array may be replaced with a different
// array object with an independent usage hint
// specified.
// data object created initially, and arrays created as
// the result of a convert_to() operation. See
// GeomUsageHint.
//
// See GeomVertexArrayData::get_usage_hint().
// However, each individual array may be replaced with a
// different array object with an independent usage hint
// specified, so there is no guarantee that the
// individual arrays all have the same usage_hint.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData::UsageHint qpGeomVertexData::
INLINE qpGeomUsageHint::UsageHint qpGeomVertexData::
get_usage_hint() const {
return _usage_hint;
}

View File

@ -44,7 +44,7 @@ qpGeomVertexData() {
////////////////////////////////////////////////////////////////////
qpGeomVertexData::
qpGeomVertexData(const qpGeomVertexFormat *format,
qpGeomVertexArrayData::UsageHint usage_hint) :
qpGeomUsageHint::UsageHint usage_hint) :
_format(format),
_usage_hint(usage_hint)
{
@ -132,7 +132,7 @@ get_num_vertices() const {
// Look up the answer on the first array (since any array will do).
int stride = _format->get_array(0)->get_stride();
return cdata->_arrays[0]->get_num_bytes() / stride;
return cdata->_arrays[0]->get_data_size_bytes() / stride;
}
////////////////////////////////////////////////////////////////////
@ -211,7 +211,7 @@ get_num_bytes() const {
Arrays::const_iterator ai;
for (ai = cdata->_arrays.begin(); ai != cdata->_arrays.end(); ++ai) {
num_bytes += (*ai)->get_num_bytes();
num_bytes += (*ai)->get_data_size_bytes();
}
return num_bytes;
@ -405,7 +405,7 @@ set_data(int array, const qpGeomVertexDataType *data_type,
{
CDReader cdata(_cycler);
int array_size = (int)cdata->_arrays[array]->get_num_bytes();
int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
if (element + data_type->get_total_bytes() > array_size) {
// Whoops, we need more vertices!
CDWriter cdataw(_cycler, cdata);

View File

@ -24,6 +24,7 @@
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomUsageHint.h"
#include "internalName.h"
#include "cycleData.h"
#include "cycleDataReader.h"
@ -63,13 +64,13 @@ private:
qpGeomVertexData();
PUBLISHED:
qpGeomVertexData(const qpGeomVertexFormat *format,
qpGeomVertexArrayData::UsageHint usage_hint);
qpGeomUsageHint::UsageHint usage_hint);
qpGeomVertexData(const qpGeomVertexData &copy);
void operator = (const qpGeomVertexData &copy);
virtual ~qpGeomVertexData();
INLINE const qpGeomVertexFormat *get_format() const;
INLINE qpGeomVertexArrayData::UsageHint get_usage_hint() const;
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
int get_num_vertices() const;
INLINE bool set_num_vertices(int n);
@ -113,7 +114,7 @@ private:
private:
CPT(qpGeomVertexFormat) _format;
qpGeomVertexArrayData::UsageHint _usage_hint;
qpGeomUsageHint::UsageHint _usage_hint;
typedef pvector< PT(qpGeomVertexArrayData) > Arrays;

View File

@ -0,0 +1,91 @@
// Filename: vertexBufferContext.I
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexBufferContext::
VertexBufferContext(qpGeomVertexArrayData *data) :
_data(data),
// Initially, the number of bytes is zero, until the data has been
// loaded (and mark_loaded() is called).
_data_size_bytes(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::get_data
// Access: Public
// Description: Returns the pointer to the client-side array data
// object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData *VertexBufferContext::
get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::get_data_size_bytes
// Access: Public
// Description: Returns the number of bytes previously reported for
// the data object. This is used to track changes in
// the data object's allocated size; if it changes from
// this, we need to create a new buffer.
////////////////////////////////////////////////////////////////////
INLINE int VertexBufferContext::
get_data_size_bytes() const {
return _data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::changed_size
// Access: Public
// Description: Returns true if the data has changed size since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
changed_size() const {
return get_data_size_bytes() != _data->get_data_size_bytes();
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::was_modified
// Access: Public
// Description: Returns true if the data has been modified since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
was_modified() const {
return _modified != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::mark_loaded
// Access: Public
// Description: Should be called after the VertexBufferContext has been
// loaded into graphics memory, this updates the
// internal flags for changed_size() and modified().
////////////////////////////////////////////////////////////////////
INLINE void VertexBufferContext::
mark_loaded() {
_data_size_bytes = _data->get_data_size_bytes();
_modified = _data->get_modified();
}

View File

@ -0,0 +1,21 @@
// Filename: vertexBufferContext.cxx
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "vertexBufferContext.h"
TypeHandle VertexBufferContext::_type_handle;

View File

@ -1,4 +1,4 @@
// Filename: dataContext.h
// Filename: vertexBufferContext.h
// Created by: drose (17Mar05)
//
////////////////////////////////////////////////////////////////////
@ -16,8 +16,8 @@
//
////////////////////////////////////////////////////////////////////
#ifndef DATACONTEXT_H
#define DATACONTEXT_H
#ifndef VERTEXBUFFERCONTEXT_H
#define VERTEXBUFFERCONTEXT_H
#include "pandabase.h"
@ -26,7 +26,7 @@
#include "qpgeomVertexArrayData.h"
////////////////////////////////////////////////////////////////////
// Class : DataContext
// Class : VertexBufferContext
// Description : This is a special class object that holds all the
// information returned by a particular GSG to indicate
// the vertex data array's internal context identifier.
@ -36,13 +36,13 @@
// allocate a vertex buffer for the array. OpenGL can
// create a buffer object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DataContext : public SavedContext {
class EXPCL_PANDA VertexBufferContext : public SavedContext {
public:
INLINE DataContext(qpGeomVertexArrayData *data);
INLINE VertexBufferContext(qpGeomVertexArrayData *data);
INLINE qpGeomVertexArrayData *get_data() const;
INLINE int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
INLINE bool changed_size() const;
INLINE bool was_modified() const;
@ -50,11 +50,11 @@ public:
private:
// This cannot be a PT(qpGeomVertexArrayData), because the data and
// the GSG both own their DataContexts! That would create a
// the GSG both own their VertexBufferContexts! That would create a
// circular reference count.
qpGeomVertexArrayData *_data;
UpdateSeq _modified;
int _num_bytes;
int _data_size_bytes;
public:
static TypeHandle get_class_type() {
@ -62,7 +62,7 @@ public:
}
static void init_type() {
SavedContext::init_type();
register_type(_type_handle, "DataContext",
register_type(_type_handle, "VertexBufferContext",
SavedContext::get_class_type());
}
virtual TypeHandle get_type() const {
@ -76,7 +76,7 @@ private:
friend class PreparedGraphicsObjects;
};
#include "dataContext.I"
#include "vertexBufferContext.I"
#endif

View File

@ -30,7 +30,8 @@ class RenderBuffer;
class GraphicsWindow;
class NodePath;
class DataContext;
class VertexBufferContext;
class IndexBufferContext;
class GeomContext;
class GeomNode;
class Geom;
@ -46,6 +47,7 @@ class GeomTrifan;
class GeomSphere;
class qpGeomVertexData;
class qpGeomVertexArrayData;
class qpGeomPrimitive;
class qpGeomTriangles;
class qpGeomTristrips;
class qpGeomTrifans;
@ -134,8 +136,11 @@ public:
virtual GeomContext *prepare_geom(Geom *geom)=0;
virtual void release_geom(GeomContext *gc)=0;
virtual DataContext *prepare_data(qpGeomVertexArrayData *data)=0;
virtual void release_data(DataContext *gc)=0;
virtual VertexBufferContext *prepare_vertex_buffer(qpGeomVertexArrayData *data)=0;
virtual void release_vertex_buffer(VertexBufferContext *vbc)=0;
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data)=0;
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state)=0;

View File

@ -153,7 +153,8 @@ static LevelCollectorProperties level_properties[] = {
{ 1, "Prepared Geoms:Active", { 0.5, 1.0, 0.8 } },
{ 1, "Prepared GeomNodes", { 1.0, 0.0, 0.5 }, "", 500 },
{ 1, "Prepared GeomNodes:Active", { 0.5, 1.0, 0.8 } },
{ 1, "Vertex buffers:Active", { 1.0, 0.0, 0.5 } },
{ 1, "Vertex buffers:Active vertex", { 1.0, 0.0, 0.5 } },
{ 1, "Vertex buffers:Active index" , { 0.5, 0.6, 1.0 } },
{ 1, "Vertex buffers", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 },
{ 1, "Vertices", { 0.5, 0.2, 0.0 }, "K", 10, 1000 },
{ 1, "Vertices:Other", { 0.2, 0.2, 0.2 } },