mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
gl display lists with new geom
This commit is contained in:
parent
70a94646f7
commit
3f7956f4e9
@ -670,7 +670,7 @@ finish_decal() {
|
||||
// are ok, false to abort this group of primitives.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
begin_draw_primitives(const qpGeomVertexData *data) {
|
||||
begin_draw_primitives(const qpGeom *, const qpGeomVertexData *data) {
|
||||
_vertex_data = data;
|
||||
return true;
|
||||
}
|
||||
@ -719,6 +719,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
end_draw_primitives() {
|
||||
_vertex_data = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -148,7 +148,7 @@ public:
|
||||
virtual CPT(RenderState) begin_decal_base_second();
|
||||
virtual void finish_decal();
|
||||
|
||||
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
|
||||
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
|
||||
virtual void draw_triangles(const qpGeomTriangles *primitive);
|
||||
virtual void draw_tristrips(const qpGeomTristrips *primitive);
|
||||
virtual void draw_trifans(const qpGeomTrifans *primitive);
|
||||
|
@ -2606,10 +2606,10 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
|
||||
// are ok, false to abort this group of primitives.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DXGraphicsStateGuardian8::
|
||||
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
|
||||
begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) {
|
||||
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
|
||||
|
||||
if (!GraphicsStateGuardian::begin_draw_primitives(vertex_data)) {
|
||||
if (!GraphicsStateGuardian::begin_draw_primitives(geom, vertex_data)) {
|
||||
return false;
|
||||
}
|
||||
nassertr(_vertex_data != (qpGeomVertexData *)NULL, false);
|
||||
@ -2694,6 +2694,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
end_draw_primitives() {
|
||||
GraphicsStateGuardian::end_draw_primitives();
|
||||
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
|
||||
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
|
||||
|
||||
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
|
||||
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
|
||||
virtual void draw_triangles(const qpGeomTriangles *primitive);
|
||||
virtual void draw_tristrips(const qpGeomTristrips *primitive);
|
||||
virtual void end_draw_primitives();
|
||||
|
@ -30,6 +30,8 @@ public:
|
||||
// This is the GL display list index.
|
||||
GLuint _index;
|
||||
|
||||
UpdateSeq _modified;
|
||||
|
||||
// The number of vertices encoded in the display list, for stats
|
||||
// reporting.
|
||||
#ifdef DO_PSTATS
|
||||
|
@ -2030,14 +2030,53 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
|
||||
// are ok, false to abort this group of primitives.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
|
||||
begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) {
|
||||
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
|
||||
|
||||
if (!GraphicsStateGuardian::begin_draw_primitives(vertex_data)) {
|
||||
if (!GraphicsStateGuardian::begin_draw_primitives(geom, vertex_data)) {
|
||||
return false;
|
||||
}
|
||||
nassertr(_vertex_data != (qpGeomVertexData *)NULL, false);
|
||||
|
||||
_geom_display_list = NULL;
|
||||
|
||||
if (geom->get_usage_hint() == qpGeomUsageHint::UH_static &&
|
||||
_vertex_data->get_usage_hint() == qpGeomUsageHint::UH_static &&
|
||||
display_lists) {
|
||||
// If the geom appears to be totally static, try to build it into
|
||||
// a display list.
|
||||
GeomContext *gc = ((qpGeom *)geom)->prepare_now(get_prepared_objects(), this);
|
||||
nassertr(gc != (GeomContext *)NULL, false);
|
||||
CLP(GeomContext) *ggc = DCAST(CLP(GeomContext), gc);
|
||||
if (ggc->_modified == geom->get_modified()) {
|
||||
// If it hasn't been modified, just play the display list again.
|
||||
GLP(CallList)(ggc->_index);
|
||||
#ifdef DO_PSTATS
|
||||
_vertices_display_list_pcollector.add_level(ggc->_num_verts);
|
||||
#endif
|
||||
|
||||
// And now we don't need to do anything else for this geom.
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it has been modified, or this is the first time, then we
|
||||
// need to build the display list up.
|
||||
GLP(NewList)(ggc->_index, GL_COMPILE_AND_EXECUTE);
|
||||
ggc->_modified = geom->get_modified();
|
||||
_geom_display_list = ggc;
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
// Count up the number of vertices we're about to render, by
|
||||
// checking the PStats vertex counters now, and at the end. This is
|
||||
// kind of hacky, but this is debug code.
|
||||
_num_display_list_verts_before =
|
||||
_vertices_tristrip_pcollector.get_level() +
|
||||
_vertices_trifan_pcollector.get_level() +
|
||||
_vertices_tri_pcollector.get_level() +
|
||||
_vertices_other_pcollector.get_level();
|
||||
#endif
|
||||
}
|
||||
|
||||
const qpGeomVertexArrayData *array_data;
|
||||
int num_components;
|
||||
qpGeomVertexDataType::NumericType numeric_type;
|
||||
@ -2051,9 +2090,6 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
|
||||
GLP(VertexPointer)(num_components, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_VERTEX_ARRAY);
|
||||
} else {
|
||||
// No vertex data? No primitives!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wants_normals() &&
|
||||
@ -2073,14 +2109,8 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
|
||||
array_data, num_components, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
if (numeric_type == qpGeomVertexDataType::NT_packed_argb) {
|
||||
// Temporary hack--this will probably reverse r and b.
|
||||
GLP(ColorPointer)(4, GL_UNSIGNED_BYTE, stride, client_pointer + start);
|
||||
|
||||
} else {
|
||||
GLP(ColorPointer)(num_components, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
}
|
||||
GLP(EnableClientState)(GL_COLOR_ARRAY);
|
||||
|
||||
} else {
|
||||
@ -2105,8 +2135,6 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
issue_scene_graph_color();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2168,7 +2196,23 @@ draw_tristrips(const qpGeomTristrips *primitive) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
end_draw_primitives() {
|
||||
GLP(DisableClientState)(GL_VERTEX_ARRAY);
|
||||
if (_geom_display_list != NULL) {
|
||||
// If we were building a display list, close it now.
|
||||
GLP(EndList)();
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
float num_verts_after =
|
||||
_vertices_tristrip_pcollector.get_level() +
|
||||
_vertices_trifan_pcollector.get_level() +
|
||||
_vertices_tri_pcollector.get_level() +
|
||||
_vertices_other_pcollector.get_level();
|
||||
float num_verts = num_verts_after - _num_display_list_verts_before;
|
||||
_geom_display_list->_num_verts = (int)(num_verts + 0.5);
|
||||
#endif
|
||||
}
|
||||
_geom_display_list = NULL;
|
||||
|
||||
GraphicsStateGuardian::end_draw_primitives();
|
||||
|
||||
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
|
||||
}
|
||||
@ -2262,6 +2306,30 @@ release_texture(TextureContext *tc) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomContext *CLP(GraphicsStateGuardian)::
|
||||
prepare_geom(Geom *geom) {
|
||||
// Temporary test until the experimental Geom rewrite becomes the
|
||||
// actual Geom implementation.
|
||||
if (geom->is_exact_type(qpGeom::get_class_type())) {
|
||||
CLP(GeomContext) *ggc = new CLP(GeomContext)(geom);
|
||||
ggc->_index = GLP(GenLists)(1);
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "preparing " << *geom << ", index " << ggc->_index << "\n";
|
||||
}
|
||||
if (ggc->_index == 0) {
|
||||
GLCAT.error()
|
||||
<< "Ran out of display list indices.\n";
|
||||
delete ggc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return ggc;
|
||||
|
||||
} else {
|
||||
// Original Geom display list implementation. Slightly broken,
|
||||
// since it doesn't work well with scene graph color
|
||||
// manipulations.
|
||||
|
||||
if (!_vertex_colors_enabled) {
|
||||
// We can't build a display list (or play back a display list) if
|
||||
// its color is overridden with a scene graph color. Maybe if we
|
||||
@ -2326,6 +2394,7 @@ prepare_geom(Geom *geom) {
|
||||
report_my_gl_errors();
|
||||
return ggc;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(GraphicsStateGuardian)::release_geom
|
||||
@ -2464,7 +2533,7 @@ setup_array_data(const qpGeomVertexArrayData *data) {
|
||||
// No support for buffer objects; always render from client.
|
||||
return data->get_data();
|
||||
}
|
||||
if (!vertex_buffers ||
|
||||
if (!vertex_buffers || _geom_display_list != NULL ||
|
||||
data->get_usage_hint() == qpGeomUsageHint::UH_client) {
|
||||
// The array specifies client rendering only, or buffer objects
|
||||
// are configured off.
|
||||
@ -2534,12 +2603,12 @@ apply_index_buffer(IndexBufferContext *ibc) {
|
||||
}
|
||||
if (gibc->changed_size()) {
|
||||
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(),
|
||||
gibc->get_data()->get_vertices(),
|
||||
gibc->get_data()->get_flat_last_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->get_data()->get_flat_last_vertices());
|
||||
}
|
||||
|
||||
gibc->mark_loaded();
|
||||
@ -2593,19 +2662,19 @@ 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();
|
||||
return data->get_flat_last_vertices();
|
||||
}
|
||||
if (!vertex_buffers ||
|
||||
if (!vertex_buffers || _geom_display_list != NULL ||
|
||||
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();
|
||||
return data->get_flat_last_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());
|
||||
nassertr(ibc != (IndexBufferContext *)NULL, data->get_flat_last_vertices());
|
||||
apply_index_buffer(ibc);
|
||||
|
||||
// NULL is the OpenGL convention for the first byte of the buffer.
|
||||
|
@ -58,6 +58,8 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
|
||||
class CLP(GeomContext);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GLGraphicsStateGuardian
|
||||
// Description : A GraphicsStateGuardian specialized for rendering
|
||||
@ -90,7 +92,7 @@ public:
|
||||
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
|
||||
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
|
||||
|
||||
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
|
||||
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
|
||||
virtual void draw_triangles(const qpGeomTriangles *primitive);
|
||||
virtual void draw_tristrips(const qpGeomTristrips *primitive);
|
||||
virtual void end_draw_primitives();
|
||||
@ -315,6 +317,8 @@ protected:
|
||||
|
||||
int _pass_number;
|
||||
bool _auto_rescale_normal;
|
||||
CLP(GeomContext) *_geom_display_list;
|
||||
float _num_display_list_verts_before;
|
||||
|
||||
int _error_count;
|
||||
|
||||
|
@ -84,7 +84,9 @@ ConfigVariableBool retained_mode
|
||||
"creates specific cache information (like display lists or vertex "
|
||||
"buffers) with the GSG for static geometry, when supported by the "
|
||||
"GSG. Set it false to use only immediate mode, which sends the "
|
||||
"vertices to the GSG every frame."));
|
||||
"vertices to the GSG every frame. This is used only in the "
|
||||
"original Geom implementation; it is replaced by display-lists "
|
||||
"in the experimental Geom rewrite."));
|
||||
|
||||
ConfigVariableBool vertex_buffers
|
||||
("vertex-buffers", false,
|
||||
@ -95,6 +97,16 @@ ConfigVariableBool vertex_buffers
|
||||
"graphics memory (which might otherwise be used for textures "
|
||||
"or offscreen buffers)."));
|
||||
|
||||
ConfigVariableBool display_lists
|
||||
("display-lists", false,
|
||||
PRC_DESC("Set this true to allow the use of OpenGL display lists for "
|
||||
"rendering static geometry. On some systems, this can result "
|
||||
"in a performance improvement over vertex buffers alone; on "
|
||||
"other systems (particularly low-end systems) it makes little to "
|
||||
"no difference. This has no effect on DirectX rendering. If "
|
||||
"vertex-buffers is also enabled, then OpenGL buffer objects "
|
||||
"will also be created for dynamic geometry."));
|
||||
|
||||
ConfigVariableBool use_qpgeom
|
||||
("use-qpgeom", false,
|
||||
PRC_DESC("A temporary variable while the experimental Geom rewrite is "
|
||||
|
@ -52,6 +52,7 @@ extern EXPCL_PANDA ConfigVariableBool keep_texture_ram;
|
||||
extern EXPCL_PANDA ConfigVariableBool keep_geom_ram;
|
||||
extern EXPCL_PANDA ConfigVariableBool retained_mode;
|
||||
extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA ConfigVariableBool display_lists;
|
||||
|
||||
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;
|
||||
|
||||
|
@ -17,6 +17,23 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::get_usage_hint
|
||||
// Access: Published
|
||||
// Description: Returns the minimum (i.e. most dynamic) usage_hint
|
||||
// among all of the individual GeomPrimitives that have
|
||||
// been added to the geom.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeomUsageHint::UsageHint qpGeom::
|
||||
get_usage_hint() const {
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_got_usage_hint) {
|
||||
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
|
||||
((qpGeom *)this)->reset_usage_hint(cdataw);
|
||||
}
|
||||
return cdata->_usage_hint;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::get_vertex_data
|
||||
// Access: Published
|
||||
@ -71,6 +88,7 @@ modify_primitive(int i) {
|
||||
clear_cache();
|
||||
CDWriter cdata(_cycler);
|
||||
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
|
||||
cdata->_got_usage_hint = false;
|
||||
return cdata->_primitives[i];
|
||||
}
|
||||
|
||||
@ -85,6 +103,19 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
|
||||
clear_cache();
|
||||
CDWriter cdata(_cycler);
|
||||
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
|
||||
if (cdata->_got_usage_hint &&
|
||||
cdata->_primitives[i]->get_usage_hint() != primitive->get_usage_hint()) {
|
||||
if (cdata->_primitives[i]->get_usage_hint() < primitive->get_usage_hint()) {
|
||||
// If we're reducing the usage hint, we might also be reducing
|
||||
// the minimum usage hit.
|
||||
cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
|
||||
} else { // (cdata->_primitives[i]->get_usage_hint() > primitive->get_usage_hint())
|
||||
// If we're increasing it, we might have to rederive the minimum.
|
||||
if (cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
|
||||
cdata->_got_usage_hint = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
cdata->_primitives[i] = (qpGeomPrimitive *)primitive;
|
||||
}
|
||||
|
||||
@ -94,7 +125,10 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeom::CData::
|
||||
CData() {
|
||||
CData() :
|
||||
_usage_hint(qpGeomUsageHint::UH_static),
|
||||
_got_usage_hint(false)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -105,7 +139,9 @@ CData() {
|
||||
INLINE qpGeom::CData::
|
||||
CData(const qpGeom::CData ©) :
|
||||
_data(copy._data),
|
||||
_primitives(copy._primitives)
|
||||
_primitives(copy._primitives),
|
||||
_usage_hint(copy._usage_hint),
|
||||
_got_usage_hint(copy._got_usage_hint)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
UpdateSeq qpGeom::_next_modified;
|
||||
TypeHandle qpGeom::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -152,6 +153,10 @@ add_primitive(const qpGeomPrimitive *primitive) {
|
||||
clear_cache();
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_primitives.push_back((qpGeomPrimitive *)primitive);
|
||||
|
||||
if (cdata->_got_usage_hint) {
|
||||
cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -164,6 +169,12 @@ remove_primitive(int i) {
|
||||
clear_cache();
|
||||
CDWriter cdata(_cycler);
|
||||
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
|
||||
if (cdata->_got_usage_hint &&
|
||||
cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
|
||||
// Maybe we're raising the minimum usage_hint; we have to rederive
|
||||
// the usage_hint later.
|
||||
cdata->_got_usage_hint = false;
|
||||
}
|
||||
cdata->_primitives.erase(cdata->_primitives.begin() + i);
|
||||
}
|
||||
|
||||
@ -203,6 +214,34 @@ get_num_bytes() const {
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::get_modified
|
||||
// Access: Published
|
||||
// Description: Returns the maximum UpdateSeq of all the Geom's
|
||||
// individual primitives and vertex arrays. This,
|
||||
// therefore, will change only when any part of the Geom
|
||||
// changes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
UpdateSeq qpGeom::
|
||||
get_modified() const {
|
||||
CDReader cdata(_cycler);
|
||||
UpdateSeq seq;
|
||||
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
seq = max(seq, (*pi)->get_modified());
|
||||
}
|
||||
|
||||
int num_arrays = cdata->_data->get_num_arrays();
|
||||
for (int i = 0; i < num_arrays; ++i) {
|
||||
seq = max(seq, cdata->_data->get_array(i)->get_modified());
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::munge_geom
|
||||
// Access: Published
|
||||
@ -342,9 +381,25 @@ clear_cache() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeom::
|
||||
draw(GraphicsStateGuardianBase *gsg, const qpGeomVertexData *vertex_data) const {
|
||||
#ifdef DO_PIPELINING
|
||||
// Make sure the usage_hint is already updated before we start to
|
||||
// draw, so we don't end up with a circular lock if the GSG asks us
|
||||
// to update this while we're holding the read lock.
|
||||
{
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_got_usage_hint) {
|
||||
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
|
||||
((qpGeom *)this)->reset_usage_hint(cdataw);
|
||||
}
|
||||
}
|
||||
// TODO: fix up the race condition between this line and the next.
|
||||
// Maybe CDWriter's elevate-to-write should return the read lock to
|
||||
// its original locked state when it's done.
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
|
||||
if (gsg->begin_draw_primitives(vertex_data)) {
|
||||
if (gsg->begin_draw_primitives(this, vertex_data)) {
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
@ -355,6 +410,25 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomVertexData *vertex_data) const
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::get_next_modified
|
||||
// Access: Public
|
||||
// Description: Returns a monotonically increasing sequence. Each
|
||||
// time this is called, a new sequence number is
|
||||
// returned, higher than the previous value.
|
||||
//
|
||||
// This is used to ensure that
|
||||
// GeomVertexArrayData::get_modified() and
|
||||
// GeomPrimitive::get_modified() update from the same
|
||||
// space, so that Geom::get_modified() returns a
|
||||
// meaningful value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
UpdateSeq qpGeom::
|
||||
get_next_modified() {
|
||||
++_next_modified;
|
||||
return _next_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::recompute_bound
|
||||
// Access: Protected, Virtual
|
||||
@ -445,6 +519,23 @@ remove_cache_entry(const qpGeomMunger *modifier) const {
|
||||
((qpGeom *)this)->_cycler.release_write_stage(0, cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::reset_usage_hint
|
||||
// Access: Private
|
||||
// Description: Recomputes the minimum usage_hint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeom::
|
||||
reset_usage_hint(qpGeom::CDWriter &cdata) {
|
||||
cdata->_usage_hint = qpGeomUsageHint::UH_static;
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
cdata->_usage_hint = min(cdata->_usage_hint, (*pi)->get_usage_hint());
|
||||
}
|
||||
cdata->_got_usage_hint = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeom::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "qpgeomVertexData.h"
|
||||
#include "qpgeomPrimitive.h"
|
||||
#include "qpgeomMunger.h"
|
||||
#include "qpgeomUsageHint.h"
|
||||
#include "updateSeq.h"
|
||||
#include "pointerTo.h"
|
||||
#include "geom.h"
|
||||
|
||||
@ -61,6 +63,8 @@ PUBLISHED:
|
||||
// Temporary.
|
||||
virtual Geom *make_copy() const;
|
||||
|
||||
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
|
||||
|
||||
INLINE CPT(qpGeomVertexData) get_vertex_data() const;
|
||||
PT(qpGeomVertexData) modify_vertex_data();
|
||||
void set_vertex_data(const qpGeomVertexData *data);
|
||||
@ -74,6 +78,7 @@ PUBLISHED:
|
||||
void clear_primitives();
|
||||
|
||||
int get_num_bytes() const;
|
||||
UpdateSeq get_modified() const;
|
||||
|
||||
void munge_geom(const qpGeomMunger *munger,
|
||||
CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const;
|
||||
@ -87,6 +92,8 @@ public:
|
||||
void draw(GraphicsStateGuardianBase *gsg,
|
||||
const qpGeomVertexData *vertex_data) const;
|
||||
|
||||
static UpdateSeq get_next_modified();
|
||||
|
||||
protected:
|
||||
virtual BoundingVolume *recompute_bound();
|
||||
|
||||
@ -120,6 +127,8 @@ private:
|
||||
|
||||
PT(qpGeomVertexData) _data;
|
||||
Primitives _primitives;
|
||||
qpGeomUsageHint::UsageHint _usage_hint;
|
||||
bool _got_usage_hint;
|
||||
MungedCache _munged_cache;
|
||||
};
|
||||
|
||||
@ -127,6 +136,10 @@ private:
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
void reset_usage_hint(CDWriter &cdata);
|
||||
|
||||
static UpdateSeq _next_modified;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
@ -17,6 +17,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpgeomPrimitive.h"
|
||||
#include "qpgeom.h"
|
||||
#include "qpgeomVertexData.h"
|
||||
#include "qpgeomVertexArrayFormat.h"
|
||||
#include "qpgeomVertexDataType.h"
|
||||
@ -536,7 +537,7 @@ clear_cache() {
|
||||
|
||||
// This, on the other hand, should be applied to the current
|
||||
// pipeline stage.
|
||||
++(cdata->_modified);
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,26 +50,30 @@
|
||||
class EXPCL_PANDA qpGeomUsageHint {
|
||||
PUBLISHED:
|
||||
enum UsageHint {
|
||||
// The following are intentionally ordered from most dynamic to
|
||||
// most static. In general, if usage_a < usage_b, then usage_a is
|
||||
// more dynamic than usage_b.
|
||||
|
||||
// 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.
|
||||
// temporary objects.
|
||||
UH_stream,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -52,43 +52,6 @@ get_data() const {
|
||||
return cdata->_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::modify_data
|
||||
// Access: Published
|
||||
// Description: Returns a modifiable pointer to the actual vertex
|
||||
// array, so that application code may directly
|
||||
// manipulate the vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_uchar qpGeomVertexArrayData::
|
||||
modify_data() {
|
||||
// Perform copy-on-write: if the reference count on the vertex data
|
||||
// is greater than 1, assume some other GeomVertexData has the same
|
||||
// pointer, so make a copy of it first.
|
||||
CDWriter cdata(_cycler);
|
||||
|
||||
if (cdata->_data.get_ref_count() > 1) {
|
||||
PTA_uchar orig_data = cdata->_data;
|
||||
cdata->_data = PTA_uchar();
|
||||
cdata->_data.v() = orig_data.v();
|
||||
}
|
||||
++(cdata->_modified);
|
||||
|
||||
return cdata->_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::set_data
|
||||
// Access: Published
|
||||
// Description: Replaces the vertex data array with a completely new
|
||||
// array.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexArrayData::
|
||||
set_data(CPTA_uchar array) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_data = (PTA_uchar &)array;
|
||||
++(cdata->_modified);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::get_num_vertices
|
||||
// Access: Published
|
||||
|
@ -17,6 +17,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpgeomVertexArrayData.h"
|
||||
#include "qpgeom.h"
|
||||
#include "preparedGraphicsObjects.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
@ -82,6 +83,43 @@ qpGeomVertexArrayData::
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::modify_data
|
||||
// Access: Published
|
||||
// Description: Returns a modifiable pointer to the actual vertex
|
||||
// array, so that application code may directly
|
||||
// manipulate the vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PTA_uchar qpGeomVertexArrayData::
|
||||
modify_data() {
|
||||
// Perform copy-on-write: if the reference count on the vertex data
|
||||
// is greater than 1, assume some other GeomVertexData has the same
|
||||
// pointer, so make a copy of it first.
|
||||
CDWriter cdata(_cycler);
|
||||
|
||||
if (cdata->_data.get_ref_count() > 1) {
|
||||
PTA_uchar orig_data = cdata->_data;
|
||||
cdata->_data = PTA_uchar();
|
||||
cdata->_data.v() = orig_data.v();
|
||||
}
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
|
||||
return cdata->_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::set_data
|
||||
// Access: Published
|
||||
// Description: Replaces the vertex data array with a completely new
|
||||
// array.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexArrayData::
|
||||
set_data(CPTA_uchar array) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_data = (PTA_uchar &)array;
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexArrayData::set_num_vertices
|
||||
// Access: Published
|
||||
@ -125,7 +163,7 @@ set_num_vertices(int n) {
|
||||
}
|
||||
}
|
||||
|
||||
++(cdata->_modified);
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ PUBLISHED:
|
||||
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
|
||||
|
||||
INLINE CPTA_uchar get_data() const;
|
||||
INLINE PTA_uchar modify_data();
|
||||
INLINE void set_data(CPTA_uchar data);
|
||||
PTA_uchar modify_data();
|
||||
void set_data(CPTA_uchar data);
|
||||
|
||||
INLINE int get_num_vertices() const;
|
||||
bool set_num_vertices(int n);
|
||||
|
@ -45,6 +45,7 @@ class GeomTri;
|
||||
class GeomTristrip;
|
||||
class GeomTrifan;
|
||||
class GeomSphere;
|
||||
class qpGeom;
|
||||
class qpGeomVertexData;
|
||||
class qpGeomVertexArrayData;
|
||||
class qpGeomPrimitive;
|
||||
@ -183,7 +184,7 @@ public:
|
||||
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0;
|
||||
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0;
|
||||
|
||||
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data)=0;
|
||||
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data)=0;
|
||||
virtual void draw_triangles(const qpGeomTriangles *primitive)=0;
|
||||
virtual void draw_tristrips(const qpGeomTristrips *primitive)=0;
|
||||
virtual void draw_trifans(const qpGeomTrifans *primitive)=0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user