diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index a2980d29a1..44e18a2806 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -31,7 +31,8 @@ lru.h \ parasiteBuffer.I parasiteBuffer.h \ windowProperties.I windowProperties.h \ - renderBuffer.h + renderBuffer.h \ + stencilRenderStates.h #define INCLUDED_SOURCES \ standardMunger.cxx \ @@ -50,7 +51,8 @@ graphicsDevice.cxx \ parasiteBuffer.cxx \ windowProperties.cxx \ - lru.cxx + lru.cxx \ + stencilRenderStates.cxx #define INSTALL_HEADERS \ standardMunger.I standardMunger.h \ @@ -72,7 +74,8 @@ lru.h \ parasiteBuffer.I parasiteBuffer.h \ windowProperties.I windowProperties.h \ - renderBuffer.h + renderBuffer.h \ + stencilRenderStates.h #define IGATESCAN all diff --git a/panda/src/display/display_composite2.cxx b/panda/src/display/display_composite2.cxx index e7aa64f68f..e066b83210 100644 --- a/panda/src/display/display_composite2.cxx +++ b/panda/src/display/display_composite2.cxx @@ -9,3 +9,4 @@ #include "graphicsOutput.cxx" #include "parasiteBuffer.cxx" #include "lru.cxx" +#include "stencilRenderStates.cxx" diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 3bb18d3430..a002d0680d 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -538,6 +538,17 @@ get_supports_basic_shaders() const { return _supports_basic_shaders; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_supports_two_sided_stencil +// Access: Published +// Description: Returns true if this particular GSG supports +// two sided stencil. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_supports_two_sided_stencil() const { + return _supports_two_sided_stencil; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_color_scale_via_lighting // Access: Published @@ -739,3 +750,23 @@ set_current_properties(FrameBufferProperties *prop) { _current_properties = prop; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_stencil_clear_value +// Access: Public +// Description: Set current stencil clear value. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +set_stencil_clear_value(unsigned int stencil_clear_value) { + _stencil_clear_value = stencil_clear_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_stencil_clear_value +// Access: Public +// Description: Get current stencil clear value. +//////////////////////////////////////////////////////////////////// +INLINE unsigned int GraphicsStateGuardian:: +get_stencil_clear_value() { + return _stencil_clear_value; +} + diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 9682c15631..990ebf3c07 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -85,7 +85,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, { _coordinate_system = CS_invalid; _internal_transform = TransformState::make_identity(); - + set_coordinate_system(get_default_coordinate_system()); _data_reader = (GeomVertexDataPipelineReader *)NULL; @@ -94,7 +94,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, _current_lens = (Lens *)NULL; _projection_mat = TransformState::make_identity(); _projection_mat_inv = TransformState::make_identity(); - + _needs_reset = true; _is_valid = false; _current_properties = NULL; @@ -130,7 +130,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, _supports_compressed_texture = false; _compressed_texture_formats.clear(); _compressed_texture_formats.set_bit(Texture::CM_off); - + // Assume no limits on number of lights or clip planes. _max_lights = -1; _max_clip_planes = -1; @@ -152,12 +152,18 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, _supports_depth_texture = false; _supports_shadow_filter = false; _supports_basic_shaders = false; + + _supports_stencil_wrap = false; + _supports_two_sided_stencil = false; + _supported_geom_rendering = 0; // If this is true, then we can apply a color and/or color scale by // twiddling the material and/or ambient light (which could mean // enabling lighting even without a LightAttrib). _color_scale_via_lighting = color_scale_via_lighting; + + _stencil_render_states = 0; } //////////////////////////////////////////////////////////////////// @@ -170,6 +176,11 @@ GraphicsStateGuardian:: if (_global_gsg == this) { _global_gsg = NULL; } + + if (_stencil_render_states) { + delete _stencil_render_states; + _stencil_render_states = 0; + } } //////////////////////////////////////////////////////////////////// @@ -229,11 +240,11 @@ set_coordinate_system(CoordinateSystem cs) { _inv_cs_transform = TransformState::make_identity(); } else { - _cs_transform = + _cs_transform = TransformState::make_mat (LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system)); - _inv_cs_transform = + _inv_cs_transform = TransformState::make_mat (LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system)); @@ -276,11 +287,11 @@ reset() { _internal_transform = _cs_transform; _scene_null = new SceneSetup; _scene_setup = _scene_null; - + _color_write_mask = ColorWriteAttrib::C_all; _color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); _depth_clear_value = 1.0f; - _stencil_clear_value = 0.0f; + _stencil_clear_value = 0; _accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); _has_scene_graph_color = false; @@ -305,6 +316,12 @@ reset() { _last_max_stage_index = 0; _is_valid = true; + + if (_stencil_render_states) { + delete _stencil_render_states; + _stencil_render_states = 0; + } + _stencil_render_states = new StencilRenderStates (this); } //////////////////////////////////////////////////////////////////// @@ -737,7 +754,7 @@ clear(DrawableRegion *clearable) { // // * window size // * texture coordinates of card center -// +// // This routine can fetch these values as well, by // shoehorning them into a matrix. In this way, we avoid // the need for a separate routine to fetch these values. @@ -756,7 +773,7 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) { const LMatrix4f *val2; static LMatrix4f t1; static LMatrix4f t2; - + switch(spec._func) { case ShaderContext::SMF_compose: val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1); @@ -881,6 +898,14 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa } case ShaderContext::SMO_view_x_to_view: { const ShaderInput *input = _target._shader->get_shader_input(name); + + if (input->get_nodepath().is_empty()) { + gsg_cat.error() + << "SHADER INPUT ASSERT: " + << name + << "\n"; + } + nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat()); t = input->get_nodepath().get_net_transform()->get_mat() * get_scene()->get_world_transform()->get_mat(); @@ -888,6 +913,14 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa } case ShaderContext::SMO_view_to_view_x: { const ShaderInput *input = _target._shader->get_shader_input(name); + + if (input->get_nodepath().is_empty()) { + gsg_cat.error() + << "SHADER INPUT ASSERT: " + << name + << "\n"; + } + nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat()); t = get_scene()->get_camera_transform()->get_mat() * invert(input->get_nodepath().get_net_transform()->get_mat()); @@ -1032,7 +1065,7 @@ begin_frame(Thread *current_thread) { // be accurately updated. _state_rs = 0; _state.clear_to_zero(); - + return true; } @@ -1068,11 +1101,11 @@ begin_scene() { void GraphicsStateGuardian:: end_scene() { // We should clear this pointer now, so that we don't keep unneeded - // reference counts dangling. We keep around a "null" scene setup + // reference counts dangling. We keep around a "null" scene setup // object instead of using a null pointer to avoid special-case code // in set_state_and_transform. _scene_setup = _scene_null; - + // Undo any lighting we had enabled last scene, to force the lights // to be reissued, in case their parameters or positions have // changed between scenes. @@ -1255,7 +1288,7 @@ finish_decal() { // are ok, false to abort this group of primitives. //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: -begin_draw_primitives(const GeomPipelineReader *geom_reader, +begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader) { _munger = munger; @@ -1360,7 +1393,7 @@ do_issue_clip_plane() { for (i = 0; i < cur_max_planes; i++) { _clip_plane_info[i]._next_enabled = false; } - + CPT(ClipPlaneAttrib) new_attrib = attrib->filter_to_max(_max_clip_planes); bool any_bound = false; @@ -1391,7 +1424,7 @@ do_issue_clip_plane() { break; } } - + // See if there are any unbound plane ids if (cur_plane_id == -1) { for (i = 0; i < cur_max_planes; i++) { @@ -1402,7 +1435,7 @@ do_issue_clip_plane() { } } } - + // If there were no unbound plane ids, see if we can replace // a currently unused but previously bound id if (cur_plane_id == -1) { @@ -1424,21 +1457,21 @@ do_issue_clip_plane() { nassertv(cur_max_planes == (int)_clip_plane_info.size()); } } - + if (cur_plane_id >= 0) { enable_clip_plane(cur_plane_id, true); _clip_plane_info[cur_plane_id]._enabled = true; _clip_plane_info[cur_plane_id]._next_enabled = true; - + if (!any_bound) { begin_bind_clip_planes(); any_bound = true; } - + // This is the first time this frame that this plane has been // bound to this particular id. bind_clip_plane(plane, cur_plane_id); - + } else if (cur_plane_id == -1) { gsg_cat.warning() << "Failed to bind " << plane << " to id.\n"; @@ -1523,7 +1556,7 @@ do_issue_color_scale() { const ColorScaleAttrib *attrib = _target._color_scale; _color_scale_enabled = attrib->has_scale(); _current_color_scale = attrib->get_scale(); - + if (_color_blend_involves_color_scale) { _state_rs = 0; _state._transparency = 0; @@ -1583,19 +1616,19 @@ do_issue_light() { NodePath light = new_light->get_on_light(li); nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL); Light *light_obj = light.node()->as_light(); - + num_enabled++; - + // Lighting should be enabled before we apply any lights. enable_lighting(true); _lighting_enabled = true; _lighting_enabled_this_frame = true; - + if (light_obj->get_type() == AmbientLight::get_class_type()) { // Ambient lights don't require specific light ids; simply add // in the ambient contribution to the current total cur_ambient_light += light_obj->get_color(); - + } else { // Check to see if this light has already been bound to an id int cur_light_id = -1; @@ -1606,7 +1639,7 @@ do_issue_light() { enable_light(i, true); _light_info[i]._enabled = true; _light_info[i]._next_enabled = true; - + if (!any_bound) { begin_bind_lights(); any_bound = true; @@ -1615,7 +1648,7 @@ do_issue_light() { break; } } - + // See if there are any unbound light ids if (cur_light_id == -1) { for (i = 0; i < cur_max_lights; i++) { @@ -1626,7 +1659,7 @@ do_issue_light() { } } } - + // If there were no unbound light ids, see if we can replace // a currently unused but previously bound id if (cur_light_id == -1) { @@ -1638,7 +1671,7 @@ do_issue_light() { } } } - + // If we *still* don't have a light id, slot a new one. if (cur_light_id == -1) { if (_max_lights < 0 || cur_max_lights < _max_lights) { @@ -1648,21 +1681,21 @@ do_issue_light() { nassertv(cur_max_lights == (int)_light_info.size()); } } - + if (cur_light_id >= 0) { enable_light(cur_light_id, true); _light_info[cur_light_id]._enabled = true; _light_info[cur_light_id]._next_enabled = true; - + if (!any_bound) { begin_bind_lights(); any_bound = true; } - + // This is the first time this frame that this light has been // bound to this particular id. light_obj->bind(this, light, cur_light_id); - + } else if (cur_light_id == -1) { gsg_cat.warning() << "Failed to bind " << light << " to id.\n"; @@ -1670,7 +1703,7 @@ do_issue_light() { } } } - + // Disable all unused lights for (i = 0; i < cur_max_lights; i++) { if (!_light_info[i]._next_enabled) { @@ -1973,7 +2006,7 @@ init_frame_pstats() { _data_transferred_pcollector.clear_level(); _vertex_buffer_switch_pcollector.clear_level(); _index_buffer_switch_pcollector.clear_level(); - + _primitive_batches_pcollector.clear_level(); _primitive_batches_tristrip_pcollector.clear_level(); _primitive_batches_trifan_pcollector.clear_level(); @@ -1983,7 +2016,7 @@ init_frame_pstats() { _vertices_trifan_pcollector.clear_level(); _vertices_tri_pcollector.clear_level(); _vertices_other_pcollector.clear_level(); - + _state_pcollector.clear_level(); _transform_state_pcollector.clear_level(); _texture_state_pcollector.clear_level(); @@ -1994,7 +2027,7 @@ init_frame_pstats() { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_unlit_state // Access: Protected, Static -// Description: +// Description: //////////////////////////////////////////////////////////////////// CPT(RenderState) GraphicsStateGuardian:: get_unlit_state() { @@ -2008,7 +2041,7 @@ get_unlit_state() { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_unclipped_state // Access: Protected, Static -// Description: +// Description: //////////////////////////////////////////////////////////////////// CPT(RenderState) GraphicsStateGuardian:: get_unclipped_state() { @@ -2022,7 +2055,7 @@ get_unclipped_state() { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_untextured_state // Access: Protected, Static -// Description: +// Description: //////////////////////////////////////////////////////////////////// CPT(RenderState) GraphicsStateGuardian:: get_untextured_state() { @@ -2043,7 +2076,7 @@ get_untextured_state() { void GraphicsStateGuardian:: traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) { PreparedGraphicsObjects::Textures::const_iterator ti; - for (ti = _prepared_objects->_prepared_textures.begin(); + for (ti = _prepared_objects->_prepared_textures.begin(); ti != _prepared_objects->_prepared_textures.end(); ++ti) { bool bResult=(*pertex_callbackfn)(*ti,callback_arg); @@ -2068,7 +2101,7 @@ calc_projection_mat(const Lens *lens) { if (!lens->is_linear()) { return NULL; } - + return TransformState::make_identity(); } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 257917bf28..bca41604ef 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -47,6 +47,7 @@ #include "bitMask.h" #include "texture.h" #include "occlusionQueryContext.h" +#include "stencilRenderStates.h" class DrawableRegion; class GraphicsEngine; @@ -120,11 +121,12 @@ PUBLISHED: INLINE bool get_supports_depth_texture() const; INLINE bool get_supports_shadow_filter() const; INLINE bool get_supports_basic_shaders() const; - + INLINE bool get_supports_two_sided_stencil() const; + virtual int get_supported_geom_rendering() const; INLINE bool get_color_scale_via_lighting() const; - + void set_coordinate_system(CoordinateSystem cs); INLINE CoordinateSystem get_coordinate_system() const; virtual CoordinateSystem get_internal_coordinate_system() const; @@ -147,7 +149,7 @@ public: virtual ShaderContext *prepare_shader(ShaderExpansion *shader); virtual void release_shader(ShaderContext *sc); - + virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data); virtual void release_vertex_buffer(VertexBufferContext *vbc); @@ -158,7 +160,7 @@ public: virtual void begin_occlusion_query(); virtual PT(OcclusionQueryContext) end_occlusion_query(); - virtual PT(GeomMunger) get_geom_munger(const RenderState *state, + virtual PT(GeomMunger) get_geom_munger(const RenderState *state, Thread *current_thread); virtual PT(GeomMunger) make_geom_munger(const RenderState *state, Thread *current_thread); @@ -176,7 +178,7 @@ public: const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered); const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t); - + virtual void prepare_display_region(DisplayRegionPipelineReader *dr, Lens::StereoChannel stereo_channel); @@ -189,14 +191,14 @@ public: virtual void end_frame(Thread *current_thread); void set_current_properties(FrameBufferProperties *properties); - + virtual bool depth_offset_decals(); virtual CPT(RenderState) begin_decal_base_first(); virtual CPT(RenderState) begin_decal_nested(); virtual CPT(RenderState) begin_decal_base_second(); virtual void finish_decal(); - virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, + virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader); virtual void draw_triangles(const GeomPrimitivePipelineReader *reader); @@ -213,28 +215,31 @@ public: INLINE CPT(TransformState) get_external_transform() const; INLINE CPT(TransformState) get_internal_transform() const; - + RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop); - + INLINE const DisplayRegion *get_current_display_region() const; INLINE Lens::StereoChannel get_current_stereo_channel() const; INLINE const Lens *get_current_lens() const; virtual const TransformState *get_cs_transform() const; INLINE const TransformState *get_inv_cs_transform() const; - + void do_issue_clip_plane(); void do_issue_color(); void do_issue_color_scale(); void do_issue_light(); - - virtual void bind_light(PointLight *light_obj, const NodePath &light, + + virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id); virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id); virtual void bind_light(Spotlight *light_obj, const NodePath &light, int light_id); + INLINE void set_stencil_clear_value(unsigned int stencil_clear_value); + INLINE unsigned int get_stencil_clear_value(); + protected: INLINE NodePath get_light(int light_id) const; virtual void enable_lighting(bool enable); @@ -267,7 +272,7 @@ protected: protected: PT(SceneSetup) _scene_null; PT(SceneSetup) _scene_setup; - + AttribSlots _state; AttribSlots _target; CPT(RenderState) _state_rs; @@ -282,7 +287,7 @@ protected: unsigned int _color_write_mask; Colorf _color_clear_value; float _depth_clear_value; - bool _stencil_clear_value; + unsigned int _stencil_clear_value; Colorf _accum_clear_value; CPT(DisplayRegion) _current_display_region; @@ -291,7 +296,7 @@ protected: CPT(TransformState) _projection_mat; CPT(TransformState) _projection_mat_inv; FrameBufferProperties *_current_properties; - + CoordinateSystem _coordinate_system; CoordinateSystem _internal_coordinate_system; CPT(TransformState) _cs_transform; @@ -342,7 +347,7 @@ protected: bool _supports_compressed_texture; BitMask32 _compressed_texture_formats; - + int _max_lights; int _max_clip_planes; @@ -359,11 +364,17 @@ protected: bool _supports_depth_texture; bool _supports_shadow_filter; bool _supports_basic_shaders; + + bool _supports_stencil_wrap; + bool _supports_two_sided_stencil; + int _supported_geom_rendering; bool _color_scale_via_lighting; int _stereo_buffer_mask; + StencilRenderStates *_stencil_render_states; + public: // Statistics static PStatCollector _vertex_buffer_switch_pcollector; @@ -384,7 +395,7 @@ public: static PStatCollector _vertices_tristrip_pcollector; static PStatCollector _vertices_trifan_pcollector; static PStatCollector _vertices_tri_pcollector; - static PStatCollector _vertices_other_pcollector; + static PStatCollector _vertices_other_pcollector; static PStatCollector _vertices_indexed_tristrip_pcollector; static PStatCollector _state_pcollector; static PStatCollector _transform_state_pcollector; diff --git a/panda/src/display/stencilRenderStates.cxx b/panda/src/display/stencilRenderStates.cxx new file mode 100644 index 0000000000..e3bdde1fe0 --- /dev/null +++ b/panda/src/display/stencilRenderStates.cxx @@ -0,0 +1,85 @@ +// Filename: stencilRenderStates.cxx +// Created by: aignacio (17May06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2006, 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 "graphicsStateGuardian.h" +#include "stencilRenderStates.h" + +StencilRenderStates:: +StencilRenderStates (GraphicsStateGuardian *gsg) { + + int index; + + // clear all + for (index = 0; index < SRS_total; index++) { + _stencil_render_state_array [index] = 0; + _stencil_function_array [index] = 0; + } + + // set default render states + set_stencil_render_state (false, SRS_clear_value, 0); + + set_stencil_render_state (false, SRS_reference, 0); + + set_stencil_render_state (false, SRS_read_mask, ~0); + set_stencil_render_state (false, SRS_write_mask, ~0); + + set_stencil_render_state (false, SRS_front_enable, 0); + set_stencil_render_state (false, SRS_front_comparison_function, SCF_always); + set_stencil_render_state (false, SRS_front_stencil_fail_operation, SO_keep); + set_stencil_render_state (false, SRS_front_stencil_pass_z_fail_operation, SO_keep); + set_stencil_render_state (false, SRS_front_stencil_pass_z_pass_operation, SO_keep); + + set_stencil_render_state (false, SRS_back_enable, 0); + set_stencil_render_state (false, SRS_back_comparison_function, SCF_always); + set_stencil_render_state (false, SRS_back_stencil_fail_operation, SO_keep); + set_stencil_render_state (false, SRS_back_stencil_pass_z_fail_operation, SO_keep); + set_stencil_render_state (false, SRS_back_stencil_pass_z_pass_operation, SO_keep); + + _gsg = gsg; +} + +StencilRenderStates:: +~StencilRenderStates (void) { + +} + +void StencilRenderStates:: +set_stencil_render_state (bool execute_function, StencilRenderStates::StencilRenderState stencil_render_state, StencilType value) { + + _stencil_render_state_array [stencil_render_state] = value; + + if (execute_function) { + StencilFunction stencil_function; + + stencil_function = _stencil_function_array [stencil_render_state]; + if (stencil_function) { + stencil_function (stencil_render_state, this); + } + } +} + +StencilType StencilRenderStates:: +get_stencil_render_state (StencilRenderStates::StencilRenderState stencil_render_state) { + return _stencil_render_state_array [stencil_render_state]; +} + +void StencilRenderStates:: +set_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilFunction stencil_function) { + _stencil_function_array [stencil_render_state] = stencil_function; +} + diff --git a/panda/src/display/stencilRenderStates.h b/panda/src/display/stencilRenderStates.h new file mode 100644 index 0000000000..57be88194a --- /dev/null +++ b/panda/src/display/stencilRenderStates.h @@ -0,0 +1,102 @@ +// Filename: stencilRenderStates.h +// Created by: aignacio (17May06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2006, 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 STENCILRENDERSTATES_H +#define STENCILRENDERSTATES_H + +class GraphicsStateGuardian; +typedef unsigned int StencilType; + +//////////////////////////////////////////////////////////////////// +// Class : StencilRenderStates +// Description : An abstract cross-platform class for stencil buffer +// render states. Each gsg needs to create its own +// low-level functions on how to set each render state. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA StencilRenderStates { + +PUBLISHED: + enum StencilRenderState + { + SRS_clear_value, + + SRS_reference, + + SRS_read_mask, + SRS_write_mask, + + SRS_front_enable, + SRS_front_comparison_function, + SRS_front_stencil_fail_operation, + SRS_front_stencil_pass_z_fail_operation, + SRS_front_stencil_pass_z_pass_operation, + + SRS_back_enable, + SRS_back_comparison_function, + SRS_back_stencil_fail_operation, + SRS_back_stencil_pass_z_fail_operation, + SRS_back_stencil_pass_z_pass_operation, + + SRS_total, + + SRS_first = 0, + }; + + enum StencilComparisonFunction + { + SCF_never, + SCF_less_than, + SCF_equal, + SCF_less_than_or_equal, + SCF_greater_than, + SCF_not_equal, + SCF_greater_than_or_equal, + SCF_always, + }; + + enum StencilOperation + { + SO_keep, + SO_zero, + SO_replace, + SO_increment, + SO_decrement, + SO_invert, + SO_increment_saturate, + SO_decrement_saturate, + }; + +public: + typedef void (*StencilFunction) (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states); + + StencilRenderStates (GraphicsStateGuardian *gsg); + ~StencilRenderStates (void); + + void set_stencil_render_state (bool execute_function, StencilRenderStates::StencilRenderState stencil_render_state, StencilType value); + StencilType get_stencil_render_state (StencilRenderStates::StencilRenderState stencil_render_state); + + void set_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilFunction stencil_function); + + GraphicsStateGuardian *_gsg; + +private: + StencilType _stencil_render_state_array [SRS_total]; + StencilFunction _stencil_function_array [SRS_total]; +}; + +#endif diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index e1fd97a64f..b485981528 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -178,6 +178,7 @@ DXGraphicsStateGuardian9:: } #endif + GraphicsStateGuardian::~GraphicsStateGuardian(); } //////////////////////////////////////////////////////////////////// @@ -230,8 +231,7 @@ apply_texture(int i, TextureContext *tc) { DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc); - if (_lru) - { + if (_lru) { _lru -> access_page (dtc -> _lru_page); } @@ -2356,6 +2356,108 @@ void DXGraphicsStateGuardian9::reset_render_states (void) _last_fvf = 0; } +//////////////////////////////////////////////////////////////////// +// DX stencil code section +//////////////////////////////////////////////////////////////////// + +static int dx_stencil_comparison_function_array [ ] = +{ + D3DCMP_NEVER, + D3DCMP_LESS, + D3DCMP_EQUAL, + D3DCMP_LESSEQUAL, + D3DCMP_GREATER, + D3DCMP_NOTEQUAL, + D3DCMP_GREATEREQUAL, + D3DCMP_ALWAYS, +}; + +static int dx_stencil_operation_array [ ] = +{ + D3DSTENCILOP_KEEP, + D3DSTENCILOP_ZERO, + D3DSTENCILOP_REPLACE, + D3DSTENCILOP_INCR, + D3DSTENCILOP_DECR, + D3DSTENCILOP_INVERT, + + D3DSTENCILOP_INCRSAT, + D3DSTENCILOP_DECRSAT, +}; + +void dx_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + StencilType render_state_value; + + DXGraphicsStateGuardian9 *gsg; + + gsg = (DXGraphicsStateGuardian9 *) stencil_render_states -> _gsg; + + render_state_value = stencil_render_states -> get_stencil_render_state (stencil_render_state); + switch (stencil_render_state) + { + case StencilRenderStates::SRS_clear_value: + gsg -> set_stencil_clear_value (render_state_value); + break; + + case StencilRenderStates::SRS_reference: + gsg -> set_render_state (D3DRS_STENCILREF, render_state_value); + break; + + case StencilRenderStates::SRS_read_mask: + gsg -> set_render_state (D3DRS_STENCILMASK, render_state_value); + break; + case StencilRenderStates::SRS_write_mask: + gsg -> set_render_state (D3DRS_STENCILWRITEMASK, render_state_value); + break; + + case StencilRenderStates::SRS_front_enable: + gsg -> set_render_state (D3DRS_STENCILENABLE, render_state_value); + break; + case StencilRenderStates::SRS_front_comparison_function: + gsg -> set_render_state (D3DRS_STENCILFUNC, dx_stencil_comparison_function_array [render_state_value]); + break; + + case StencilRenderStates::SRS_front_stencil_fail_operation: + gsg -> set_render_state (D3DRS_STENCILFAIL, dx_stencil_operation_array [render_state_value]); + break; + case StencilRenderStates::SRS_front_stencil_pass_z_fail_operation: + gsg -> set_render_state (D3DRS_STENCILZFAIL, dx_stencil_operation_array [render_state_value]); + break; + case StencilRenderStates::SRS_front_stencil_pass_z_pass_operation: + gsg -> set_render_state (D3DRS_STENCILPASS, dx_stencil_operation_array [render_state_value]); + break; + + case StencilRenderStates::SRS_back_enable: + gsg -> set_render_state (D3DRS_TWOSIDEDSTENCILMODE, render_state_value); + break; + case StencilRenderStates::SRS_back_comparison_function: + gsg -> set_render_state (D3DRS_CCW_STENCILFUNC, dx_stencil_comparison_function_array [render_state_value]); + break; + case StencilRenderStates::SRS_back_stencil_fail_operation: + gsg -> set_render_state (D3DRS_CCW_STENCILFAIL, dx_stencil_operation_array [render_state_value]); + break; + case StencilRenderStates::SRS_back_stencil_pass_z_fail_operation: + gsg -> set_render_state (D3DRS_CCW_STENCILZFAIL, dx_stencil_operation_array [render_state_value]); + break; + case StencilRenderStates::SRS_back_stencil_pass_z_pass_operation: + gsg -> set_render_state (D3DRS_CCW_STENCILPASS, dx_stencil_operation_array [render_state_value]); + break; + + default: + break; + } +} + +void dx_set_stencil_functions (StencilRenderStates *stencil_render_states) { + if (stencil_render_states) { + StencilRenderStates::StencilRenderState stencil_render_state; + + for (stencil_render_state = StencilRenderStates::SRS_first; stencil_render_state < StencilRenderStates::SRS_total; stencil_render_state = (StencilRenderStates::StencilRenderState) ((int) stencil_render_state + 1)) { + stencil_render_states -> set_stencil_function (stencil_render_state, dx_stencil_function); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian9::reset // Access: Public, Virtual @@ -2400,6 +2502,9 @@ reset() { _screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0); _screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0); + _supports_stencil_wrap = (d3d_caps.StencilCaps & D3DSTENCILCAPS_INCR) && (d3d_caps.StencilCaps & D3DSTENCILCAPS_DECR); + _supports_two_sided_stencil = ((d3d_caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0); + if (dxgsg9_cat.is_debug()) { dxgsg9_cat.debug() << "\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) @@ -2428,6 +2533,8 @@ reset() { << "\nsupports_stream_offset = " << _supports_stream_offset << "\nsupports_dynamic_textures = " << _screen->_supports_dynamic_textures << "\nsupports_automatic_mipmap_generation = " << _screen->_supports_automatic_mipmap_generation + << "\nsupports_stencil_wrap = " << _supports_stencil_wrap + << "\nsupports_two_sided_stencil = " << _supports_two_sided_stencil << "\nMaxAnisotropy = " << d3d_caps.MaxAnisotropy << "\nDirectX SDK version " DIRECTX_SDK_VERSION << "\n"; @@ -2732,6 +2839,8 @@ reset() { _texture_binding_shader_context = (CLP(ShaderContext) *)NULL; PRINT_REFCNT(dxgsg9, _d3d_device); + + dx_set_stencil_functions (_stencil_render_states); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index b4628cc887..ea52467660 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -52,6 +52,8 @@ #include +#define DEBUG_BUFFERS false + TypeHandle CLP(GraphicsStateGuardian)::_type_handle; PStatCollector CLP(GraphicsStateGuardian)::_load_display_list_pcollector("Draw:Transfer data:Display lists"); @@ -271,6 +273,183 @@ CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties) : CLP(GraphicsStateGuardian):: ~CLP(GraphicsStateGuardian)() { close_gsg(); + + if (_stencil_render_states) { + delete _stencil_render_states; + _stencil_render_states = 0; + } + + GraphicsStateGuardian::~GraphicsStateGuardian(); +} + +//////////////////////////////////////////////////////////////////// +// GL stencil code section +//////////////////////////////////////////////////////////////////// + +static int gl_stencil_comparison_function_array [ ] = +{ + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS, +}; + +static int gl_stencil_operations_array [ ] = +{ + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR_WRAP, + GL_DECR_WRAP, + GL_INVERT, + + GL_INCR, + GL_DECR, +}; + +void __glActiveStencilFace (GraphicsStateGuardian *gsg, GLenum face) { + CLP(GraphicsStateGuardian) *glgsg; + + glgsg = (CLP(GraphicsStateGuardian) *) gsg; + if (gsg -> get_supports_two_sided_stencil ( ) && + glgsg -> _glActiveStencilFaceEXT) { + if (face == GL_FRONT) { + // glActiveStencilFaceEXT (GL_FRONT); + glgsg -> _glActiveStencilFaceEXT (GL_FRONT); + } + else { + // glActiveStencilFaceEXT (GL_BACK); + glgsg -> _glActiveStencilFaceEXT (GL_BACK); + } + } +} + +void gl_front_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + + __glActiveStencilFace (stencil_render_states -> _gsg, GL_FRONT); + glStencilFunc + ( + gl_stencil_comparison_function_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_front_comparison_function)], + stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_reference), + stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_read_mask) + ); +} +void gl_front_stencil_operation (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + __glActiveStencilFace (stencil_render_states -> _gsg, GL_FRONT); + glStencilOp + ( + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_front_stencil_fail_operation)], + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_front_stencil_pass_z_fail_operation)], + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_front_stencil_pass_z_pass_operation)] + ); +} + +void gl_back_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + + bool supports_two_sided_stencil; + + supports_two_sided_stencil = stencil_render_states -> _gsg -> get_supports_two_sided_stencil ( ); + if (supports_two_sided_stencil) { + __glActiveStencilFace (stencil_render_states -> _gsg, GL_BACK); + glStencilFunc + ( + gl_stencil_comparison_function_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_back_comparison_function)], + stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_reference), + stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_read_mask) + ); + } +} + +void gl_back_stencil_operation (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + + bool supports_two_sided_stencil; + + supports_two_sided_stencil = stencil_render_states -> _gsg -> get_supports_two_sided_stencil ( ); + if (supports_two_sided_stencil) { + __glActiveStencilFace (stencil_render_states -> _gsg, GL_BACK); + glStencilOp + ( + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_back_stencil_fail_operation)], + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_back_stencil_pass_z_fail_operation)], + gl_stencil_operations_array [stencil_render_states -> get_stencil_render_state (StencilRenderStates::SRS_back_stencil_pass_z_pass_operation)] + ); + } +} + +void gl_front_back_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + gl_front_stencil_function (stencil_render_state, stencil_render_states); + gl_back_stencil_function (stencil_render_state, stencil_render_states); +} + +void gl_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) { + + StencilType render_state_value; + bool supports_two_sided_stencil; + + supports_two_sided_stencil = stencil_render_states -> _gsg -> get_supports_two_sided_stencil ( ); + + render_state_value = stencil_render_states -> get_stencil_render_state (stencil_render_state); + switch (stencil_render_state) + { + case StencilRenderStates::SRS_clear_value: + stencil_render_states -> _gsg -> set_stencil_clear_value (render_state_value); + break; + + case StencilRenderStates::SRS_write_mask: + glStencilMask (render_state_value); + break; + case StencilRenderStates::SRS_front_enable: + if (render_state_value) { + glEnable (GL_STENCIL_TEST); + } + else { + glDisable (GL_STENCIL_TEST); + } + break; + case StencilRenderStates::SRS_back_enable: + if (supports_two_sided_stencil) { + if (render_state_value) { + glEnable (GL_STENCIL_TEST_TWO_SIDE_EXT); + } + else { + glDisable (GL_STENCIL_TEST_TWO_SIDE_EXT); + } + } + break; + + default: + break; + } +} + +void gl_set_stencil_functions (StencilRenderStates *stencil_render_states) { + + if (stencil_render_states) { + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_clear_value, gl_stencil_function); + + // GL seems to support different read masks and/or reference values for front and back, but DX does not. + // This needs to be cross-platform so do it the DX way by setting the same read mask and reference for both front and back. + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_reference, gl_front_back_stencil_function); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_read_mask, gl_front_back_stencil_function); + + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_write_mask, gl_stencil_function); + + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_front_enable, gl_stencil_function); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_front_comparison_function, gl_front_stencil_function); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_front_stencil_fail_operation, gl_front_stencil_operation); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_front_stencil_pass_z_fail_operation, gl_front_stencil_operation); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_front_stencil_pass_z_pass_operation, gl_front_stencil_operation); + + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_back_enable, gl_stencil_function); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_back_comparison_function, gl_back_stencil_function); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_back_stencil_fail_operation, gl_back_stencil_operation); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_back_stencil_pass_z_fail_operation, gl_back_stencil_operation); + stencil_render_states -> set_stencil_function (StencilRenderStates::SRS_back_stencil_pass_z_pass_operation, gl_back_stencil_operation); + } } //////////////////////////////////////////////////////////////////// @@ -433,7 +612,7 @@ reset() { _glDrawRangeElements = null_glDrawRangeElements; } - _supports_depth_texture = + _supports_depth_texture = has_extension("GL_ARB_depth_texture") || is_at_least_version(1, 4); _supports_3d_texture = false; @@ -505,13 +684,13 @@ reset() { } if (_supports_compressed_texture) { - if (_glCompressedTexImage1D == NULL || - _glCompressedTexImage2D == NULL || - _glCompressedTexImage3D == NULL || - _glCompressedTexSubImage1D == NULL || - _glCompressedTexSubImage2D == NULL || - _glCompressedTexSubImage3D == NULL || - _glGetCompressedTexImage == NULL) { + if (_glCompressedTexImage1D == NULL || + _glCompressedTexImage2D == NULL || + _glCompressedTexImage3D == NULL || + _glCompressedTexSubImage1D == NULL || + _glCompressedTexSubImage2D == NULL || + _glCompressedTexSubImage3D == NULL || + _glGetCompressedTexImage == NULL) { GLCAT.warning() << "Compressed textures advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; _supports_compressed_texture = false; @@ -568,7 +747,7 @@ reset() { _supports_tex_non_pow2 = has_extension("GL_ARB_texture_non_power_of_two"); - + if (is_at_least_version(1, 3)) { _supports_multitexture = true; @@ -758,8 +937,8 @@ reset() { } } - if (_supports_occlusion_query && - (_glGenQueries == NULL || _glBeginQuery == NULL || + if (_supports_occlusion_query && + (_glGenQueries == NULL || _glBeginQuery == NULL || _glEndQuery == NULL || _glDeleteQueries == NULL || _glGetQueryObjectuiv == NULL)) { GLCAT.warning() @@ -920,27 +1099,27 @@ reset() { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: GLCAT.debug(false) << " GL_COMPRESSED_RGB_S3TC_DXT1_EXT\n"; break; - + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: GLCAT.debug(false) << " GL_COMPRESSED_RGBA_S3TC_DXT1_EXT\n"; break; - + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: GLCAT.debug(false) << " GL_COMPRESSED_RGBA_S3TC_DXT3_EXT\n"; break; - + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: GLCAT.debug(false) << " GL_COMPRESSED_RGBA_S3TC_DXT5_EXT\n"; break; - + case GL_COMPRESSED_RGB_FXT1_3DFX: GLCAT.debug(false) << " GL_COMPRESSED_RGB_FXT1_3DFX\n"; break; - + case GL_COMPRESSED_RGBA_FXT1_3DFX: GLCAT.debug(false) << " GL_COMPRESSED_RGBA_FXT1_3DFX\n"; break; - + default: GLCAT.debug(false) << " Unknown compressed format 0x" << hex << formats[i] @@ -954,6 +1133,16 @@ reset() { report_my_gl_errors(); + _supports_stencil_wrap = has_extension("GL_EXT_stencil_wrap"); + _supports_two_sided_stencil = has_extension("GL_EXT_stencil_two_side"); + if (_supports_two_sided_stencil) { + _glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC) + get_extension_func(GLPREFIX_QUOTED, "ActiveStencilFaceEXT"); + } + else { + _glActiveStencilFaceEXT = 0; + } + _auto_rescale_normal = false; // If we don't have double-buffering, don't attempt to write to the @@ -1074,6 +1263,8 @@ reset() { _error_count = 0; report_my_gl_errors(); + + gl_set_stencil_functions (_stencil_render_states); } @@ -1146,7 +1337,7 @@ do_clear(const RenderBuffer &buffer) { // scissor region and viewport) //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: -prepare_display_region(DisplayRegionPipelineReader *dr, +prepare_display_region(DisplayRegionPipelineReader *dr, Lens::StereoChannel stereo_channel) { nassertv(dr != (DisplayRegionPipelineReader *)NULL); GraphicsStateGuardian::prepare_display_region(dr, stereo_channel); @@ -1165,7 +1356,7 @@ prepare_display_region(DisplayRegionPipelineReader *dr, enable_scissor(true); GLP(Scissor)(x, y, width, height); GLP(Viewport)(x, y, width, height); - + report_my_gl_errors(); do_point_size(); } @@ -1287,7 +1478,7 @@ end_frame(Thread *current_thread) { if (PStatClient::is_connected()) { check_nonresident_texture(_prepared_objects->_texture_residency.get_inactive_resident()); check_nonresident_texture(_prepared_objects->_texture_residency.get_active_resident()); - + // OpenGL provides no methods for querying whether a buffer object // (vertex buffer) is resident. In fact, the API appears geared // towards the assumption that such buffers are always resident. @@ -1346,7 +1537,7 @@ end_frame(Thread *current_thread) { report_my_gl_errors(); } - + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::begin_draw_primitives @@ -2330,7 +2521,7 @@ extract_texture_data(Texture *tex) { Texture::ComponentType type = Texture::T_unsigned_byte; Texture::Format format = Texture::F_rgb; Texture::CompressionMode compression = Texture::CM_off; - + switch (internal_format) { case GL_COLOR_INDEX: format = Texture::F_color_index; @@ -2464,8 +2655,8 @@ extract_texture_data(Texture *tex) { tex->set_wrap_u(get_panda_wrap_mode(wrap_u)); tex->set_wrap_v(get_panda_wrap_mode(wrap_v)); tex->set_wrap_w(get_panda_wrap_mode(wrap_w)); - tex->set_border_color(Colorf(border_color[0], border_color[1], - border_color[2], border_color[3])); + tex->set_border_color(Colorf(border_color[0], border_color[1], + border_color[2], border_color[3])); tex->set_minfilter(get_panda_filter_type(minfilter)); // tex->set_magfilter(get_panda_filter_type(magfilter)); @@ -2474,10 +2665,10 @@ extract_texture_data(Texture *tex) { size_t page_size = 0; if (!extract_texture_image(image, page_size, tex, target, page_target, - type, compression, 0)) { + type, compression, 0)) { return false; } - + tex->set_ram_image(image, compression, page_size); if (tex->uses_mipmaps()) { @@ -2488,8 +2679,8 @@ extract_texture_data(Texture *tex) { highest_level = min(highest_level, num_expected_levels); for (int n = 1; n <= highest_level; ++n) { if (!extract_texture_image(image, page_size, tex, target, page_target, - type, compression, n)) { - return false; + type, compression, n)) { + return false; } tex->set_ram_mipmap_image(n, image, page_size); } @@ -2590,7 +2781,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) { CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(_prepared_objects, data); _glGenBuffers(1, &gvbc->_index); - if (GLCAT.is_debug()) { + if (DEBUG_BUFFERS && GLCAT.is_debug()) { GLCAT.debug() << "creating vertex buffer " << gvbc->_index << ": " << data->get_num_rows() << " vertices " @@ -2669,7 +2860,7 @@ release_vertex_buffer(VertexBufferContext *vbc) { CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc); - if (GLCAT.is_debug()) { + if (DEBUG_BUFFERS && GLCAT.is_debug()) { GLCAT.debug() << "deleting vertex buffer " << gvbc->_index << "\n"; } @@ -2758,7 +2949,7 @@ prepare_index_buffer(GeomPrimitive *data) { CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(_prepared_objects, data); _glGenBuffers(1, &gibc->_index); - if (GLCAT.is_debug()) { + if (DEBUG_BUFFERS && GLCAT.is_debug()) { GLCAT.debug() << "creating index buffer " << gibc->_index << ": " << data->get_num_vertices() << " indices (" @@ -2837,7 +3028,7 @@ release_index_buffer(IndexBufferContext *ibc) { CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc); - if (GLCAT.is_debug()) { + if (DEBUG_BUFFERS && GLCAT.is_debug()) { GLCAT.debug() << "deleting index buffer " << gibc->_index << "\n"; } @@ -2990,7 +3181,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, tex->set_x_size(Texture::up_to_power_2(w)); tex->set_y_size(Texture::up_to_power_2(h)); } - + // Sanity check everything. if (z >= 0) { if (!_supports_cube_map) { @@ -3681,7 +3872,7 @@ do_issue_blending() { // all the other blending-related stuff doesn't matter. If the // device doesn't support color-write, we use blending tricks // to effectively disable color write. - unsigned int color_channels = + unsigned int color_channels = _target._color_write->get_channels() & _color_write_mask; if (color_channels == ColorWriteAttrib::C_off) { if (_target._color_write != _state._color_write) { @@ -4179,7 +4370,16 @@ report_extensions() const { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: has_extension(const string &extension) const { - return (_extensions.find(extension) != _extensions.end()); + + bool state; + + state = _extensions.find(extension) != _extensions.end(); + if (GLCAT.is_debug()) { + GLCAT.debug() + << "HAS EXT " << extension << " " << state << "\n"; + } + + return state; } //////////////////////////////////////////////////////////////////// @@ -4254,39 +4454,39 @@ set_draw_buffer(const RenderBuffer &rb) { case RenderBuffer::T_front: GLP(DrawBuffer)(GL_FRONT); break; - + case RenderBuffer::T_back: GLP(DrawBuffer)(GL_BACK); break; - + case RenderBuffer::T_right: GLP(DrawBuffer)(GL_RIGHT); break; - + case RenderBuffer::T_left: GLP(DrawBuffer)(GL_LEFT); break; - + case RenderBuffer::T_front_right: nassertv(_current_properties->is_stereo()); GLP(DrawBuffer)(GL_FRONT_RIGHT); break; - + case RenderBuffer::T_front_left: nassertv(_current_properties->is_stereo()); GLP(DrawBuffer)(GL_FRONT_LEFT); break; - + case RenderBuffer::T_back_right: nassertv(_current_properties->is_stereo()); GLP(DrawBuffer)(GL_BACK_RIGHT); break; - + case RenderBuffer::T_back_left: nassertv(_current_properties->is_stereo()); GLP(DrawBuffer)(GL_BACK_LEFT); break; - + default: GLP(DrawBuffer)(GL_FRONT_AND_BACK); } @@ -4297,7 +4497,7 @@ set_draw_buffer(const RenderBuffer &rb) { (_color_write_mask & ColorWriteAttrib::C_green) != 0, (_color_write_mask & ColorWriteAttrib::C_blue) != 0, (_color_write_mask & ColorWriteAttrib::C_alpha) != 0); - + report_my_gl_errors(); } @@ -4342,40 +4542,40 @@ set_read_buffer(const RenderBuffer &rb) { case RenderBuffer::T_front: GLP(ReadBuffer)(GL_FRONT); break; - + case RenderBuffer::T_back: GLP(ReadBuffer)(GL_BACK); break; - + case RenderBuffer::T_right: GLP(ReadBuffer)(GL_RIGHT); break; - + case RenderBuffer::T_left: GLP(ReadBuffer)(GL_LEFT); break; - + case RenderBuffer::T_front_right: GLP(ReadBuffer)(GL_FRONT_RIGHT); break; - + case RenderBuffer::T_front_left: GLP(ReadBuffer)(GL_FRONT_LEFT); break; - + case RenderBuffer::T_back_right: GLP(ReadBuffer)(GL_BACK_RIGHT); break; - + case RenderBuffer::T_back_left: GLP(ReadBuffer)(GL_BACK_LEFT); break; - + default: GLP(ReadBuffer)(GL_FRONT_AND_BACK); } } - + report_my_gl_errors(); } @@ -4639,16 +4839,16 @@ get_external_image_format(Texture *tex) const { case Texture::F_color_index: case Texture::F_stencil_index: case Texture::F_depth_component: - // This shouldn't be possible. - nassertr(false, GL_RGB); - break; + // This shouldn't be possible. + nassertr(false, GL_RGB); + break; case Texture::F_rgba: case Texture::F_rgbm: case Texture::F_rgba4: case Texture::F_rgba8: case Texture::F_rgba12: - return GL_COMPRESSED_RGBA; + return GL_COMPRESSED_RGBA; case Texture::F_rgb: case Texture::F_rgb5: @@ -4656,20 +4856,20 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgb8: case Texture::F_rgb12: case Texture::F_rgb332: - return GL_COMPRESSED_RGB; + return GL_COMPRESSED_RGB; case Texture::F_alpha: - return GL_COMPRESSED_ALPHA; + return GL_COMPRESSED_ALPHA; case Texture::F_red: case Texture::F_green: case Texture::F_blue: case Texture::F_luminance: - return GL_COMPRESSED_LUMINANCE; + return GL_COMPRESSED_LUMINANCE; case Texture::F_luminance_alpha: case Texture::F_luminance_alphamask: - return GL_COMPRESSED_LUMINANCE_ALPHA; + return GL_COMPRESSED_LUMINANCE_ALPHA; } break; @@ -4679,13 +4879,13 @@ get_external_image_format(Texture *tex) const { } else { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } - + case Texture::CM_dxt3: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - + case Texture::CM_dxt5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - + case Texture::CM_fxt1: if (Texture::has_alpha(tex->get_format())) { return GL_COMPRESSED_RGBA_FXT1_3DFX; @@ -4772,37 +4972,37 @@ get_internal_image_format(Texture *tex) const { case Texture::F_color_index: case Texture::F_stencil_index: case Texture::F_depth_component: - // Unsupported; fall through to below. - break; + // Unsupported; fall through to below. + break; case Texture::F_rgbm: - if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { - return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { - return GL_COMPRESSED_RGBA_FXT1_3DFX; - } else { - return GL_COMPRESSED_RGBA; - } + if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { + return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { + return GL_COMPRESSED_RGBA_FXT1_3DFX; + } else { + return GL_COMPRESSED_RGBA; + } case Texture::F_rgba4: - if (get_supports_compressed_texture_format(Texture::CM_dxt3) && !is_3d) { - return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { - return GL_COMPRESSED_RGBA_FXT1_3DFX; - } else { - return GL_COMPRESSED_RGBA; - } + if (get_supports_compressed_texture_format(Texture::CM_dxt3) && !is_3d) { + return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { + return GL_COMPRESSED_RGBA_FXT1_3DFX; + } else { + return GL_COMPRESSED_RGBA; + } case Texture::F_rgba: case Texture::F_rgba8: case Texture::F_rgba12: - if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) { - return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { - return GL_COMPRESSED_RGBA_FXT1_3DFX; - } else { - return GL_COMPRESSED_RGBA; - } + if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) { + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { + return GL_COMPRESSED_RGBA_FXT1_3DFX; + } else { + return GL_COMPRESSED_RGBA; + } case Texture::F_rgb: case Texture::F_rgb5: @@ -4810,26 +5010,26 @@ get_internal_image_format(Texture *tex) const { case Texture::F_rgb8: case Texture::F_rgb12: case Texture::F_rgb332: - if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { - return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { - return GL_COMPRESSED_RGB_FXT1_3DFX; - } else { - return GL_COMPRESSED_RGB; - } + if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { + return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { + return GL_COMPRESSED_RGB_FXT1_3DFX; + } else { + return GL_COMPRESSED_RGB; + } case Texture::F_alpha: - return GL_COMPRESSED_ALPHA; + return GL_COMPRESSED_ALPHA; case Texture::F_red: case Texture::F_green: case Texture::F_blue: case Texture::F_luminance: - return GL_COMPRESSED_LUMINANCE; + return GL_COMPRESSED_LUMINANCE; case Texture::F_luminance_alpha: case Texture::F_luminance_alphamask: - return GL_COMPRESSED_LUMINANCE_ALPHA; + return GL_COMPRESSED_LUMINANCE_ALPHA; } break; @@ -4839,20 +5039,20 @@ get_internal_image_format(Texture *tex) const { } else { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } - + case Texture::CM_dxt3: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - + case Texture::CM_dxt5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - + case Texture::CM_fxt1: if (Texture::has_alpha(tex->get_format())) { return GL_COMPRESSED_RGBA_FXT1_3DFX; } else { return GL_COMPRESSED_RGB_FXT1_3DFX; } - + case Texture::CM_default: case Texture::CM_off: case Texture::CM_dxt2: @@ -6416,7 +6616,7 @@ upload_texture(CLP(TextureContext) *gtc) { } else { image_compression = tex->get_ram_image_compression(); } - + int width = tex->get_x_size(); int height = tex->get_y_size(); int depth = tex->get_z_size(); @@ -6500,7 +6700,7 @@ upload_texture(CLP(TextureContext) *gtc) { depth = new_depth; } } - + if (!_supports_bgr) { // If the GL doesn't claim to support BGR, we may have to reverse // the component ordering of the image. @@ -6612,10 +6812,10 @@ upload_texture_image(CLP(TextureContext) *gtc, int width, int height, int depth, GLint external_format, GLenum component_type, bool one_page_only, int z, - Texture::CompressionMode image_compression) { + Texture::CompressionMode image_compression) { // Make sure the error stack is cleared out before we begin. report_my_gl_errors(); - + if (target == GL_NONE) { // Unsupported target (e.g. 3-d texturing on GL 1.1). return false; @@ -6631,10 +6831,10 @@ upload_texture_image(CLP(TextureContext) *gtc, if (GLCAT.is_debug()) { if (image_compression != Texture::CM_off) { GLCAT.debug() - << "loading pre-compressed texture " << tex->get_name() << "\n"; + << "loading pre-compressed texture " << tex->get_name() << "\n"; } else if (is_compressed_format(internal_format)) { GLCAT.debug() - << "compressing texture " << tex->get_name() << "\n"; + << "compressing texture " << tex->get_name() << "\n"; } } @@ -6655,17 +6855,17 @@ upload_texture_image(CLP(TextureContext) *gtc, num_ram_mipmap_levels = 1; if (uses_mipmaps) { num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); - + if (num_ram_mipmap_levels == 1) { // No RAM mipmap levels available. Should we generate some? - if (!_supports_generate_mipmap || + if (!_supports_generate_mipmap || (!auto_generate_mipmaps && image_compression == Texture::CM_off)) { // Yes, the GL won't generate them, so we need to. tex->generate_ram_mipmap_images(); num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); } } - + if (num_ram_mipmap_levels != 1) { // We will load the mipmap levels from RAM. Don't ask the GL to // generate them. @@ -6673,7 +6873,7 @@ upload_texture_image(CLP(TextureContext) *gtc, GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, false); } load_ram_mipmaps = true; - + } else { // We don't have mipmap levels in RAM. Ask the GL to generate // them if it can. @@ -6687,10 +6887,10 @@ upload_texture_image(CLP(TextureContext) *gtc, } } } - + int highest_level = 0; - - + + if (!gtc->_already_applied || gtc->_uses_mipmaps != uses_mipmaps || gtc->_internal_format != internal_format || @@ -6716,7 +6916,7 @@ upload_texture_image(CLP(TextureContext) *gtc, external_format, GL_UNSIGNED_BYTE, blank_image); delete blank_image; } - + for (int n = 0; n < num_ram_mipmap_levels; ++n) { const unsigned char *image = tex->get_ram_mipmap_image(n); if (image == (const unsigned char *)NULL) { @@ -6746,7 +6946,7 @@ upload_texture_image(CLP(TextureContext) *gtc, 0, image_size, image); } break; - + case GL_TEXTURE_3D: if (_supports_3d_texture) { if (image_compression == Texture::CM_off) { @@ -6754,7 +6954,7 @@ upload_texture_image(CLP(TextureContext) *gtc, width, height, depth, 0, external_format, component_type, image); } else { - _glCompressedTexImage3D(target, n, external_format, width, + _glCompressedTexImage3D(target, n, external_format, width, height, depth, 0, image_size, image); } @@ -6763,14 +6963,14 @@ upload_texture_image(CLP(TextureContext) *gtc, return false; } break; - + default: if (image_compression == Texture::CM_off) { GLP(TexImage2D)(target, n, internal_format, width, height, 0, external_format, component_type, image); } else { - _glCompressedTexImage2D(target, n, external_format, width, height, + _glCompressedTexImage2D(target, n, external_format, width, height, 0, image_size, image); } } @@ -6827,7 +7027,7 @@ upload_texture_image(CLP(TextureContext) *gtc, return false; } break; - + default: if (image_compression == Texture::CM_off) { GLP(TexSubImage2D)(target, n, 0, 0, width, height, @@ -6905,15 +7105,15 @@ get_texture_memory_size(Texture *tex) { if (is_compressed_format(internal_format)) { // Try to get the compressed size. GLint image_size; - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); - + GLenum error_code = GLP(GetError)(); if (error_code != GL_NO_ERROR) { if (GLCAT.is_debug()) { - GLCAT.debug() - << "Couldn't get compressed size for " << tex->get_name() - << " : " << get_error_string(error_code) << "\n"; + GLCAT.debug() + << "Couldn't get compressed size for " << tex->get_name() + << " : " << get_error_string(error_code) << "\n"; } // Fall through to the noncompressed case. } else { @@ -6922,26 +7122,26 @@ get_texture_memory_size(Texture *tex) { } // OK, get the noncompressed size. - GLint red_size, green_size, blue_size, alpha_size, + GLint red_size, green_size, blue_size, alpha_size, luminance_size, intensity_size; GLint depth_size = 0; - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_RED_SIZE, &red_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_GREEN_SIZE, &green_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_LUMINANCE_SIZE, &luminance_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_INTENSITY_SIZE, &intensity_size); if (_supports_depth_texture) { // Actually, this seems to cause problems on some Mesa versions, // even though they advertise GL_ARB_depth_texture. Who needs it. - // GLP(GetTexLevelParameteriv)(page_target, 0, - // GL_TEXTURE_DEPTH_SIZE, &depth_size); + // GLP(GetTexLevelParameteriv)(page_target, 0, + // GL_TEXTURE_DEPTH_SIZE, &depth_size); } GLint width = 1, height = 1, depth = 1; @@ -7013,9 +7213,9 @@ check_nonresident_texture(BufferContextChain &chain) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: extract_texture_image(PTA_uchar &image, size_t &page_size, - Texture *tex, GLenum target, GLenum page_target, - Texture::ComponentType type, - Texture::CompressionMode compression, int n) { + Texture *tex, GLenum target, GLenum page_target, + Texture::ComponentType type, + Texture::CompressionMode compression, int n) { if (target == GL_TEXTURE_CUBE_MAP) { // A cube map, compressed or uncompressed. This we must extract // one page at a time. @@ -7034,8 +7234,8 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, if (compression != Texture::CM_off) { GLint image_size; - GLP(GetTexLevelParameteriv)(page_target, n, - GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); + GLP(GetTexLevelParameteriv)(page_target, n, + GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); nassertr(image_size <= (int)page_size, false); page_size = image_size; } @@ -7044,12 +7244,12 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, for (int z = 0; z < 6; ++z) { page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z; - + if (compression == Texture::CM_off) { - GLP(GetTexImage)(page_target, n, external_format, pixel_type, - image.p() + z * page_size); + GLP(GetTexImage)(page_target, n, external_format, pixel_type, + image.p() + z * page_size); } else { - _glGetCompressedTexImage(page_target, 0, image.p() + z * page_size); + _glGetCompressedTexImage(page_target, 0, image.p() + z * page_size); } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 97ee16c917..212d91f2a8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -78,6 +78,7 @@ typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint lev typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); #endif // __EDG__ //////////////////////////////////////////////////////////////////// @@ -90,12 +91,12 @@ class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian { public: CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties); virtual ~CLP(GraphicsStateGuardian)(); - + virtual void reset(); virtual void do_clear(const RenderBuffer &buffer); - virtual void prepare_display_region(DisplayRegionPipelineReader *dr, + virtual void prepare_display_region(DisplayRegionPipelineReader *dr, Lens::StereoChannel stereo_channel); virtual CPT(TransformState) calc_projection_mat(const Lens *lens); virtual bool prepare_lens(); @@ -103,7 +104,7 @@ public: virtual bool begin_frame(Thread *current_thread); virtual void end_frame(Thread *current_thread); - virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, + virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader); virtual void draw_triangles(const GeomPrimitivePipelineReader *reader); @@ -125,7 +126,7 @@ public: virtual ShaderContext *prepare_shader(ShaderExpansion *shader); virtual void release_shader(ShaderContext *sc); - + void record_deleted_display_list(GLuint index); virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data); @@ -153,11 +154,11 @@ public: void apply_fog(Fog *fog); - virtual void bind_light(PointLight *light_obj, const NodePath &light, + virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id); - virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, + virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id); - virtual void bind_light(Spotlight *light_obj, const NodePath &light, + virtual void bind_light(Spotlight *light_obj, const NodePath &light, int light_id); void print_gfx_visual(); @@ -186,7 +187,7 @@ public: const TransformState *transform); void bind_fbo(GLuint fbo); - + protected: void do_issue_transform(); void do_issue_render_mode(); @@ -207,7 +208,7 @@ protected: void do_issue_tex_gen(); void do_issue_tex_matrix(); - static bool report_errors_loop(int line, const char *source_file, + static bool report_errors_loop(int line, const char *source_file, GLenum error_code, int &error_count); static string get_error_string(GLenum error_code); string show_gl_string(const string &name, GLenum id); @@ -260,7 +261,7 @@ protected: GLenum get_texture_target(Texture::TextureType texture_type) const; GLenum get_texture_wrap_mode(Texture::WrapMode wm) const; static Texture::WrapMode get_panda_wrap_mode(GLenum wm); - static GLenum get_texture_filter_type(Texture::FilterType ft, + static GLenum get_texture_filter_type(Texture::FilterType ft, Texture::Format fmt, bool ignore_mipmaps); static Texture::FilterType get_panda_filter_type(GLenum ft); static GLenum get_component_type(Texture::ComponentType component_type); @@ -271,7 +272,7 @@ protected: static GLint get_texture_apply_mode_type(TextureStage::Mode am); static GLint get_texture_combine_type(TextureStage::CombineMode cm); GLint get_texture_src_type(TextureStage::CombineSource cs, - int last_stage, int last_saved_result, + int last_stage, int last_saved_result, int this_stage) const; static GLint get_texture_operand_type(TextureStage::CombineOperand co); static GLenum get_fog_mode_type(Fog::Mode m); @@ -288,19 +289,19 @@ protected: void specify_texture(Texture *tex); void apply_texture(TextureContext *tc); bool upload_texture(CLP(TextureContext) *gtc); - bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, - GLenum target, GLint internal_format, + bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, + GLenum target, GLint internal_format, int width, int height, int depth, - GLint external_format, GLenum component_type, + GLint external_format, GLenum component_type, bool one_page_only, int z, - Texture::CompressionMode image_compression); + Texture::CompressionMode image_compression); size_t get_texture_memory_size(Texture *tex); void check_nonresident_texture(BufferContextChain &chain); bool extract_texture_image(PTA_uchar &image, size_t &page_size, - Texture *tex, GLenum target, GLenum page_target, - Texture::ComponentType type, - Texture::CompressionMode compression, int n); + Texture *tex, GLenum target, GLenum page_target, + Texture::ComponentType type, + Texture::CompressionMode compression, int n); void do_point_size(); @@ -329,7 +330,7 @@ protected: bool _polygon_offset_enabled; bool _flat_shade_model; int _decal_level; - + bool _dithering_enabled; int _viewport_width; @@ -339,14 +340,14 @@ protected: float _point_size; bool _point_perspective; bool _vertex_blending_enabled; - + PT(ShaderExpansion) _current_shader_expansion; CLP(ShaderContext) *_current_shader_context; PT(ShaderExpansion) _vertex_array_shader_expansion; CLP(ShaderContext) *_vertex_array_shader_context; PT(ShaderExpansion) _texture_binding_shader_expansion; CLP(ShaderContext) *_texture_binding_shader_context; - + #ifdef SUPPORT_IMMEDIATE_MODE CLP(ImmediateModeSender) _sender; bool _use_sender; @@ -358,7 +359,7 @@ protected: GLuint _current_vbuffer_index; GLuint _current_ibuffer_index; GLuint _current_fbo; - + int _error_count; string _gl_vendor; @@ -435,7 +436,7 @@ public: PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC _glFramebufferRenderbuffer; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC _glGetFramebufferAttachmentParameteriv; PFNGLGENERATEMIPMAPEXTPROC _glGenerateMipmap; - + PFNGLDRAWBUFFERSPROC _glDrawBuffers; PFNGLGENQUERIESPROC _glGenQueries; @@ -444,6 +445,8 @@ public: PFNGLDELETEQUERIESPROC _glDeleteQueries; PFNGLGETQUERYOBJECTUIVPROC _glGetQueryObjectuiv; + PFNGLACTIVESTENCILFACEEXTPROC _glActiveStencilFaceEXT; + GLenum _edge_clamp; GLenum _border_clamp; GLenum _mirror_repeat; diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 3dbb37bb19..2578eec7f0 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -100,6 +100,7 @@ showBoundsEffect.I showBoundsEffect.h \ spotlight.I spotlight.h \ stateMunger.I stateMunger.h \ + stencilAttrib.I stencilAttrib.h \ switchNode.I switchNode.h \ texMatrixAttrib.I texMatrixAttrib.h \ texProjectorEffect.I texProjectorEffect.h \ @@ -202,6 +203,7 @@ showBoundsEffect.cxx \ spotlight.cxx \ stateMunger.cxx \ + stencilAttrib.cxx \ switchNode.cxx \ texMatrixAttrib.cxx \ texProjectorEffect.cxx \ @@ -301,6 +303,7 @@ showBoundsEffect.I showBoundsEffect.h \ spotlight.I spotlight.h \ stateMunger.I stateMunger.h \ + stencilAttrib.I stencilAttrib.h \ switchNode.I switchNode.h \ texMatrixAttrib.I texMatrixAttrib.h \ texProjectorEffect.I texProjectorEffect.h \ diff --git a/panda/src/pgraph/attribSlots.I b/panda/src/pgraph/attribSlots.I index 0bb374e26b..91aea86da2 100644 --- a/panda/src/pgraph/attribSlots.I +++ b/panda/src/pgraph/attribSlots.I @@ -43,6 +43,7 @@ clear_to_zero() { _rescale_normal = NULL; _shade_model = NULL; _shader = NULL; + _stencil = NULL; _tex_gen = NULL; _tex_matrix = NULL; _texture = NULL; diff --git a/panda/src/pgraph/attribSlots.cxx b/panda/src/pgraph/attribSlots.cxx index 0bba977bad..abe9a468a1 100644 --- a/panda/src/pgraph/attribSlots.cxx +++ b/panda/src/pgraph/attribSlots.cxx @@ -51,13 +51,14 @@ initialize_defvals() { _defvals._rescale_normal = DCAST(RescaleNormalAttrib,RescaleNormalAttrib::make_default()); _defvals._shade_model = DCAST(ShadeModelAttrib,ShadeModelAttrib::make(ShadeModelAttrib::M_smooth)); _defvals._shader = DCAST(ShaderAttrib,ShaderAttrib::make_off()); + _defvals._stencil = DCAST(StencilAttrib,StencilAttrib::make()); _defvals._tex_gen = DCAST(TexGenAttrib,TexGenAttrib::make()); _defvals._tex_matrix = DCAST(TexMatrixAttrib,TexMatrixAttrib::make()); _defvals._texture = DCAST(TextureAttrib,TextureAttrib::make_all_off()); _defvals._transparency = DCAST(TransparencyAttrib,TransparencyAttrib::make(TransparencyAttrib::M_none)); - + // Step two. Replace each with make_default_impl. - + _defvals._alpha_test = DCAST(AlphaTestAttrib,_defvals._alpha_test->make_default()); _defvals._antialias = DCAST(AntialiasAttrib,_defvals._antialias->make_default()); _defvals._clip_plane = DCAST(ClipPlaneAttrib,_defvals._clip_plane->make_default()); @@ -77,6 +78,7 @@ initialize_defvals() { _defvals._rescale_normal = DCAST(RescaleNormalAttrib,_defvals._rescale_normal->make_default()); _defvals._shade_model = DCAST(ShadeModelAttrib,_defvals._shade_model->make_default()); _defvals._shader = DCAST(ShaderAttrib,_defvals._shader->make_default()); + _defvals._stencil = DCAST(StencilAttrib,_defvals._stencil->make_default()); _defvals._tex_gen = DCAST(TexGenAttrib,_defvals._tex_gen->make_default()); _defvals._tex_matrix = DCAST(TexMatrixAttrib,_defvals._tex_matrix->make_default()); _defvals._texture = DCAST(TextureAttrib,_defvals._texture->make_default()); @@ -118,6 +120,7 @@ AttribSlots(const AttribSlots ©) : _rescale_normal(copy._rescale_normal), _shade_model(copy._shade_model), _shader(copy._shader), + _stencil(copy._stencil), _tex_gen(copy._tex_gen), _tex_matrix(copy._tex_matrix), _texture(copy._texture), @@ -151,6 +154,7 @@ operator =(const AttribSlots &src) { _rescale_normal = src._rescale_normal; _shade_model = src._shade_model; _shader = src._shader; + _stencil = src._stencil; _tex_gen = src._tex_gen; _tex_matrix = src._tex_matrix; _texture = src._texture; @@ -184,10 +188,11 @@ get_slot(int n) const { case 16: return DCAST(RenderAttrib, _rescale_normal); case 17: return DCAST(RenderAttrib, _shade_model); case 18: return DCAST(RenderAttrib, _shader); - case 19: return DCAST(RenderAttrib, _tex_gen); - case 20: return DCAST(RenderAttrib, _tex_matrix); - case 21: return DCAST(RenderAttrib, _texture); - case 22: return DCAST(RenderAttrib, _transparency); + case 19: return DCAST(RenderAttrib, _stencil); + case 20: return DCAST(RenderAttrib, _tex_gen); + case 21: return DCAST(RenderAttrib, _tex_matrix); + case 22: return DCAST(RenderAttrib, _texture); + case 23: return DCAST(RenderAttrib, _transparency); default: nassertr(false, NULL); return NULL; @@ -221,11 +226,11 @@ set_slot(int n, const RenderAttrib *val) { case 16: _rescale_normal = DCAST(RescaleNormalAttrib, val); break; case 17: _shade_model = DCAST(ShadeModelAttrib, val); break; case 18: _shader = DCAST(ShaderAttrib, val); break; - case 19: _tex_gen = DCAST(TexGenAttrib, val); break; - case 20: _tex_matrix = DCAST(TexMatrixAttrib, val); break; - case 21: _texture = DCAST(TextureAttrib, val); break; - case 22: _transparency = DCAST(TransparencyAttrib, val); break; + case 19: _stencil = DCAST(StencilAttrib, val); break; + case 20: _tex_gen = DCAST(TexGenAttrib, val); break; + case 21: _tex_matrix = DCAST(TexMatrixAttrib, val); break; + case 22: _texture = DCAST(TextureAttrib, val); break; + case 23: _transparency = DCAST(TransparencyAttrib, val); break; default: nassertv(false); } } - diff --git a/panda/src/pgraph/attribSlots.h b/panda/src/pgraph/attribSlots.h index a9db7d1fdd..2174e8e962 100644 --- a/panda/src/pgraph/attribSlots.h +++ b/panda/src/pgraph/attribSlots.h @@ -43,6 +43,7 @@ #include "rescaleNormalAttrib.h" #include "shadeModelAttrib.h" #include "shaderAttrib.h" +#include "stencilAttrib.h" #include "texMatrixAttrib.h" #include "texGenAttrib.h" #include "textureAttrib.h" @@ -76,11 +77,12 @@ class EXPCL_PANDA AttribSlots CPT(RescaleNormalAttrib) _rescale_normal; CPT(ShadeModelAttrib) _shade_model; CPT(ShaderAttrib) _shader; + CPT(StencilAttrib) _stencil; CPT(TexGenAttrib) _tex_gen; CPT(TexMatrixAttrib) _tex_matrix; CPT(TextureAttrib) _texture; CPT(TransparencyAttrib) _transparency; - + public: AttribSlots(); AttribSlots(const AttribSlots ©); @@ -91,10 +93,10 @@ class EXPCL_PANDA AttribSlots public: // Each "array" reference requires a switch and a DCAST, so it's not overly fast. - enum { slot_count=23 }; + enum { slot_count=24 }; const RenderAttrib *get_slot(int n) const; void set_slot(int n, const RenderAttrib *attrib); - + private: static AttribSlots _defvals; static void initialize_defvals(); diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 2b40a5e46b..5a4b3301b6 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -247,8 +247,8 @@ ConfigVariableBool m_dual_transparent ConfigVariableBool m_dual_flash ("m-dual-flash", false, PRC_DESC("Set this true to flash any objects that use M_dual, for debugging.")); - - + + ConfigVariableBool asynchronous_loads ("asynchronous-loads", false, PRC_DESC("Set this true to support actual asynchronous loads via the " @@ -258,7 +258,7 @@ ConfigVariableBool asynchronous_loads "this false for now.")); ConfigVariableList load_file_type -("load-file-type", +("load-file-type", PRC_DESC("List the model loader modules that Panda will automatically " "import when a new, unknown model type is loaded. This may be " "either the name of a module, or a space-separate list of filename " @@ -344,6 +344,7 @@ init_libpgraph() { ShowBoundsEffect::init_type(); Spotlight::init_type(); StateMunger::init_type(); + StencilAttrib::init_type(); SwitchNode::init_type(); TexMatrixAttrib::init_type(); TexProjectorEffect::init_type(); @@ -385,7 +386,7 @@ init_libpgraph() { LensNode::register_with_read_factory(); LightAttrib::register_with_read_factory(); LODNode::register_with_read_factory(); - MaterialAttrib::register_with_read_factory(); + MaterialAttrib::register_with_read_factory(); ModelNode::register_with_read_factory(); ModelRoot::register_with_read_factory(); PandaNode::register_with_read_factory(); diff --git a/panda/src/pgraph/pgraph_composite4.cxx b/panda/src/pgraph/pgraph_composite4.cxx index 98d5ee70d7..2a7a7e8eb1 100644 --- a/panda/src/pgraph/pgraph_composite4.cxx +++ b/panda/src/pgraph/pgraph_composite4.cxx @@ -16,6 +16,7 @@ #include "showBoundsEffect.cxx" #include "spotlight.cxx" #include "stateMunger.cxx" +#include "stencilAttrib.cxx" #include "switchNode.cxx" #include "texMatrixAttrib.cxx" #include "texProjectorEffect.cxx" diff --git a/panda/src/pgraph/stencilAttrib.I b/panda/src/pgraph/stencilAttrib.I new file mode 100644 index 0000000000..746fa9303f --- /dev/null +++ b/panda/src/pgraph/stencilAttrib.I @@ -0,0 +1,70 @@ +// Filename: stencilAttrib.I +// Created by: aignacio (18May06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2006, 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: StencilAttrib::Constructor +// Access: Private +// Description: Use StencilAttrib::make() to construct a new +// StencilAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE StencilAttrib:: +StencilAttrib() { + + _stencil_render_states [SRS_clear_value] = 0; + + _stencil_render_states [SRS_reference] = 0; + + _stencil_render_states [SRS_read_mask] = ~0; + _stencil_render_states [SRS_write_mask] = ~0; + + _stencil_render_states [SRS_front_enable] = 0; + _stencil_render_states [SRS_front_comparison_function] = SCF_always; + _stencil_render_states [SRS_front_stencil_fail_operation] = SO_keep; + _stencil_render_states [SRS_front_stencil_pass_z_fail_operation] = SO_keep; + _stencil_render_states [SRS_front_stencil_pass_z_pass_operation] = SO_keep; + + _stencil_render_states [SRS_back_enable] = 0; + _stencil_render_states [SRS_back_comparison_function] = SCF_always; + _stencil_render_states [SRS_back_stencil_fail_operation] = SO_keep; + _stencil_render_states [SRS_back_stencil_pass_z_fail_operation] = SO_keep; + _stencil_render_states [SRS_back_stencil_pass_z_pass_operation] = SO_keep; + + _default = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::set_render_state +// Access: Published +// Description: Sets the render state. +//////////////////////////////////////////////////////////////////// +INLINE void StencilAttrib:: +set_render_state(unsigned int render_state_identifier, unsigned int render_state) { + _stencil_render_states [render_state_identifier] = render_state; + _default = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::get_render_state +// Access: Published +// Description: Returns render state. +//////////////////////////////////////////////////////////////////// +INLINE unsigned int StencilAttrib:: +get_render_state(unsigned int render_state_identifier) const { + return _stencil_render_states [render_state_identifier]; +} diff --git a/panda/src/pgraph/stencilAttrib.cxx b/panda/src/pgraph/stencilAttrib.cxx new file mode 100644 index 0000000000..ba8df25a29 --- /dev/null +++ b/panda/src/pgraph/stencilAttrib.cxx @@ -0,0 +1,186 @@ +// Filename: stencilAttrib.cxx +// Created by: aignacio (18May06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2006, 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 "stencilAttrib.h" +#include "attribSlots.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle StencilAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::make +// Access: Published, Static +// Description: Constructs a new StencilAttrib object. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) StencilAttrib:: +make() { + StencilAttrib *attrib = new StencilAttrib; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void StencilAttrib:: +output(ostream &out) const { + int index; + for (index = 0; index < SRS_total; index++) { + out << "(" << index << "," << _stencil_render_states [index] << ")"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived StencilAttrib +// types to return a unique number indicating whether +// this StencilAttrib is equivalent to the other one. +// +// This should return 0 if the two StencilAttrib objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two StencilAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int StencilAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const StencilAttrib *sa; + DCAST_INTO_R(sa, other, 0); + + int compare_result = 0; + + // quick test to see if both are default states + // which should be the most common case + if (_default && (_default == sa -> _default)) { + + } + else { + int index; + for (index = 0; index < SRS_total; index++) { + if (_stencil_render_states [index] - sa -> _stencil_render_states [index]) { + + // ????? + compare_result = -(index + 1); + break; + } + } + } + + return compare_result; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived StencilAttrib +// types to specify what the default property for a +// StencilAttrib of this type should be. +// +// This should return a newly-allocated StencilAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of StencilAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *StencilAttrib:: +make_default_impl() const { + return new StencilAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::store_into_slot +// Access: Public, Virtual +// Description: Stores this attrib into the appropriate slot of +// an object of class AttribSlots. +//////////////////////////////////////////////////////////////////// +void StencilAttrib:: +store_into_slot(AttribSlots *slots) const { + slots->_stencil = this; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// StencilAttrib. +//////////////////////////////////////////////////////////////////// +void StencilAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void StencilAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + int index; + for (index = 0; index < SRS_total; index++) { + dg.add_int32(_stencil_render_states [index]); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type StencilAttrib is encountered +// in the Bam file. It should create the StencilAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *StencilAttrib:: +make_from_bam(const FactoryParams ¶ms) { + StencilAttrib *attrib = new StencilAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: StencilAttrib::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new StencilAttrib. +//////////////////////////////////////////////////////////////////// +void StencilAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + int index; + for (index = 0; index < SRS_total; index++) { + _stencil_render_states [index] = scan.get_int32(); + } + _default = false; +} diff --git a/panda/src/pgraph/stencilAttrib.h b/panda/src/pgraph/stencilAttrib.h new file mode 100644 index 0000000000..ad41cd853e --- /dev/null +++ b/panda/src/pgraph/stencilAttrib.h @@ -0,0 +1,134 @@ +// Filename: stencilAttrib.h +// Created by: aignacio (18May06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2006, 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 STENCILATTRIB_H +#define STENCILATTRIB_H + +#include "pandabase.h" +#include "renderAttrib.h" + +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : StencilAttrib +// Description : Enables or disables writing of pixel to framebuffer +// based on its alpha value relative to a reference alpha value +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA StencilAttrib : public RenderAttrib { +private: + INLINE StencilAttrib(); + +PUBLISHED: + + // enums are duplicated here from class StencilRenderStates for use in Python + enum StencilRenderState + { + SRS_clear_value, + + SRS_reference, + + SRS_read_mask, + SRS_write_mask, + + SRS_front_enable, + SRS_front_comparison_function, + SRS_front_stencil_fail_operation, + SRS_front_stencil_pass_z_fail_operation, + SRS_front_stencil_pass_z_pass_operation, + + SRS_back_enable, + SRS_back_comparison_function, + SRS_back_stencil_fail_operation, + SRS_back_stencil_pass_z_fail_operation, + SRS_back_stencil_pass_z_pass_operation, + + SRS_total, + + SRS_first = 0, + }; + + enum StencilComparisonFunction + { + SCF_never, + SCF_less_than, + SCF_equal, + SCF_less_than_or_equal, + SCF_greater_than, + SCF_not_equal, + SCF_greater_than_or_equal, + SCF_always, + }; + + enum StencilOperation + { + SO_keep, + SO_zero, + SO_replace, + SO_increment, + SO_decrement, + SO_invert, + SO_increment_saturate, + SO_decrement_saturate, + }; + + static CPT(RenderAttrib) make(); + INLINE void set_render_state (unsigned int render_state_identifier, unsigned int render_state); + INLINE unsigned int get_render_state (unsigned int render_state_identifier) const; + +public: + virtual void output(ostream &out) const; + virtual void store_into_slot(AttribSlots *slots) const; + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +private: + unsigned int _stencil_render_states [SRS_total]; + bool _default; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderAttrib::init_type(); + register_type(_type_handle, "StencilAttrib", + RenderAttrib::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 "stencilAttrib.I" + +#endif +