From dbed74e410b142cbf1a0e3b1e587d53420f2ff67 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 18 Mar 2005 20:18:57 +0000 Subject: [PATCH] ibuffers as well as vbuffers --- panda/src/display/graphicsStateGuardian.cxx | 87 +++-- panda/src/display/graphicsStateGuardian.h | 16 +- panda/src/dxgsg8/Sources.pp | 4 +- panda/src/dxgsg8/config_dxgsg8.cxx | 4 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 62 ++-- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 6 +- ...ataContext8.I => dxVertexBufferContext8.I} | 2 +- ...ontext8.cxx => dxVertexBufferContext8.cxx} | 36 +- ...ataContext8.h => dxVertexBufferContext8.h} | 24 +- panda/src/dxgsg8/dxgsg8_composite1.cxx | 2 +- panda/src/egg2pg/eggLoader.cxx | 6 +- panda/src/framework/windowFramework.cxx | 8 +- panda/src/glstuff/Sources.pp | 9 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 250 +++++++++---- .../src/glstuff/glGraphicsStateGuardian_src.h | 13 +- ...ntext_src.I => glIndexBufferContext_src.I} | 10 +- ...t_src.cxx => glIndexBufferContext_src.cxx} | 4 +- panda/src/glstuff/glIndexBufferContext_src.h | 53 +++ panda/src/glstuff/glVertexBufferContext_src.I | 30 ++ .../glVertexBufferContext_src.cxx} | 6 +- ...text_src.h => glVertexBufferContext_src.h} | 18 +- panda/src/glstuff/glmisc_src.cxx | 3 +- panda/src/glstuff/glstuff_src.cxx | 3 +- panda/src/glstuff/glstuff_src.h | 3 +- panda/src/gobj/Sources.pp | 18 +- panda/src/gobj/config_gobj.cxx | 6 +- panda/src/gobj/gobj_composite1.cxx | 1 - panda/src/gobj/gobj_composite2.cxx | 6 +- .../{dataContext.I => indexBufferContext.I} | 40 +-- panda/src/gobj/indexBufferContext.cxx | 21 ++ panda/src/gobj/indexBufferContext.h | 82 +++++ panda/src/gobj/preparedGraphicsObjects.cxx | 333 ++++++++++++++---- panda/src/gobj/preparedGraphicsObjects.h | 38 +- panda/src/gobj/qpgeomPrimitive.I | 46 +++ panda/src/gobj/qpgeomPrimitive.cxx | 136 ++++++- panda/src/gobj/qpgeomPrimitive.h | 34 +- panda/src/gobj/qpgeomTriangles.cxx | 6 +- panda/src/gobj/qpgeomTriangles.h | 2 +- panda/src/gobj/qpgeomTrifans.cxx | 8 +- panda/src/gobj/qpgeomTrifans.h | 2 +- panda/src/gobj/qpgeomTristrips.cxx | 8 +- panda/src/gobj/qpgeomTristrips.h | 2 +- panda/src/gobj/qpgeomUsageHint.h | 77 ++++ panda/src/gobj/qpgeomVertexArrayData.I | 18 +- panda/src/gobj/qpgeomVertexArrayData.cxx | 32 +- panda/src/gobj/qpgeomVertexArrayData.h | 35 +- panda/src/gobj/qpgeomVertexData.I | 14 +- panda/src/gobj/qpgeomVertexData.cxx | 8 +- panda/src/gobj/qpgeomVertexData.h | 7 +- panda/src/gobj/vertexBufferContext.I | 91 +++++ panda/src/gobj/vertexBufferContext.cxx | 21 ++ .../{dataContext.h => vertexBufferContext.h} | 22 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 11 +- panda/src/pstatclient/pStatProperties.cxx | 3 +- 54 files changed, 1380 insertions(+), 407 deletions(-) rename panda/src/dxgsg8/{dxDataContext8.I => dxVertexBufferContext8.I} (94%) rename panda/src/dxgsg8/{dxDataContext8.cxx => dxVertexBufferContext8.cxx} (82%) rename panda/src/dxgsg8/{dxDataContext8.h => dxVertexBufferContext8.h} (72%) rename panda/src/glstuff/{glDataContext_src.I => glIndexBufferContext_src.I} (80%) rename panda/src/glstuff/{glDataContext_src.cxx => glIndexBufferContext_src.cxx} (87%) create mode 100644 panda/src/glstuff/glIndexBufferContext_src.h create mode 100644 panda/src/glstuff/glVertexBufferContext_src.I rename panda/src/{gobj/dataContext.cxx => glstuff/glVertexBufferContext_src.cxx} (87%) rename panda/src/glstuff/{glDataContext_src.h => glVertexBufferContext_src.h} (73%) rename panda/src/gobj/{dataContext.I => indexBufferContext.I} (76%) create mode 100644 panda/src/gobj/indexBufferContext.cxx create mode 100644 panda/src/gobj/indexBufferContext.h create mode 100644 panda/src/gobj/qpgeomUsageHint.h create mode 100644 panda/src/gobj/vertexBufferContext.I create mode 100644 panda/src/gobj/vertexBufferContext.cxx rename panda/src/gobj/{dataContext.h => vertexBufferContext.h} (81%) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 5118288f33..50c0349c39 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -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()); } } } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index f4747ee671..ecf2fa070c 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -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 _current_textures; pset _current_geoms; - pset _current_datas; + pset _current_vertex_buffers; + pset _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; diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp index b0ae6dbf9a..9ea74d6dfe 100644 --- a/panda/src/dxgsg8/Sources.pp +++ b/panda/src/dxgsg8/Sources.pp @@ -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 \ diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index 4f490f3fea..da27198918 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -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(); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index c340398c5f..b2e432dbdb 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -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; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index fe62fa0f8e..af0266db54 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -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); diff --git a/panda/src/dxgsg8/dxDataContext8.I b/panda/src/dxgsg8/dxVertexBufferContext8.I similarity index 94% rename from panda/src/dxgsg8/dxDataContext8.I rename to panda/src/dxgsg8/dxVertexBufferContext8.I index bf3f65af53..7acfc79052 100644 --- a/panda/src/dxgsg8/dxDataContext8.I +++ b/panda/src/dxgsg8/dxVertexBufferContext8.I @@ -1,4 +1,4 @@ -// Filename: dxDataContext8.I +// Filename: dxVertexBufferContext8.I // Created by: drose (18Mar05) // //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/dxDataContext8.cxx b/panda/src/dxgsg8/dxVertexBufferContext8.cxx similarity index 82% rename from panda/src/dxgsg8/dxDataContext8.cxx rename to panda/src/dxgsg8/dxVertexBufferContext8.cxx index 37d1dfd093..495a1b2241 100644 --- a/panda/src/dxgsg8/dxDataContext8.cxx +++ b/panda/src/dxgsg8/dxVertexBufferContext8.cxx @@ -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 -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(); } diff --git a/panda/src/dxgsg8/dxDataContext8.h b/panda/src/dxgsg8/dxVertexBufferContext8.h similarity index 72% rename from panda/src/dxgsg8/dxDataContext8.h rename to panda/src/dxgsg8/dxVertexBufferContext8.h index e69dbac78c..5410016268 100644 --- a/panda/src/dxgsg8/dxDataContext8.h +++ b/panda/src/dxgsg8/dxVertexBufferContext8.h @@ -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 diff --git a/panda/src/dxgsg8/dxgsg8_composite1.cxx b/panda/src/dxgsg8/dxgsg8_composite1.cxx index f9fb485380..93f83e8aec 100644 --- a/panda/src/dxgsg8/dxgsg8_composite1.cxx +++ b/panda/src/dxgsg8/dxgsg8_composite1.cxx @@ -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" diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index ba048d6b96..b89abb9cf5 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -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) { diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index cba12c1e90..46d7d243bf 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -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(); diff --git a/panda/src/glstuff/Sources.pp b/panda/src/glstuff/Sources.pp index 65b4360a81..39cc12ee68 100644 --- a/panda/src/glstuff/Sources.pp +++ b/panda/src/glstuff/Sources.pp @@ -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 \ diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 55801194b8..a0c6801e04 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -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; } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 57d4dc1386..fcaba3e851 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -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(); diff --git a/panda/src/glstuff/glDataContext_src.I b/panda/src/glstuff/glIndexBufferContext_src.I similarity index 80% rename from panda/src/glstuff/glDataContext_src.I rename to panda/src/glstuff/glIndexBufferContext_src.I index ea3f8b5077..408e4c801d 100644 --- a/panda/src/glstuff/glDataContext_src.I +++ b/panda/src/glstuff/glIndexBufferContext_src.I @@ -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; } diff --git a/panda/src/glstuff/glDataContext_src.cxx b/panda/src/glstuff/glIndexBufferContext_src.cxx similarity index 87% rename from panda/src/glstuff/glDataContext_src.cxx rename to panda/src/glstuff/glIndexBufferContext_src.cxx index 605db7e623..1859fed374 100644 --- a/panda/src/glstuff/glDataContext_src.cxx +++ b/panda/src/glstuff/glIndexBufferContext_src.cxx @@ -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; diff --git a/panda/src/glstuff/glIndexBufferContext_src.h b/panda/src/glstuff/glIndexBufferContext_src.h new file mode 100644 index 0000000000..76f921eba5 --- /dev/null +++ b/panda/src/glstuff/glIndexBufferContext_src.h @@ -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" + diff --git a/panda/src/glstuff/glVertexBufferContext_src.I b/panda/src/glstuff/glVertexBufferContext_src.I new file mode 100644 index 0000000000..a298d784ca --- /dev/null +++ b/panda/src/glstuff/glVertexBufferContext_src.I @@ -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; +} diff --git a/panda/src/gobj/dataContext.cxx b/panda/src/glstuff/glVertexBufferContext_src.cxx similarity index 87% rename from panda/src/gobj/dataContext.cxx rename to panda/src/glstuff/glVertexBufferContext_src.cxx index 2844754deb..6ab09e42cf 100644 --- a/panda/src/gobj/dataContext.cxx +++ b/panda/src/glstuff/glVertexBufferContext_src.cxx @@ -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; diff --git a/panda/src/glstuff/glDataContext_src.h b/panda/src/glstuff/glVertexBufferContext_src.h similarity index 73% rename from panda/src/glstuff/glDataContext_src.h rename to panda/src/glstuff/glVertexBufferContext_src.h index dd1fb61423..516eac056b 100644 --- a/panda/src/glstuff/glDataContext_src.h +++ b/panda/src/glstuff/glVertexBufferContext_src.h @@ -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" diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 4747d53e2c..a73a37995b 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -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); diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index cb420cf01c..28fad5e0b7 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -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" diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index 998ba44c24..d1a7d38973 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -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" diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 845f422377..3e7975c660 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -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 diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 49d98a2fcc..6783266d9f 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -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(); diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index a41098d5e1..e1169a0e5f 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -1,6 +1,5 @@ #include "boundedObject.cxx" -#include "dataContext.cxx" #include "geom.cxx" #include "geomLine.cxx" #include "geomLinestrip.cxx" diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index c8f210dbd5..c86de9bd1d 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -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" diff --git a/panda/src/gobj/dataContext.I b/panda/src/gobj/indexBufferContext.I similarity index 76% rename from panda/src/gobj/dataContext.I rename to panda/src/gobj/indexBufferContext.I index 461b846e3c..4f603ebf46 100644 --- a/panda/src/gobj/dataContext.I +++ b/panda/src/gobj/indexBufferContext.I @@ -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(); } diff --git a/panda/src/gobj/indexBufferContext.cxx b/panda/src/gobj/indexBufferContext.cxx new file mode 100644 index 0000000000..3780f79b42 --- /dev/null +++ b/panda/src/gobj/indexBufferContext.cxx @@ -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; diff --git a/panda/src/gobj/indexBufferContext.h b/panda/src/gobj/indexBufferContext.h new file mode 100644 index 0000000000..25cd54e489 --- /dev/null +++ b/panda/src/gobj/indexBufferContext.h @@ -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 + diff --git a/panda/src/gobj/preparedGraphicsObjects.cxx b/panda/src/gobj/preparedGraphicsObjects.cxx index 689da0e6f2..7fda50d9d6 100644 --- a/panda/src/gobj/preparedGraphicsObjects.cxx +++ b/panda/src/gobj/preparedGraphicsObjects.cxx @@ -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(); } diff --git a/panda/src/gobj/preparedGraphicsObjects.h b/panda/src/gobj/preparedGraphicsObjects.h index 7a9198ce20..f6b39cb606 100644 --- a/panda/src/gobj/preparedGraphicsObjects.h +++ b/panda/src/gobj/preparedGraphicsObjects.h @@ -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 Geoms; typedef phash_set< PT(Geom) > EnqueuedGeoms; - typedef phash_set Datas; - typedef phash_set< PT(qpGeomVertexArrayData) > EnqueuedDatas; + typedef phash_set VertexBuffers; + typedef phash_set< PT(qpGeomVertexArrayData) > EnqueuedVertexBuffers; + typedef phash_set 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; diff --git a/panda/src/gobj/qpgeomPrimitive.I b/panda/src/gobj/qpgeomPrimitive.I index abcaf7a40a..abb14e212f 100644 --- a/panda/src/gobj/qpgeomPrimitive.I +++ b/panda/src/gobj/qpgeomPrimitive.I @@ -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 diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index f918173698..68ba6845ee 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -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 ©) : 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); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomPrimitive.h b/panda/src/gobj/qpgeomPrimitive.h index a4dbefd059..edfd154c70 100644 --- a/panda/src/gobj/qpgeomPrimitive.h +++ b/panda/src/gobj/qpgeomPrimitive.h @@ -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 ©); 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 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" diff --git a/panda/src/gobj/qpgeomTriangles.cxx b/panda/src/gobj/qpgeomTriangles.cxx index 0b02a9d6e2..9e8d1dfea1 100644 --- a/panda/src/gobj/qpgeomTriangles.cxx +++ b/panda/src/gobj/qpgeomTriangles.cxx @@ -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 ¶ms) { - qpGeomTriangles *object = new qpGeomTriangles; + qpGeomTriangles *object = new qpGeomTriangles(qpGeomUsageHint::UH_client); DatagramIterator scan; BamReader *manager; diff --git a/panda/src/gobj/qpgeomTriangles.h b/panda/src/gobj/qpgeomTriangles.h index 959e742c57..48d8936a56 100644 --- a/panda/src/gobj/qpgeomTriangles.h +++ b/panda/src/gobj/qpgeomTriangles.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomTriangles : public qpGeomPrimitive { PUBLISHED: - qpGeomTriangles(); + qpGeomTriangles(qpGeomUsageHint::UsageHint usage_hint); qpGeomTriangles(const qpGeomTriangles ©); virtual ~qpGeomTriangles(); diff --git a/panda/src/gobj/qpgeomTrifans.cxx b/panda/src/gobj/qpgeomTrifans.cxx index 586b830bce..367d4e8640 100644 --- a/panda/src/gobj/qpgeomTrifans.cxx +++ b/panda/src/gobj/qpgeomTrifans.cxx @@ -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 ¶ms) { - qpGeomTrifans *object = new qpGeomTrifans; + qpGeomTrifans *object = new qpGeomTrifans(qpGeomUsageHint::UH_client); DatagramIterator scan; BamReader *manager; diff --git a/panda/src/gobj/qpgeomTrifans.h b/panda/src/gobj/qpgeomTrifans.h index d3199d126d..55044b9dfe 100644 --- a/panda/src/gobj/qpgeomTrifans.h +++ b/panda/src/gobj/qpgeomTrifans.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomTrifans : public qpGeomPrimitive { PUBLISHED: - qpGeomTrifans(); + qpGeomTrifans(qpGeomUsageHint::UsageHint usage_hint); qpGeomTrifans(const qpGeomTrifans ©); virtual ~qpGeomTrifans(); diff --git a/panda/src/gobj/qpgeomTristrips.cxx b/panda/src/gobj/qpgeomTristrips.cxx index ff9a66145b..452a4e5287 100644 --- a/panda/src/gobj/qpgeomTristrips.cxx +++ b/panda/src/gobj/qpgeomTristrips.cxx @@ -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 ¶ms) { - qpGeomTristrips *object = new qpGeomTristrips; + qpGeomTristrips *object = new qpGeomTristrips(qpGeomUsageHint::UH_client); DatagramIterator scan; BamReader *manager; diff --git a/panda/src/gobj/qpgeomTristrips.h b/panda/src/gobj/qpgeomTristrips.h index c6f11e8451..a24f0f1791 100644 --- a/panda/src/gobj/qpgeomTristrips.h +++ b/panda/src/gobj/qpgeomTristrips.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomTristrips : public qpGeomPrimitive { PUBLISHED: - qpGeomTristrips(); + qpGeomTristrips(qpGeomUsageHint::UsageHint usage_hint); qpGeomTristrips(const qpGeomTristrips ©); virtual ~qpGeomTristrips(); diff --git a/panda/src/gobj/qpgeomUsageHint.h b/panda/src/gobj/qpgeomUsageHint.h new file mode 100644 index 0000000000..24a470f110 --- /dev/null +++ b/panda/src/gobj/qpgeomUsageHint.h @@ -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 + diff --git a/panda/src/gobj/qpgeomVertexArrayData.I b/panda/src/gobj/qpgeomVertexArrayData.I index 578fdc01dc..d7d60c05c6 100644 --- a/panda/src/gobj/qpgeomVertexArrayData.I +++ b/panda/src/gobj/qpgeomVertexArrayData.I @@ -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(); } diff --git a/panda/src/gobj/qpgeomVertexArrayData.cxx b/panda/src/gobj/qpgeomVertexArrayData.cxx index 0344f897cc..09639e338a 100644 --- a/panda/src/gobj/qpgeomVertexArrayData.cxx +++ b/panda/src/gobj/qpgeomVertexArrayData.cxx @@ -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:: diff --git a/panda/src/gobj/qpgeomVertexArrayData.h b/panda/src/gobj/qpgeomVertexArrayData.h index 933a10e221..11ef7d2c11 100644 --- a/panda/src/gobj/qpgeomVertexArrayData.h +++ b/panda/src/gobj/qpgeomVertexArrayData.h @@ -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 ©); private: void operator = (const qpGeomVertexArrayData ©); @@ -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 Contexts; + typedef pmap Contexts; Contexts _contexts; // This is the data that must be cycled between pipeline stages. diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I index febe7a2bb4..edc7ada938 100644 --- a/panda/src/gobj/qpgeomVertexData.I +++ b/panda/src/gobj/qpgeomVertexData.I @@ -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; } diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 151ab820c5..c55d3e70c8 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -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); diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h index 66c8a01e01..c95fed8ff5 100644 --- a/panda/src/gobj/qpgeomVertexData.h +++ b/panda/src/gobj/qpgeomVertexData.h @@ -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 ©); void operator = (const qpGeomVertexData ©); 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; diff --git a/panda/src/gobj/vertexBufferContext.I b/panda/src/gobj/vertexBufferContext.I new file mode 100644 index 0000000000..74b481ec8c --- /dev/null +++ b/panda/src/gobj/vertexBufferContext.I @@ -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(); +} diff --git a/panda/src/gobj/vertexBufferContext.cxx b/panda/src/gobj/vertexBufferContext.cxx new file mode 100644 index 0000000000..02d3841185 --- /dev/null +++ b/panda/src/gobj/vertexBufferContext.cxx @@ -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; diff --git a/panda/src/gobj/dataContext.h b/panda/src/gobj/vertexBufferContext.h similarity index 81% rename from panda/src/gobj/dataContext.h rename to panda/src/gobj/vertexBufferContext.h index 3a69c31215..231b64fed2 100644 --- a/panda/src/gobj/dataContext.h +++ b/panda/src/gobj/vertexBufferContext.h @@ -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 diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index b58f91a714..729f532f40 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -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; diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 71df9ef7e8..a3b340d737 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -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 } },