diff --git a/dtool/Config.pp b/dtool/Config.pp index 9df66114ab..c71ce98a99 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -306,6 +306,14 @@ // only in a development build. #defer SIMULATE_NETWORK_DELAY $[<= $[OPTIMIZE], 3] +// This option compiles in support for immediate-mode OpenGL +// rendering. Since this is normally useful only for researching +// buggy drivers, and since there is a tiny bit of per-primitive +// overhead to have this option available even if it is unused, it is +// by default enabled only in a development build. This has no effect +// on DirectX rendering. +#define SUPPORT_IMMEDIATE_MODE $[<= $[OPTIMIZE], 3] + // Do you want to compile in support for pipelining? This enables // setting and accessing multiple different copies of frame-specific // data stored in nodes, etc. At the moment, Panda cannot actually diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 510f574fdc..21e05510ed 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -226,6 +226,9 @@ $[cdefine DO_MEMORY_USAGE] /* Define if we want to enable min-lag and max-lag. */ $[cdefine SIMULATE_NETWORK_DELAY] +/* Define if we want to allow immediate mode OpenGL rendering. */ +$[cdefine SUPPORT_IMMEDIATE_MODE] + /* Define if we want to compile in support for pipelining. */ $[cdefine DO_PIPELINING] diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 446d2c3ed1..cc35448495 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1041,6 +1041,7 @@ begin_frame() { #ifdef DO_PSTATS _vertices_display_list_pcollector.clear_level(); + _vertices_immediate_pcollector.clear_level(); _primitive_batches_display_list_pcollector.clear_level(); #endif @@ -1297,10 +1298,11 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger, #endif } - if (!vertex_arrays) { +#ifdef SUPPORT_IMMEDIATE_MODE + _use_sender = !vertex_arrays; + if (_use_sender) { // We must use immediate mode to render primitives. _sender.clear(); - _use_sender = true; _sender.add_column(_vertex_data, InternalName::get_normal(), NULL, NULL, GLP(Normal3f), NULL); @@ -1371,10 +1373,10 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger, _sender.add_column(_vertex_data, InternalName::get_vertex(), NULL, GLP(Vertex2f), GLP(Vertex3f), GLP(Vertex4f)); - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { // We may use vertex arrays or buffers to render primitives. - _use_sender = false; - const GeomVertexArrayData *array_data; int num_values; Geom::NumericType numeric_type; @@ -1517,29 +1519,32 @@ draw_triangles(const GeomTriangles *primitive) { } #endif // NDEBUG - _vertices_tri_pcollector.add_level(primitive->get_num_vertices()); - _primitive_batches_tri_pcollector.add_level(1); - +#ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { draw_immediate_simple_primitives(primitive, GL_TRIANGLES); - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { + _vertices_tri_pcollector.add_level(primitive->get_num_vertices()); + _primitive_batches_tri_pcollector.add_level(1); + if (primitive->is_indexed()) { const unsigned char *client_pointer = setup_primitive(primitive); _glDrawRangeElements(GL_TRIANGLES, - primitive->get_min_vertex(), - primitive->get_max_vertex(), - primitive->get_num_vertices(), - get_numeric_type(primitive->get_index_type()), - client_pointer); + primitive->get_min_vertex(), + primitive->get_max_vertex(), + primitive->get_num_vertices(), + get_numeric_type(primitive->get_index_type()), + client_pointer); } else { GLP(DrawArrays)(GL_TRIANGLES, - primitive->get_first_vertex(), - primitive->get_num_vertices()); + primitive->get_first_vertex(), + primitive->get_num_vertices()); } } - + report_my_gl_errors(); } @@ -1556,27 +1561,30 @@ draw_tristrips(const GeomTristrips *primitive) { } #endif // NDEBUG +#ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { draw_immediate_composite_primitives(primitive, GL_TRIANGLE_STRIP); - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) { // One long triangle strip, connected by the degenerate vertices // that have already been set up within the primitive. _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices()); _primitive_batches_tristrip_pcollector.add_level(1); if (primitive->is_indexed()) { - const unsigned char *client_pointer = setup_primitive(primitive); - _glDrawRangeElements(GL_TRIANGLE_STRIP, - primitive->get_min_vertex(), - primitive->get_max_vertex(), - primitive->get_num_vertices(), - get_numeric_type(primitive->get_index_type()), - client_pointer); + const unsigned char *client_pointer = setup_primitive(primitive); + _glDrawRangeElements(GL_TRIANGLE_STRIP, + primitive->get_min_vertex(), + primitive->get_max_vertex(), + primitive->get_num_vertices(), + get_numeric_type(primitive->get_index_type()), + client_pointer); } else { - GLP(DrawArrays)(GL_TRIANGLE_STRIP, - primitive->get_first_vertex(), - primitive->get_num_vertices()); + GLP(DrawArrays)(GL_TRIANGLE_STRIP, + primitive->get_first_vertex(), + primitive->get_num_vertices()); } } else { @@ -1586,32 +1594,32 @@ draw_tristrips(const GeomTristrips *primitive) { _primitive_batches_tristrip_pcollector.add_level(ends.size()); if (primitive->is_indexed()) { - const unsigned char *client_pointer = setup_primitive(primitive); - int index_stride = primitive->get_index_stride(); - GeomVertexReader mins(primitive->get_mins(), 0); - GeomVertexReader maxs(primitive->get_maxs(), 0); - nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && - primitive->get_maxs()->get_num_rows() == (int)ends.size()); - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - _glDrawRangeElements(GL_TRIANGLE_STRIP, - mins.get_data1i(), maxs.get_data1i(), - ends[i] - start, - get_numeric_type(primitive->get_index_type()), - client_pointer + start * index_stride); - start = ends[i] + 2; - } + const unsigned char *client_pointer = setup_primitive(primitive); + int index_stride = primitive->get_index_stride(); + GeomVertexReader mins(primitive->get_mins(), 0); + GeomVertexReader maxs(primitive->get_maxs(), 0); + nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && + primitive->get_maxs()->get_num_rows() == (int)ends.size()); + + unsigned int start = 0; + for (size_t i = 0; i < ends.size(); i++) { + _vertices_tristrip_pcollector.add_level(ends[i] - start); + _glDrawRangeElements(GL_TRIANGLE_STRIP, + mins.get_data1i(), maxs.get_data1i(), + ends[i] - start, + get_numeric_type(primitive->get_index_type()), + client_pointer + start * index_stride); + start = ends[i] + 2; + } } else { - unsigned int start = 0; - int first_vertex = primitive->get_first_vertex(); - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, - ends[i] - start); - start = ends[i] + 2; - } + unsigned int start = 0; + int first_vertex = primitive->get_first_vertex(); + for (size_t i = 0; i < ends.size(); i++) { + _vertices_tristrip_pcollector.add_level(ends[i] - start); + GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, + ends[i] - start); + start = ends[i] + 2; + } } } } @@ -1632,10 +1640,12 @@ draw_trifans(const GeomTrifans *primitive) { } #endif // NDEBUG +#ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { draw_immediate_composite_primitives(primitive, GL_TRIANGLE_FAN); - - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { // Send the individual triangle fans. There's no connecting fans // with degenerate vertices, so no worries about that. CPTA_int ends = primitive->get_ends(); @@ -1686,10 +1696,12 @@ draw_lines(const GeomLines *primitive) { } #endif // NDEBUG +#ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { draw_immediate_simple_primitives(primitive, GL_LINES); - - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { _vertices_other_pcollector.add_level(primitive->get_num_vertices()); _primitive_batches_other_pcollector.add_level(1); @@ -1739,10 +1751,12 @@ draw_points(const GeomPoints *primitive) { } #endif // NDEBUG +#ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { draw_immediate_simple_primitives(primitive, GL_POINTS); - - } else { + } else +#endif // SUPPORT_IMMEDIATE_MODE + { _vertices_other_pcollector.add_level(primitive->get_num_vertices()); _primitive_batches_other_pcollector.add_level(1); @@ -3082,6 +3096,7 @@ wants_texcoords() const { return true; } +#ifdef SUPPORT_IMMEDIATE_MODE //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::draw_immediate_simple_primitives // Access: Protected @@ -3108,7 +3123,9 @@ draw_immediate_simple_primitives(const GeomPrimitive *primitive, GLenum mode) { GLP(End)(); } +#endif // SUPPORT_IMMEDIATE_MODE +#ifdef SUPPORT_IMMEDIATE_MODE //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::draw_immediate_composite_primitives // Access: Protected @@ -3156,6 +3173,7 @@ draw_immediate_composite_primitives(const GeomPrimitive *primitive, GLenum mode) } } } +#endif // SUPPORT_IMMEDIATE_MODE //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::report_errors_loop diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index af29c23392..c481373087 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -157,8 +157,11 @@ public: void dump_state(void); const float *get_light_color(Light *light) const; + +#ifdef SUPPORT_IMMEDIATE_MODE void draw_immediate_simple_primitives(const GeomPrimitive *primitive, GLenum mode); void draw_immediate_composite_primitives(const GeomPrimitive *primitive, GLenum mode); +#endif // SUPPORT_IMMEDIATE_MODE INLINE static bool report_errors(int line, const char *source_file); INLINE void report_my_errors(int line, const char *source_file); @@ -306,8 +309,11 @@ protected: bool _vertex_blending_enabled; CPT(DisplayRegion) _actual_display_region; + +#ifdef SUPPORT_IMMEDIATE_MODE CLP(ImmediateModeSender) _sender; bool _use_sender; +#endif // SUPPORT_IMMEDIATE_MODE #ifdef HAVE_CGGL PT(CgShader) _cg_shader; // The current CgShader object diff --git a/panda/src/glstuff/glImmediateModeSender_src.cxx b/panda/src/glstuff/glImmediateModeSender_src.cxx index 22c160e880..b24bb46905 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.cxx +++ b/panda/src/glstuff/glImmediateModeSender_src.cxx @@ -16,6 +16,7 @@ // //////////////////////////////////////////////////////////////////// +#ifdef SUPPORT_IMMEDIATE_MODE //////////////////////////////////////////////////////////////////// // Function: CLP(ImmediateModeSender)::Destructor @@ -616,3 +617,5 @@ issue_vertex() { (*_func)(4, (const unsigned int *)d); } + +#endif // SUPPORT_IMMEDIATE_MODE diff --git a/panda/src/glstuff/glImmediateModeSender_src.h b/panda/src/glstuff/glImmediateModeSender_src.h index 4e0b94279b..4861c4ef98 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.h +++ b/panda/src/glstuff/glImmediateModeSender_src.h @@ -19,6 +19,8 @@ #include "pandabase.h" #include "geomVertexReader.h" +#ifdef SUPPORT_IMMEDIATE_MODE + //////////////////////////////////////////////////////////////////// // Class : GLImmediateModeSender // Description : This class collects together a handful of objects @@ -225,3 +227,5 @@ private: #include "glImmediateModeSender_src.I" +#endif // SUPPORT_IMMEDIATE_MODE + diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 960ce87ee1..0a01de0d56 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -92,15 +92,17 @@ ConfigVariableBool vertex_arrays PRC_DESC("Set this true to allow the use of vertex arrays for rendering " "OpenGL vertex data. This, or vertex buffers, is the normal " "way of issuing vertices ever since OpenGL 1.1, and you " - "almost always want to have set to true. However, some very " + "almost always want to have this set to true. However, some very " "buggy graphics drivers may have problems handling vertex arrays " "correctly, so if you are experiencing problems you might try " "setting this to false. If this is false, Panda will fall back " "to using immediate-mode commands like glVertex3f(), etc., to " "issue the vertices, which is potentially much slower than " - "vertex arrays. Setting this false causes vertex_buffers to be " - "ignored (since vertex buffers are a special case of vertex " - "arrays in OpenGL). This has no effect on DirectX rendering.")); + "vertex arrays. Setting this false also disables vertex buffers, " + "effectively ignoring the setting of the vertex-buffers variable " + "(since vertex buffers are a special case of vertex arrays in " + "OpenGL). This variable is normally not enabled in a production " + "build. This has no effect on DirectX rendering.")); ConfigVariableBool display_lists ("display-lists", false, diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index ba4c518953..00efb54501 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -189,6 +189,7 @@ static LevelCollectorProperties level_properties[] = { { 1, "Vertices:Triangle strips", { 0.2, 0.5, 0.8 } }, { 1, "Vertices:Indexed triangle strips", { 0.5, 0.2, 0.8 } }, { 1, "Vertices:Display lists", { 0.8, 0.5, 1.0 } }, + { 1, "Vertices:Immediate mode", { 1.0, 0.5, 0.0 } }, { 1, "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 }, { 1, "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } }, { 1, "Geoms", { 0.4, 0.8, 0.3 }, "", 500.0 },