beginning dx8 vbuffer support

This commit is contained in:
David Rose 2005-03-18 15:47:58 +00:00
parent aeeca93186
commit 0edc10b609
17 changed files with 544 additions and 112 deletions

View File

@ -47,8 +47,8 @@ PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage"
PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Prepared Bufferss");
PStatCollector GraphicsStateGuardian::_active_buffers_pcollector("Prepared Bufferss:Active");
PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex Buffers");
PStatCollector GraphicsStateGuardian::_active_buffers_pcollector("Vertex Buffers:Active");
PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes");
PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active");
PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory");
@ -1446,6 +1446,7 @@ init_frame_pstats() {
_active_texusage_pcollector.clear_level();
_active_geom_pcollector.clear_level();
_active_geom_node_pcollector.clear_level();
_active_buffers_pcollector.clear_level();
// Also clear out our other counters while we're here.
_vertices_tristrip_pcollector.clear_level();
@ -1507,7 +1508,9 @@ void GraphicsStateGuardian::
add_to_data_record(DataContext *dc) {
if (PStatClient::is_connected()) {
if (dc != (DataContext *)NULL && _current_datas.insert(dc).second) {
_active_buffers_pcollector.add_level(dc->_data->get_num_bytes());
int delta = dc->get_data()->get_num_bytes() - dc->get_num_bytes();
_total_buffers_pcollector.add_level(delta);
_active_buffers_pcollector.add_level(dc->get_data()->get_num_bytes());
}
}
}
@ -1555,6 +1558,13 @@ get_untextured_state() {
return state;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::traverse_prepared_textures
// Access: Public
// Description: Calls the indicated function on all
// currently-prepared textures, or until the callback
// function returns false.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
PreparedGraphicsObjects::Textures::const_iterator ti;

View File

@ -20,6 +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 \
dxTextureContext8.h \
dxGeomMunger8.h \
d3dfont8.h \
@ -36,6 +37,7 @@
#define INCLUDED_SOURCES \
config_dxgsg8.cxx \
dxDataContext8.cxx \
dxTextureContext8.cxx \
dxGeomMunger8.cxx \
d3dfont8.cxx \

View File

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

View File

@ -0,0 +1,18 @@
// Filename: dxDataContext8.I
// 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 .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,150 @@
// Filename: dxDataContext8.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#include "dxDataContext8.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomVertexArrayFormat.h"
#include "internalName.h"
#include "config_dxgsg8.h"
#include <d3dx8.h>
TypeHandle DXDataContext8::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXDataContext8::
DXDataContext8(qpGeomVertexArrayData *data) :
DataContext(data),
_vbuffer(NULL)
{
// Now fill in the FVF code.
const qpGeomVertexArrayFormat *array_format = data->get_array_format();
// We have to start with the vertex data, and work up from there in
// order, since that's the way the FVF is defined.
int n = 0;
int num_data_types = array_format->get_num_data_types();
_fvf = 0;
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_vertex()) {
_fvf |= D3DFVF_XYZ;
++n;
}
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_normal()) {
_fvf |= D3DFVF_NORMAL;
++n;
}
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_color()) {
_fvf |= D3DFVF_DIFFUSE;
++n;
}
// For multitexture support, we will need to look for all of the
// texcoord names and enable them in order.
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_texcoord()) {
const qpGeomVertexDataType *data_type = array_format->get_data_type(n);
switch (data_type->get_num_values()) {
case 1:
_fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0);
++n;
break;
case 2:
_fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
++n;
break;
case 3:
_fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
++n;
break;
case 4:
_fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0);
++n;
break;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXDataContext8::
~DXDataContext8() {
if (_vbuffer != NULL) {
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
_vbuffer = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::create_vbuffer
// Access: Public
// Description: Creates a new vertex buffer and uploads data to it.
////////////////////////////////////////////////////////////////////
void DXDataContext8::
create_vbuffer(DXScreenData &scrn) {
if (_vbuffer != NULL) {
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
_vbuffer = NULL;
}
HRESULT hr = scrn.pD3DDevice->CreateVertexBuffer
(get_data()->get_num_bytes(), D3DUSAGE_WRITEONLY,
_fvf, D3DPOOL_MANAGED, &_vbuffer);
if (FAILED(hr)) {
dxgsg8_cat.warning()
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
_vbuffer = NULL;
} else {
upload_data();
}
}
////////////////////////////////////////////////////////////////////
// Function: DXDataContext8::upload_data
// Access: Public
// Description: Copies the latest data from the client store to
// DirectX.
////////////////////////////////////////////////////////////////////
void DXDataContext8::
upload_data() {
nassertv(_vbuffer != NULL);
BYTE *local_pointer;
HRESULT hr = _vbuffer->Lock(0, 0, &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());
_vbuffer->Unlock();
}

View File

@ -0,0 +1,64 @@
// Filename: dxDataContext8.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 DXDATACONTEXT8_H
#define DXDATACONTEXT8_H
#include "pandabase.h"
#include "dxgsg8base.h"
#include "dataContext.h"
////////////////////////////////////////////////////////////////////
// Class : DXDataContext8
// Description : Caches a GeomVertexArrayData in the DirectX device as
// a vertex buffer.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXDataContext8 : public DataContext {
public:
DXDataContext8(qpGeomVertexArrayData *data);
virtual ~DXDataContext8();
void create_vbuffer(DXScreenData &scrn);
void upload_data();
IDirect3DVertexBuffer8 *_vbuffer;
int _fvf;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
DataContext::init_type();
register_type(_type_handle, "DXDataContext8",
DataContext::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 "dxDataContext8.I"
#endif

View File

@ -55,6 +55,8 @@
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#include "dxGeomMunger8.h"
#include "config_gobj.h"
#include "dxDataContext8.h"
#ifdef DO_PSTATS
#include "pStatTimer.h"
@ -198,6 +200,9 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
_pFvfBufBasePtr = NULL;
_index_buf=NULL;
_vbuffer_active = false;
_ibuffer_active = false;
// _max_light_range = __D3DLIGHT_RANGE_MAX;
// non-dx obj values inited here should not change if resize is
@ -2613,60 +2618,12 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
// The munger should have put the "vertex" data at the beginning of
// the first array.
const qpGeomVertexArrayFormat *array_format = format->get_array(0);
const qpGeomVertexArrayData *data = _vertex_data->get_array(0);
// Now we have to start with the vertex data, and work up from there
// in order, since that's the way the FVF is defined.
int n = 0;
int num_data_types = array_format->get_num_data_types();
DataContext *dc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
nassertr(dc != (DataContext *)NULL, false);
apply_data(dc);
DWORD fvf = 0;
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_vertex()) {
fvf |= D3DFVF_XYZ;
++n;
} else {
// No vertex data, no vertices.
return false;
}
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_normal()) {
fvf |= D3DFVF_NORMAL;
++n;
}
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_color()) {
fvf |= D3DFVF_DIFFUSE;
++n;
}
// For multitexture support, we will need to look for all of the
// texcoord names and enable them in order.
if (n < num_data_types &&
array_format->get_data_type(n)->get_name() == InternalName::get_texcoord()) {
const qpGeomVertexDataType *data_type = array_format->get_data_type(n);
switch (data_type->get_num_values()) {
case 1:
fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0);
++n;
break;
case 2:
fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
++n;
break;
case 3:
fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
++n;
break;
case 4:
fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0);
++n;
break;
}
}
set_vertex_format(fvf);
return true;
}
@ -2677,15 +2634,24 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
draw_triangles(const qpGeomTriangles *primitive) {
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_flat_first_vertices(),
D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
if (_vbuffer_active && _ibuffer_active) {
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
0, primitive->get_num_primitives());
} else {
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_flat_first_vertices(),
D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
}
////////////////////////////////////////////////////////////////////
@ -2936,6 +2902,97 @@ release_texture(TextureContext *tc) {
delete gtc;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::prepare_data
// 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
// responsibility of the calling function to later
// call release_data() 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) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "prepare_data(" << (void *)data << ")\n";
}
DXDataContext8 *ddc = new DXDataContext8(data);
if (vertex_buffers) {
ddc->create_vbuffer(*_pScrn);
ddc->mark_loaded();
}
return ddc;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::apply_data
// Access: Public
// Description: Makes the data the currently available data for
// rendering.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
apply_data(DataContext *dc) {
DXDataContext8 *ddc = DCAST(DXDataContext8, dc);
if (ddc->_vbuffer != NULL) {
add_to_data_record(ddc);
if (ddc->was_modified()) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "apply_data(" << (void *)dc->get_data() << ")\n";
}
if (ddc->changed_size()) {
// Here we have to destroy the old vertex buffer and create a
// new one.
ddc->create_vbuffer(*_pScrn);
} else {
// Here we just copy the new data to the vertex buffer.
ddc->upload_data();
}
ddc->mark_loaded();
}
_pD3DDevice->SetStreamSource
(0, ddc->_vbuffer, ddc->get_data()->get_array_format()->get_stride());
_vbuffer_active = true;
} else {
_vbuffer_active = false;
}
set_vertex_format(ddc->_fvf);
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::release_data
// 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 DXGraphicsStateGuardian8::
release_data(DataContext *dc) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "release_data(" << (void *)dc->get_data() << ")\n";
}
DXDataContext8 *ddc = DCAST(DXDataContext8, dc);
delete ddc;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::get_geom_munger
// Access: Public, Virtual

View File

@ -99,6 +99,10 @@ 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 CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
@ -313,6 +317,8 @@ protected:
int _projection_mat_stack_count;
CPT(DisplayRegion) _actual_display_region;
bool _vbuffer_active;
bool _ibuffer_active;
// Color/Alpha Matrix Transition stuff
INLINE void transform_color(Colorf &InColor,D3DCOLOR &OutColor);

View File

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

View File

@ -21,7 +21,8 @@
////////////////////////////////////////////////////////////////////
// Class : GLDataContext
// Description :
// Description : Caches a GeomVertexArrayData on the GL as a buffer
// object.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(DataContext) : public DataContext {
public:

View File

@ -2357,11 +2357,12 @@ prepare_data(qpGeomVertexArrayData *data) {
CLP(DataContext) *gdc = new CLP(DataContext)(data);
_glGenBuffers(1, &gdc->_index);
add_to_data_record(gdc);
_glBindBuffer(GL_ARRAY_BUFFER, gdc->_index);
_glBufferData(GL_ARRAY_BUFFER, gdc->_data->get_num_bytes(),
gdc->_data->get_data(),
get_usage(gdc->_data->get_usage_hint()));
gdc->_modified = gdc->_data->get_modified();
_glBufferData(GL_ARRAY_BUFFER, gdc->get_data()->get_num_bytes(),
gdc->get_data()->get_data(),
get_usage(gdc->get_data()->get_usage_hint()));
gdc->mark_loaded();
report_my_gl_errors();
return gdc;
@ -2372,17 +2373,12 @@ prepare_data(qpGeomVertexArrayData *data) {
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::apply_data
// Access: Public, Virtual
// Access: Public
// Description: Makes the data the currently available data for
// rendering.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
apply_data(DataContext *dc) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "apply_data(" << (void *)dc->_data << ")\n";
}
nassertv(_supports_buffers);
CLP(DataContext) *gdc = DCAST(CLP(DataContext), dc);
@ -2390,11 +2386,22 @@ apply_data(DataContext *dc) {
add_to_data_record(gdc);
_glBindBuffer(GL_ARRAY_BUFFER, gdc->_index);
if (gdc->_modified != gdc->_data->get_modified()) {
_glBufferSubData(GL_ARRAY_BUFFER, 0, gdc->_data->get_num_bytes(),
gdc->_data->get_data());
if (gdc->was_modified()) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "apply_data(" << (void *)dc->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()));
gdc->_modified = gdc->_data->get_modified();
} else {
_glBufferSubData(GL_ARRAY_BUFFER, 0, gdc->get_num_bytes(),
gdc->get_data()->get_data());
}
gdc->mark_loaded();
}
report_my_gl_errors();
@ -2412,7 +2419,7 @@ void CLP(GraphicsStateGuardian)::
release_data(DataContext *dc) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "release_data(" << (void *)dc->_data << ")\n";
<< "release_data(" << (void *)dc->get_data() << ")\n";
}
nassertv(_supports_buffers);
@ -2458,9 +2465,7 @@ 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());
CLP(DataContext) *gdc = DCAST(CLP(DataContext), dc);
_glBindBuffer(GL_ARRAY_BUFFER, gdc->_index);
apply_data(dc);
// NULL is the OpenGL convention for the first byte of the buffer.
return NULL;

View File

@ -105,7 +105,7 @@ public:
virtual void release_geom(GeomContext *gc);
virtual DataContext *prepare_data(qpGeomVertexArrayData *data);
virtual void apply_data(DataContext *dc);
void apply_data(DataContext *dc);
virtual void release_data(DataContext *dc);
const unsigned char *setup_array_data(const qpGeomVertexArrayData *data);

View File

@ -24,6 +24,68 @@
////////////////////////////////////////////////////////////////////
INLINE DataContext::
DataContext(qpGeomVertexArrayData *data) :
_data(data)
_data(data),
// Initially, the number of bytes is zero, until the data has been
// loaded (and mark_loaded() is called).
_num_bytes(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::get_data
// Access: Public
// Description: Returns the pointer to the client-side array data
// object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData *DataContext::
get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::get_num_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;
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::changed_size
// Access: Public
// Description: Returns true if the data has changed size since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool DataContext::
changed_size() const {
return get_num_bytes() != _data->get_num_bytes();
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::was_modified
// Access: Public
// Description: Returns true if the data has been modified since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool DataContext::
was_modified() const {
return _modified != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: DataContext::mark_loaded
// Access: Public
// Description: Should be called after the DataContext has been
// loaded into graphics memory, this updates the
// internal flags for changed_size() and modified().
////////////////////////////////////////////////////////////////////
INLINE void DataContext::
mark_loaded() {
_num_bytes = _data->get_num_bytes();
_modified = _data->get_modified();
}

View File

@ -23,8 +23,7 @@
#include "savedContext.h"
#include "updateSeq.h"
class qpGeomVertexArrayData;
#include "qpgeomVertexArrayData.h"
////////////////////////////////////////////////////////////////////
// Class : DataContext
@ -41,11 +40,21 @@ class EXPCL_PANDA DataContext : public SavedContext {
public:
INLINE DataContext(qpGeomVertexArrayData *data);
INLINE qpGeomVertexArrayData *get_data() const;
INLINE int get_num_bytes() const;
INLINE bool changed_size() const;
INLINE bool was_modified() const;
INLINE void mark_loaded();
private:
// This cannot be a PT(qpGeomVertexArrayData), because the data and
// the GSG both own their DataContexts! That would create a
// circular reference count.
qpGeomVertexArrayData *_data;
UpdateSeq _modified;
int _num_bytes;
public:
static TypeHandle get_class_type() {
@ -63,6 +72,8 @@ public:
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
#include "dataContext.I"

View File

@ -18,9 +18,13 @@
#include "preparedGraphicsObjects.h"
#include "textureContext.h"
#include "texture.h"
#include "geom.h"
#include "qpgeomVertexArrayData.h"
#include "mutexHolder.h"
PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex Buffers");
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::Constructor
@ -69,6 +73,19 @@ PreparedGraphicsObjects::
_prepared_geoms.clear();
_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);
}
_prepared_datas.clear();
_released_datas.clear();
_enqueued_datas.clear();
}
@ -411,20 +428,21 @@ dequeue_data(qpGeomVertexArrayData *data) {
// it's in, at the time release_data is called).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
release_data(DataContext *gc) {
release_data(DataContext *dc) {
MutexHolder holder(_lock);
gc->_data->clear_prepared(this);
dc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(dc->get_num_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.
gc->_data = (qpGeomVertexArrayData *)NULL;
dc->_data = (qpGeomVertexArrayData *)NULL;
bool removed = (_prepared_datas.erase(gc) != 0);
bool removed = (_prepared_datas.erase(dc) != 0);
nassertv(removed);
_released_datas.insert(gc);
_released_datas.insert(dc);
}
////////////////////////////////////////////////////////////////////
@ -441,15 +459,16 @@ release_all_datas() {
int num_datas = (int)_prepared_datas.size();
Datas::iterator gci;
for (gci = _prepared_datas.begin();
gci != _prepared_datas.end();
++gci) {
DataContext *gc = (*gci);
gc->_data->clear_prepared(this);
gc->_data = (qpGeomVertexArrayData *)NULL;
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;
_released_datas.insert(gc);
_released_datas.insert(dc);
}
_prepared_datas.clear();
@ -487,14 +506,16 @@ prepare_data_now(qpGeomVertexArrayData *data, GraphicsStateGuardianBase *gsg) {
// 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 *gc = gsg->prepare_data(data);
DataContext *dc = gsg->prepare_data(data);
if (gc != (DataContext *)NULL) {
bool prepared = _prepared_datas.insert(gc).second;
nassertr(prepared, gc);
if (dc != (DataContext *)NULL) {
bool prepared = _prepared_datas.insert(dc).second;
nassertr(prepared, dc);
_total_buffers_pcollector.add_level(dc->get_num_bytes());
}
return gc;
return dc;
}
////////////////////////////////////////////////////////////////////
@ -513,7 +534,8 @@ void PreparedGraphicsObjects::
update(GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// First, release all the textures awaiting release.
// First, release all the textures, geoms, and data arrays awaiting
// release.
Textures::iterator tci;
for (tci = _released_textures.begin();
tci != _released_textures.end();
@ -524,7 +546,6 @@ update(GraphicsStateGuardianBase *gsg) {
_released_textures.clear();
// Next, release all the geoms awaiting release.
Geoms::iterator gci;
for (gci = _released_geoms.begin();
gci != _released_geoms.end();
@ -535,7 +556,18 @@ update(GraphicsStateGuardianBase *gsg) {
_released_geoms.clear();
// Now prepare all the textures awaiting preparation.
Datas::iterator dci;
for (dci = _released_datas.begin();
dci != _released_datas.end();
++dci) {
DataContext *dc = (*dci);
gsg->release_data(dc);
}
_released_datas.clear();
// Now prepare all the textures, geoms, and data arrays awaiting
// preparation.
EnqueuedTextures::iterator qti;
for (qti = _enqueued_textures.begin();
qti != _enqueued_textures.end();
@ -546,7 +578,6 @@ update(GraphicsStateGuardianBase *gsg) {
_enqueued_textures.clear();
// And finally prepare all the geoms awaiting preparation.
EnqueuedGeoms::iterator qgi;
for (qgi = _enqueued_geoms.begin();
qgi != _enqueued_geoms.end();
@ -555,5 +586,13 @@ update(GraphicsStateGuardianBase *gsg) {
geom->prepare_now(this, gsg);
}
_enqueued_geoms.clear();
EnqueuedDatas::iterator qdi;
for (qdi = _enqueued_datas.begin();
qdi != _enqueued_datas.end();
++qdi) {
qpGeomVertexArrayData *data = (*qdi);
data->prepare_now(this, gsg);
}
_enqueued_datas.clear();
}

View File

@ -99,6 +99,7 @@ private:
EnqueuedDatas _enqueued_datas;
static PStatCollector _total_texusage_pcollector;
static PStatCollector _total_buffers_pcollector;
friend class GraphicsStateGuardian;
};

View File

@ -32,13 +32,16 @@
class PreparedGraphicsObjects;
class DataContext;
class GraphicsStateGuardianBase;
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexArrayData
// Description : This is the data for one array of a GeomVertexData
// structure. Many GeomVertexData structures will only
// define one array; some will define multiple arrays.
// DirectX calls this concept a "stream".
// define one array, with all data elements interleaved
// (DirectX 8.0 and before insisted on this format);
// some will define multiple arrays. DirectX calls this
// concept a "stream".
//
// This object is just a block of data. See
// GeomVertexData for the organizing structure.