Panda3D
 All Classes Functions Variables Enumerations
graphicsStateGuardian.cxx
00001 // Filename: graphicsStateGuardian.cxx
00002 // Created by:  drose (02eb99)
00003 // Updated by: fperazzi, PandaSE (05May10) (added fetch_ptr_parameter,
00004 //  _max_2d_texture_array_layers, _supports_2d_texture_array,
00005 //  get_supports_cg_profile)
00006 //
00007 ////////////////////////////////////////////////////////////////////
00008 //
00009 // PANDA 3D SOFTWARE
00010 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00011 //
00012 // All use of this software is subject to the terms of the revised BSD
00013 // license.  You should have received a copy of this license along
00014 // with this source code in a file named "LICENSE."
00015 //
00016 ////////////////////////////////////////////////////////////////////
00017 
00018 #include "graphicsStateGuardian.h"
00019 #include "graphicsEngine.h"
00020 #include "config_display.h"
00021 #include "textureContext.h"
00022 #include "vertexBufferContext.h"
00023 #include "indexBufferContext.h"
00024 #include "renderBuffer.h"
00025 #include "light.h"
00026 #include "planeNode.h"
00027 #include "ambientLight.h"
00028 #include "throw_event.h"
00029 #include "clockObject.h"
00030 #include "pStatTimer.h"
00031 #include "geomTristrips.h"
00032 #include "geomTrifans.h"
00033 #include "geomLinestrips.h"
00034 #include "colorWriteAttrib.h"
00035 #include "shader.h"
00036 #include "pnotify.h"
00037 #include "drawableRegion.h"
00038 #include "displayRegion.h"
00039 #include "graphicsOutput.h"
00040 #include "texturePool.h"
00041 #include "geomMunger.h"
00042 #include "ambientLight.h"
00043 #include "directionalLight.h"
00044 #include "pointLight.h"
00045 #include "spotlight.h"
00046 #include "textureReloadRequest.h"
00047 #include "shaderAttrib.h"
00048 #include "materialAttrib.h"
00049 #include "depthWriteAttrib.h"
00050 #include "lightAttrib.h"
00051 #include "texGenAttrib.h"
00052 #include "shaderGenerator.h"
00053 #include "lightLensNode.h"
00054 #include "colorAttrib.h"
00055 #include "colorScaleAttrib.h"
00056 #include "clipPlaneAttrib.h"
00057 #include "fogAttrib.h"
00058 
00059 #include <algorithm>
00060 #include <limits.h>
00061 
00062 #ifdef HAVE_PYTHON
00063 #include "py_panda.h"
00064 #ifndef CPPPARSER
00065 IMPORT_THIS struct Dtool_PyTypedObject Dtool_Texture;
00066 #endif
00067 #endif  // HAVE_PYTHON
00068 
00069 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
00070 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
00071 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
00072 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
00073 PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer");
00074 PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer");
00075 PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
00076 PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
00077 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
00078 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
00079 PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches");
00080 PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector("Primitive batches:Triangle strips");
00081 PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector("Primitive batches:Triangle fans");
00082 PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector("Primitive batches:Triangles");
00083 PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector("Primitive batches:Other");
00084 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips");
00085 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans");
00086 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles");
00087 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector("Vertices:Other");
00088 PStatCollector GraphicsStateGuardian::_state_pcollector("State changes");
00089 PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes:Transforms");
00090 PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures");
00091 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive:Draw");
00092 PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector("Draw:Set State");
00093 PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear");
00094 PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush");
00095 
00096 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
00097 
00098 
00099 PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform");
00100 PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test");
00101 PStatCollector GraphicsStateGuardian::_draw_set_state_antialias_pcollector("Draw:Set State:Antialias");
00102 PStatCollector GraphicsStateGuardian::_draw_set_state_clip_plane_pcollector("Draw:Set State:Clip plane");
00103 PStatCollector GraphicsStateGuardian::_draw_set_state_color_pcollector("Draw:Set State:Color");
00104 PStatCollector GraphicsStateGuardian::_draw_set_state_cull_face_pcollector("Draw:Set State:Cull face");
00105 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_offset_pcollector("Draw:Set State:Depth offset");
00106 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_test_pcollector("Draw:Set State:Depth test");
00107 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_write_pcollector("Draw:Set State:Depth write");
00108 PStatCollector GraphicsStateGuardian::_draw_set_state_render_mode_pcollector("Draw:Set State:Render mode");
00109 PStatCollector GraphicsStateGuardian::_draw_set_state_rescale_normal_pcollector("Draw:Set State:Rescale normal");
00110 PStatCollector GraphicsStateGuardian::_draw_set_state_shade_model_pcollector("Draw:Set State:Shade model");
00111 PStatCollector GraphicsStateGuardian::_draw_set_state_blending_pcollector("Draw:Set State:Blending");
00112 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_pcollector("Draw:Set State:Shader");
00113 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_parameters_pcollector("Draw:Set State:Shader Parameters");
00114 PStatCollector GraphicsStateGuardian::_draw_set_state_texture_pcollector("Draw:Set State:Texture");
00115 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_matrix_pcollector("Draw:Set State:Tex matrix");
00116 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_gen_pcollector("Draw:Set State:Tex gen");
00117 PStatCollector GraphicsStateGuardian::_draw_set_state_material_pcollector("Draw:Set State:Material");
00118 PStatCollector GraphicsStateGuardian::_draw_set_state_light_pcollector("Draw:Set State:Light");
00119 PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector("Draw:Set State:Stencil");
00120 PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector("Draw:Set State:Fog");
00121 PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector("Draw:Set State:Scissor");
00122 
00123 
00124 PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL;
00125 
00126 TypeHandle GraphicsStateGuardian::_type_handle;
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: GraphicsStateGuardian::Constructor
00130 //       Access: Public
00131 //  Description:
00132 ////////////////////////////////////////////////////////////////////
00133 
00134 GraphicsStateGuardian::
00135 GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
00136                       GraphicsEngine *engine, GraphicsPipe *pipe) :
00137   _internal_coordinate_system(internal_coordinate_system),
00138   _pipe(pipe),
00139   _engine(engine)
00140 {
00141   _coordinate_system = CS_invalid;
00142   _internal_transform = TransformState::make_identity();
00143 
00144   set_coordinate_system(get_default_coordinate_system());
00145 
00146   _data_reader = (GeomVertexDataPipelineReader *)NULL;
00147   _current_display_region = (DisplayRegion*)NULL;
00148   _current_stereo_channel = Lens::SC_mono;
00149   _current_tex_view_offset = 0;
00150   _current_lens = (Lens *)NULL;
00151   _projection_mat = TransformState::make_identity();
00152   _projection_mat_inv = TransformState::make_identity();
00153 
00154   _needs_reset = true;
00155   _is_valid = false;
00156   _current_properties = NULL;
00157   _closing_gsg = false;
00158   _active = true;
00159   _prepared_objects = new PreparedGraphicsObjects;
00160   _stereo_buffer_mask = ~0;
00161   _incomplete_render = allow_incomplete_render;
00162   _effective_incomplete_render = false;
00163   _loader = Loader::get_global_ptr();
00164 
00165   _is_hardware = false;
00166   _prefers_triangle_strips = false;
00167   _max_vertices_per_array = INT_MAX;
00168   _max_vertices_per_primitive = INT_MAX;
00169 
00170   // Initially, we set this to 1 (the default--no multitexturing
00171   // supported).  A derived GSG may set this differently if it
00172   // supports multitexturing.
00173   _max_texture_stages = 1;
00174 
00175   // Also initially, we assume there are no limits on texture sizes,
00176   // and that 3-d and cube-map textures are not supported.
00177   _max_texture_dimension = -1;
00178   _max_3d_texture_dimension = 0;
00179   _max_2d_texture_array_layers = 0;
00180   _max_cube_map_dimension = 0;
00181 
00182   // Assume we don't support these fairly advanced texture combiner
00183   // modes.
00184   _supports_texture_combine = false;
00185   _supports_texture_saved_result = false;
00186   _supports_texture_dot3 = false;
00187 
00188   _supports_3d_texture = false;
00189   _supports_2d_texture_array = false;
00190   _supports_cube_map = false;
00191   _supports_tex_non_pow2 = false;
00192   _supports_compressed_texture = false;
00193   _compressed_texture_formats.clear();
00194   _compressed_texture_formats.set_bit(Texture::CM_off);
00195 
00196   // Assume no limits on number of lights or clip planes.
00197   _max_lights = -1;
00198   _max_clip_planes = -1;
00199 
00200   // Assume no vertex blending capability.
00201   _max_vertex_transforms = 0;
00202   _max_vertex_transform_indices = 0;
00203 
00204   _supports_occlusion_query = false;
00205 
00206   // Initially, we set this to false; a GSG that knows it has this
00207   // property should set it to true.
00208   _copy_texture_inverted = false;
00209 
00210   // Similarly with these capabilities flags.
00211   _supports_multisample = false;
00212   _supports_generate_mipmap = false;
00213   _supports_depth_texture = false;
00214   _supports_depth_stencil = false;
00215   _supports_shadow_filter = false;
00216   _supports_basic_shaders = false;
00217   _supports_glsl = false;
00218 
00219   _supports_stencil = false;
00220   _supports_stencil_wrap = false;
00221   _supports_two_sided_stencil = false;
00222   _supports_geometry_instancing = false;
00223 
00224   _maximum_simultaneous_render_targets = 1;
00225 
00226   _supported_geom_rendering = 0;
00227 
00228   // If this is true, then we can apply a color and/or color scale by
00229   // twiddling the material and/or ambient light (which could mean
00230   // enabling lighting even without a LightAttrib).
00231   _color_scale_via_lighting = color_scale_via_lighting;
00232 
00233   // Similarly for applying a texture to achieve uniform alpha
00234   // scaling.
00235   _alpha_scale_via_texture = alpha_scale_via_texture;
00236 
00237   // Few GSG's can do this, since it requires touching each vertex as
00238   // it is rendered.
00239   _runtime_color_scale = false;
00240 
00241   _stencil_render_states = 0;
00242 
00243   // The default is no shader support.
00244   _auto_detect_shader_model = SM_00;
00245   _shader_model = SM_00;
00246   
00247   _gamma = 1.0f;
00248   _texture_quality_override = Texture::QL_default;
00249   
00250   _shader_generator = NULL;
00251 }
00252 
00253 ////////////////////////////////////////////////////////////////////
00254 //     Function: GraphicsStateGuardian::Destructor
00255 //       Access: Public, Virtual
00256 //  Description:
00257 ////////////////////////////////////////////////////////////////////
00258 GraphicsStateGuardian::
00259 ~GraphicsStateGuardian() {
00260   remove_gsg(this);
00261 
00262   if (_stencil_render_states) {
00263     delete _stencil_render_states;
00264     _stencil_render_states = 0;
00265   }
00266   
00267   if (_shader_generator) {
00268     delete _shader_generator;
00269     _shader_generator = 0;
00270   }
00271 
00272   GeomMunger::unregister_mungers_for_gsg(this);
00273 }
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: GraphicsStateGuardian::get_engine
00277 //       Access: Published
00278 //  Description: Returns the graphics engine that created this GSG.
00279 //               Since there is normally only one GraphicsEngine
00280 //               object in an application, this is usually the same as
00281 //               the global GraphicsEngine.
00282 ////////////////////////////////////////////////////////////////////
00283 GraphicsEngine *GraphicsStateGuardian::
00284 get_engine() const {
00285   nassertr(_engine != (GraphicsEngine *)NULL, GraphicsEngine::get_global_ptr());
00286   return _engine;
00287 }
00288 
00289 ////////////////////////////////////////////////////////////////////
00290 //     Function: GraphicsStateGuardian::get_supports_multisample
00291 //       Access: Published, Virtual
00292 //  Description: Returns true if this particular GSG supports using
00293 //               the multisample bits to provide antialiasing, and
00294 //               also supports M_multisample and M_multisample_mask
00295 //               transparency modes.  If this is not true for a
00296 //               particular GSG, Panda will map the M_multisample
00297 //               modes to M_binary.
00298 //
00299 //               This method is declared virtual solely so that it can
00300 //               be queried from cullResult.cxx.
00301 ////////////////////////////////////////////////////////////////////
00302 bool GraphicsStateGuardian::
00303 get_supports_multisample() const {
00304   return _supports_multisample;
00305 }
00306 
00307 ////////////////////////////////////////////////////////////////////
00308 //     Function: GraphicsStateGuardian::get_supported_geom_rendering
00309 //       Access: Published, Virtual
00310 //  Description: Returns the union of Geom::GeomRendering values that
00311 //               this particular GSG can support directly.  If a Geom
00312 //               needs to be rendered that requires some additional
00313 //               properties, the StandardMunger and/or the
00314 //               CullableObject will convert it as needed.
00315 //
00316 //               This method is declared virtual solely so that it can
00317 //               be queried from cullableObject.cxx.
00318 ////////////////////////////////////////////////////////////////////
00319 int GraphicsStateGuardian::
00320 get_supported_geom_rendering() const {
00321   return _supported_geom_rendering;
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: GraphicsStateGuardian::get_supports_cg_profile
00326 //       Access: Published, Virtual
00327 //  Description: Returns true if this particular GSG supports the 
00328 //               specified Cg Shader Profile.
00329 ////////////////////////////////////////////////////////////////////
00330 bool GraphicsStateGuardian::
00331 get_supports_cg_profile(const string &name) const {
00332   return false;
00333 }
00334 
00335 ////////////////////////////////////////////////////////////////////
00336 //     Function: GraphicsStateGuardian::set_coordinate_system
00337 //       Access: Published
00338 //  Description: Changes the coordinate system in effect on this
00339 //               particular gsg.  This is also called the "external"
00340 //               coordinate system, since it is the coordinate system
00341 //               used by the scene graph, external to to GSG.
00342 //
00343 //               Normally, this will be the default coordinate system,
00344 //               but it might be set differently at runtime.
00345 ////////////////////////////////////////////////////////////////////
00346 void GraphicsStateGuardian::
00347 set_coordinate_system(CoordinateSystem cs) {
00348   _coordinate_system = cs;
00349 
00350   // Changing the external coordinate system changes the cs_transform.
00351   if (_internal_coordinate_system == CS_default ||
00352       _internal_coordinate_system == _coordinate_system) {
00353     _cs_transform = TransformState::make_identity();
00354     _inv_cs_transform = TransformState::make_identity();
00355 
00356   } else {
00357     _cs_transform =
00358       TransformState::make_mat
00359       (LMatrix4::convert_mat(_coordinate_system,
00360                               _internal_coordinate_system));
00361     _inv_cs_transform =
00362       TransformState::make_mat
00363       (LMatrix4::convert_mat(_internal_coordinate_system,
00364                               _coordinate_system));
00365   }
00366 }
00367 
00368 ////////////////////////////////////////////////////////////////////
00369 //     Function: GraphicsStateGuardian::get_internal_coordinate_system
00370 //       Access: Published, Virtual
00371 //  Description: Returns the coordinate system used internally by the
00372 //               GSG.  This may be the same as the external coordinate
00373 //               system reported by get_coordinate_system(), or it may
00374 //               be something different.
00375 //
00376 //               In any case, vertices that have been transformed
00377 //               before being handed to the GSG (that is, vertices
00378 //               with a contents value of C_clip_point) will be
00379 //               expected to be in this coordinate system.
00380 ////////////////////////////////////////////////////////////////////
00381 CoordinateSystem GraphicsStateGuardian::
00382 get_internal_coordinate_system() const {
00383   return _internal_coordinate_system;
00384 }
00385 
00386 ////////////////////////////////////////////////////////////////////
00387 //     Function: GraphicsStateGuardian::get_prepared_objects
00388 //       Access: Public, Virtual
00389 //  Description: Returns the set of texture and geom objects that have
00390 //               been prepared with this GSG (and possibly other GSG's
00391 //               that share objects).
00392 ////////////////////////////////////////////////////////////////////
00393 PreparedGraphicsObjects *GraphicsStateGuardian::
00394 get_prepared_objects() {
00395   return _prepared_objects;
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: GraphicsStateGuardian::set_gamma
00400 //       Access: Published, Virtual
00401 //  Description: Set gamma.  Returns true on success.
00402 ////////////////////////////////////////////////////////////////////
00403 bool GraphicsStateGuardian::
00404 set_gamma(PN_stdfloat gamma) {
00405   _gamma = gamma;  
00406 
00407   return false;
00408 }
00409 
00410 ////////////////////////////////////////////////////////////////////
00411 //     Function: GraphicsStateGuardian::get_gamma
00412 //       Access: Published
00413 //  Description: Get the current gamma setting.
00414 ////////////////////////////////////////////////////////////////////
00415 PN_stdfloat GraphicsStateGuardian::
00416 get_gamma(PN_stdfloat gamma) {
00417   return _gamma;
00418 }
00419 
00420 ////////////////////////////////////////////////////////////////////
00421 //     Function: GraphicsStateGuardian::restore_gamma
00422 //       Access: Published, Virtual
00423 //  Description: Restore original gamma setting.
00424 ////////////////////////////////////////////////////////////////////
00425 void GraphicsStateGuardian::
00426 restore_gamma() {
00427 }
00428 
00429 #ifdef HAVE_PYTHON
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: GraphicsStateGuardian::get_prepared_textures
00432 //       Access: Published
00433 //  Description: Returns a Python list of all of the
00434 //               currently-prepared textures within the GSG.
00435 ////////////////////////////////////////////////////////////////////
00436 PyObject *GraphicsStateGuardian::
00437 get_prepared_textures() const {
00438   ReMutexHolder holder(_prepared_objects->_lock);
00439   size_t num_textures = _prepared_objects->_prepared_textures.size();
00440   PyObject *list = PyList_New(num_textures);
00441 
00442   size_t i = 0;
00443   PreparedGraphicsObjects::Textures::const_iterator ti;
00444   for (ti = _prepared_objects->_prepared_textures.begin();
00445        ti != _prepared_objects->_prepared_textures.end();
00446        ++ti) {
00447     PT(Texture) tex = (*ti)->get_texture();
00448 
00449     PyObject *element = 
00450       DTool_CreatePyInstanceTyped(tex, Dtool_Texture,
00451                                   true, false, tex->get_type_index());
00452     tex->ref();
00453 
00454     nassertr(i < num_textures, NULL);
00455     PyList_SetItem(list, i, element);
00456     ++i;
00457   }
00458   nassertr(i == num_textures, NULL);
00459 
00460   return list;
00461 }
00462 #endif  // HAVE_PYTHON
00463 
00464 ////////////////////////////////////////////////////////////////////
00465 //     Function: GraphicsStateGuardian::traverse_prepared_textures
00466 //       Access: Public
00467 //  Description: Calls the indicated function on all
00468 //               currently-prepared textures, or until the callback
00469 //               function returns false.
00470 ////////////////////////////////////////////////////////////////////
00471 void GraphicsStateGuardian::
00472 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, 
00473                            void *callback_arg) {
00474   ReMutexHolder holder(_prepared_objects->_lock);
00475   PreparedGraphicsObjects::Textures::const_iterator ti;
00476   for (ti = _prepared_objects->_prepared_textures.begin();
00477        ti != _prepared_objects->_prepared_textures.end();
00478        ++ti) {
00479     bool result = (*func)(*ti,callback_arg);
00480     if (!result) {
00481       return;
00482     }
00483   }
00484 }
00485 
00486 #ifndef NDEBUG
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: GraphicsStateGuardian::set_flash_texture
00489 //       Access: Published
00490 //  Description: Sets the "flash texture".  This is a debug feature;
00491 //               when enabled, the specified texture will begin
00492 //               flashing in the scene, helping you to find it
00493 //               visually.
00494 //
00495 //               The texture also flashes with a color code: blue for
00496 //               mipmap level 0, yellow for mipmap level 1, and red
00497 //               for mipmap level 2 or higher (even for textures that
00498 //               don't have mipmaps).  This gives you an idea of the
00499 //               choice of the texture size.  If it is blue, the
00500 //               texture is being drawn the proper size or magnified;
00501 //               if it is yellow, it is being minified a little bit;
00502 //               and if it red, it is being minified considerably.  If
00503 //               you see a red texture when you are right in front of
00504 //               it, you should consider reducing the size of the
00505 //               texture to avoid wasting texture memory.
00506 //
00507 //               Not all rendering backends support the flash_texture
00508 //               feature.  Presently, it is only supported by OpenGL.
00509 ////////////////////////////////////////////////////////////////////
00510 void GraphicsStateGuardian::
00511 set_flash_texture(Texture *tex) {
00512   _flash_texture = tex;
00513 }
00514 #endif  // NDEBUG
00515 
00516 #ifndef NDEBUG
00517 ////////////////////////////////////////////////////////////////////
00518 //     Function: GraphicsStateGuardian::clear_flash_texture
00519 //       Access: Published
00520 //  Description: Resets the "flash texture", so that no textures will
00521 //               flash.  See set_flash_texture().
00522 ////////////////////////////////////////////////////////////////////
00523 void GraphicsStateGuardian::
00524 clear_flash_texture() {
00525   _flash_texture = NULL;
00526 }
00527 #endif  // NDEBUG
00528 
00529 #ifndef NDEBUG
00530 ////////////////////////////////////////////////////////////////////
00531 //     Function: GraphicsStateGuardian::get_flash_texture
00532 //       Access: Published
00533 //  Description: Returns the current "flash texture", if any, or NULL
00534 //               if none.  See set_flash_texture().
00535 ////////////////////////////////////////////////////////////////////
00536 Texture *GraphicsStateGuardian::
00537 get_flash_texture() const {
00538   return _flash_texture;
00539 }
00540 #endif  // NDEBUG
00541 
00542 ////////////////////////////////////////////////////////////////////
00543 //     Function: GraphicsStateGuardian::set_scene
00544 //       Access: Published
00545 //  Description: Sets the SceneSetup object that indicates the initial
00546 //               camera position, etc.  This must be called before
00547 //               traversal begins.  Returns true if the scene is
00548 //               acceptable, false if something's wrong.  This should
00549 //               be called in the draw thread only.
00550 ////////////////////////////////////////////////////////////////////
00551 bool GraphicsStateGuardian::
00552 set_scene(SceneSetup *scene_setup) {
00553   _scene_setup = scene_setup;
00554   _current_lens = scene_setup->get_lens();
00555   if (_current_lens == (Lens *)NULL) {
00556     return false;
00557   }
00558 
00559   _projection_mat = calc_projection_mat(_current_lens);
00560   if (_projection_mat == 0) {
00561     return false;
00562   }
00563   _projection_mat_inv = _projection_mat->get_inverse();
00564   return prepare_lens();
00565 }
00566 
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: GraphicsStateGuardian::get_scene
00569 //       Access: Published, Virtual
00570 //  Description: Returns the current SceneSetup object.
00571 ////////////////////////////////////////////////////////////////////
00572 SceneSetup *GraphicsStateGuardian::
00573 get_scene() const {
00574   return _scene_setup;
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: GraphicsStateGuardian::prepare_texture
00579 //       Access: Public, Virtual
00580 //  Description: Creates whatever structures the GSG requires to
00581 //               represent the texture internally, and returns a
00582 //               newly-allocated TextureContext object with this data.
00583 //               It is the responsibility of the calling function to
00584 //               later call release_texture() with this same pointer
00585 //               (which will also delete the pointer).
00586 //
00587 //               This function should not be called directly to
00588 //               prepare a texture.  Instead, call Texture::prepare().
00589 ////////////////////////////////////////////////////////////////////
00590 TextureContext *GraphicsStateGuardian::
00591 prepare_texture(Texture *) {
00592   return (TextureContext *)NULL;
00593 }
00594 
00595 ////////////////////////////////////////////////////////////////////
00596 //     Function: GraphicsStateGuardian::update_texture
00597 //       Access: Public, Virtual
00598 //  Description: Ensures that the current Texture data is refreshed
00599 //               onto the GSG.  This means updating the texture
00600 //               properties and/or re-uploading the texture image, if
00601 //               necessary.  This should only be called within the
00602 //               draw thread.
00603 //
00604 //               If force is true, this function will not return until
00605 //               the texture has been fully uploaded.  If force is
00606 //               false, the function may choose to upload a simple
00607 //               version of the texture instead, if the texture is not
00608 //               fully resident (and if get_incomplete_render() is
00609 //               true).
00610 ////////////////////////////////////////////////////////////////////
00611 bool GraphicsStateGuardian::
00612 update_texture(TextureContext *, bool) {
00613   return true;
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: GraphicsStateGuardian::release_texture
00618 //       Access: Public, Virtual
00619 //  Description: Frees the resources previously allocated via a call
00620 //               to prepare_texture(), including deleting the
00621 //               TextureContext itself, if it is non-NULL.
00622 ////////////////////////////////////////////////////////////////////
00623 void GraphicsStateGuardian::
00624 release_texture(TextureContext *) {
00625 }
00626 
00627 ////////////////////////////////////////////////////////////////////
00628 //     Function: GraphicsStateGuardian::extract_texture_data
00629 //       Access: Public, Virtual
00630 //  Description: This method should only be called by the
00631 //               GraphicsEngine.  Do not call it directly; call
00632 //               GraphicsEngine::extract_texture_data() instead.
00633 //
00634 //               This method will be called in the draw thread to
00635 //               download the texture memory's image into its
00636 //               ram_image value.  It returns true on success, false
00637 //               otherwise.
00638 ////////////////////////////////////////////////////////////////////
00639 bool GraphicsStateGuardian::
00640 extract_texture_data(Texture *) {
00641   return false;
00642 }
00643 
00644 ////////////////////////////////////////////////////////////////////
00645 //     Function: GraphicsStateGuardian::prepare_geom
00646 //       Access: Public, Virtual
00647 //  Description: Prepares the indicated Geom for retained-mode
00648 //               rendering, by creating whatever structures are
00649 //               necessary in the GSG (for instance, vertex buffers).
00650 //               Returns the newly-allocated GeomContext that can be
00651 //               used to render the geom.
00652 ////////////////////////////////////////////////////////////////////
00653 GeomContext *GraphicsStateGuardian::
00654 prepare_geom(Geom *) {
00655   return (GeomContext *)NULL;
00656 }
00657 
00658 ////////////////////////////////////////////////////////////////////
00659 //     Function: GraphicsStateGuardian::release_geom
00660 //       Access: Public, Virtual
00661 //  Description: Frees the resources previously allocated via a call
00662 //               to prepare_geom(), including deleting the GeomContext
00663 //               itself, if it is non-NULL.
00664 //
00665 //               This function should not be called directly to
00666 //               prepare a Geom.  Instead, call Geom::prepare().
00667 ////////////////////////////////////////////////////////////////////
00668 void GraphicsStateGuardian::
00669 release_geom(GeomContext *) {
00670 }
00671 
00672 ////////////////////////////////////////////////////////////////////
00673 //     Function: GraphicsStateGuardian::prepare_shader
00674 //       Access: Public, Virtual
00675 //  Description: Compile a vertex/fragment shader body.
00676 ////////////////////////////////////////////////////////////////////
00677 ShaderContext *GraphicsStateGuardian::
00678 prepare_shader(Shader *shader) {
00679   return (ShaderContext *)NULL;
00680 }
00681 
00682 ////////////////////////////////////////////////////////////////////
00683 //     Function: GraphicsStateGuardian::release_shader
00684 //       Access: Public, Virtual
00685 //  Description: Releases the resources allocated by prepare_shader
00686 ////////////////////////////////////////////////////////////////////
00687 void GraphicsStateGuardian::
00688 release_shader(ShaderContext *sc) {
00689 }
00690 
00691 ////////////////////////////////////////////////////////////////////
00692 //     Function: GraphicsStateGuardian::prepare_vertex_buffer
00693 //       Access: Public, Virtual
00694 //  Description: Prepares the indicated buffer for retained-mode
00695 //               rendering.
00696 ////////////////////////////////////////////////////////////////////
00697 VertexBufferContext *GraphicsStateGuardian::
00698 prepare_vertex_buffer(GeomVertexArrayData *) {
00699   return (VertexBufferContext *)NULL;
00700 }
00701 
00702 ////////////////////////////////////////////////////////////////////
00703 //     Function: GraphicsStateGuardian::release_vertex_buffer
00704 //       Access: Public, Virtual
00705 //  Description: Frees the resources previously allocated via a call
00706 //               to prepare_data(), including deleting the
00707 //               VertexBufferContext itself, if necessary.
00708 ////////////////////////////////////////////////////////////////////
00709 void GraphicsStateGuardian::
00710 release_vertex_buffer(VertexBufferContext *) {
00711 }
00712 
00713 ////////////////////////////////////////////////////////////////////
00714 //     Function: GraphicsStateGuardian::prepare_index_buffer
00715 //       Access: Public, Virtual
00716 //  Description: Prepares the indicated buffer for retained-mode
00717 //               rendering.
00718 ////////////////////////////////////////////////////////////////////
00719 IndexBufferContext *GraphicsStateGuardian::
00720 prepare_index_buffer(GeomPrimitive *) {
00721   return (IndexBufferContext *)NULL;
00722 }
00723 
00724 ////////////////////////////////////////////////////////////////////
00725 //     Function: GraphicsStateGuardian::release_index_buffer
00726 //       Access: Public, Virtual
00727 //  Description: Frees the resources previously allocated via a call
00728 //               to prepare_data(), including deleting the
00729 //               IndexBufferContext itself, if necessary.
00730 ////////////////////////////////////////////////////////////////////
00731 void GraphicsStateGuardian::
00732 release_index_buffer(IndexBufferContext *) {
00733 }
00734 
00735 ////////////////////////////////////////////////////////////////////
00736 //     Function: GraphicsStateGuardian::get_supports_occlusion_query
00737 //       Access: Public, Virtual
00738 //  Description: Returns true if this GSG supports an occlusion query.
00739 //               If this is true, then begin_occlusion_query() and
00740 //               end_occlusion_query() may be called to bracket a
00741 //               sequence of draw_triangles() (or whatever) calls to
00742 //               measure pixels that pass the depth test.
00743 ////////////////////////////////////////////////////////////////////
00744 bool GraphicsStateGuardian::
00745 get_supports_occlusion_query() const {
00746   return _supports_occlusion_query;
00747 }
00748 
00749 ////////////////////////////////////////////////////////////////////
00750 //     Function: GraphicsStateGuardian::begin_occlusion_query
00751 //       Access: Public, Virtual
00752 //  Description: Begins a new occlusion query.  After this call, you
00753 //               may call begin_draw_primitives() and
00754 //               draw_triangles()/draw_whatever() repeatedly.
00755 //               Eventually, you should call end_occlusion_query()
00756 //               before the end of the frame; that will return a new
00757 //               OcclusionQueryContext object that will tell you how
00758 //               many pixels represented by the bracketed geometry
00759 //               passed the depth test.
00760 //
00761 //               It is not valid to call begin_occlusion_query()
00762 //               between another begin_occlusion_query()
00763 //               .. end_occlusion_query() sequence.
00764 ////////////////////////////////////////////////////////////////////
00765 void GraphicsStateGuardian::
00766 begin_occlusion_query() {
00767   nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
00768 }
00769 
00770 ////////////////////////////////////////////////////////////////////
00771 //     Function: GraphicsStateGuardian::end_occlusion_query
00772 //       Access: Public, Virtual
00773 //  Description: Ends a previous call to begin_occlusion_query().
00774 //               This call returns the OcclusionQueryContext object
00775 //               that will (eventually) report the number of pixels
00776 //               that passed the depth test between the call to
00777 //               begin_occlusion_query() and end_occlusion_query().
00778 ////////////////////////////////////////////////////////////////////
00779 PT(OcclusionQueryContext) GraphicsStateGuardian::
00780 end_occlusion_query() {
00781   nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
00782   PT(OcclusionQueryContext) result = _current_occlusion_query;
00783   _current_occlusion_query = NULL;
00784   return result;
00785 }
00786 
00787 ////////////////////////////////////////////////////////////////////
00788 //     Function: GraphicsStateGuardian::get_geom_munger
00789 //       Access: Public, Virtual
00790 //  Description: Looks up or creates a GeomMunger object to munge
00791 //               vertices appropriate to this GSG for the indicated
00792 //               state.
00793 ////////////////////////////////////////////////////////////////////
00794 PT(GeomMunger) GraphicsStateGuardian::
00795 get_geom_munger(const RenderState *state, Thread *current_thread) {
00796   // We can cast the RenderState to a non-const object because we are
00797   // only updating a cache within the RenderState, not really changing
00798   // any of its properties.
00799   RenderState *nc_state = ((RenderState *)state);
00800 
00801   // Before we even look up the map, see if the _last_mi value points
00802   // to this GSG.  This is likely because we tend to visit the same
00803   // state multiple times during a frame.  Also, this might well be
00804   // the only GSG in the world anyway.
00805   if (!nc_state->_mungers.empty()) {
00806     RenderState::Mungers::const_iterator mi = nc_state->_last_mi;
00807     if (!(*mi).first.was_deleted() && (*mi).first == this) {
00808       if ((*mi).second->is_registered()) {
00809         return (*mi).second;
00810       }
00811     }
00812   }
00813 
00814   // Nope, we have to look it up in the map.
00815   RenderState::Mungers::iterator mi = nc_state->_mungers.find(this);
00816   if (mi != nc_state->_mungers.end() && !(*mi).first.was_deleted()) {
00817     if ((*mi).second->is_registered()) {
00818       nc_state->_last_mi = mi;
00819       return (*mi).second;
00820     }
00821     // This GeomMunger is no longer registered.  Remove it from the
00822     // map.
00823     nc_state->_mungers.erase(mi);
00824   }
00825 
00826   // Nothing in the map; create a new entry.
00827   PT(GeomMunger) munger = make_geom_munger(nc_state, current_thread);
00828   nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger);
00829 
00830   mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
00831   nc_state->_last_mi = mi;
00832 
00833   return munger;
00834 }
00835 
00836 ////////////////////////////////////////////////////////////////////
00837 //     Function: GraphicsStateGuardian::make_geom_munger
00838 //       Access: Public, Virtual
00839 //  Description: Creates a new GeomMunger object to munge vertices
00840 //               appropriate to this GSG for the indicated state.
00841 ////////////////////////////////////////////////////////////////////
00842 PT(GeomMunger) GraphicsStateGuardian::
00843 make_geom_munger(const RenderState *state, Thread *current_thread) {
00844   // The default implementation returns no munger at all, but
00845   // presumably, every kind of GSG needs some special munging action,
00846   // so real GSG's will override this to return something more
00847   // useful.
00848   return NULL;
00849 }
00850 
00851 ////////////////////////////////////////////////////////////////////
00852 //     Function: GraphicsStateGuardian::compute_distance_to
00853 //       Access: Public, Virtual
00854 //  Description: This function may only be called during a render
00855 //               traversal; it will compute the distance to the
00856 //               indicated point, assumed to be in eye coordinates,
00857 //               from the camera plane.
00858 ////////////////////////////////////////////////////////////////////
00859 PN_stdfloat GraphicsStateGuardian::
00860 compute_distance_to(const LPoint3 &point) const {
00861   switch (_coordinate_system) {
00862   case CS_zup_right:
00863     return point[1];
00864 
00865   case CS_yup_right:
00866     return -point[2];
00867 
00868   case CS_zup_left:
00869     return -point[1];
00870 
00871   case CS_yup_left:
00872     return point[2];
00873 
00874   default:
00875     gsg_cat.error()
00876       << "Invalid coordinate system in compute_distance_to: "
00877       << (int)_coordinate_system << "\n";
00878     return 0.0f;
00879   }
00880 }
00881 
00882 ////////////////////////////////////////////////////////////////////
00883 //     Function: GraphicsStateGuardian::fetch_specified_value
00884 //       Access: Public
00885 //  Description: The gsg contains a large number of useful matrices:
00886 //
00887 //                  * the world transform,
00888 //                  * the modelview matrix,
00889 //                  * the cs_transform,
00890 //                  * etc, etc.
00891 //
00892 //               A shader can request any of these values, and
00893 //               furthermore, it can request that various compositions,
00894 //               inverses, and transposes be performed.  The
00895 //               ShaderMatSpec is a data structure indicating what
00896 //               datum is desired and what conversions to perform.
00897 //               This routine, fetch_specified_value, is responsible for
00898 //               doing the actual retrieval and conversions.
00899 //
00900 //               Some values, like the following, aren't matrices:
00901 //
00902 //                  * window size
00903 //                  * texture coordinates of card center
00904 //
00905 //               This routine can fetch these values as well, by
00906 //               shoehorning them into a matrix.  In this way, we avoid
00907 //               the need for a separate routine to fetch these values.
00908 //
00909 //               The "altered" bits indicate what parts of the
00910 //               state_and_transform have changed since the last 
00911 //               time this particular ShaderMatSpec was evaluated.
00912 //               This may allow data to be cached and not reevaluated.
00913 //
00914 ////////////////////////////////////////////////////////////////////
00915 const LMatrix4 *GraphicsStateGuardian::
00916 fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
00917   LVecBase3 v;
00918   
00919   if (altered & spec._dep[0]) {
00920     const LMatrix4 *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0]);
00921     if (t != &spec._cache[0]) {
00922       spec._cache[0] = *t;
00923     }
00924   }
00925   if (altered & spec._dep[1]) {
00926     const LMatrix4 *t = fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1]);
00927     if (t != &spec._cache[1]) {
00928       spec._cache[1] = *t;
00929     }
00930   }
00931   
00932   switch(spec._func) {
00933   case Shader::SMF_compose:
00934     spec._value.multiply(spec._cache[0], spec._cache[1]);
00935     return &spec._value;
00936   case Shader::SMF_transform_dlight:
00937     spec._value = spec._cache[0];
00938     v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2));
00939     v.normalize();
00940     spec._value.set_row(2, v);
00941     v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
00942     v.normalize();
00943     spec._value.set_row(3, v);
00944     return &spec._value;
00945   case Shader::SMF_transform_plight:
00946     spec._value = spec._cache[0];
00947     spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
00948     return &spec._value;
00949   case Shader::SMF_transform_slight:
00950     spec._value = spec._cache[0];
00951     spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
00952     v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
00953     v.normalize();
00954     spec._value.set_row(3, v);
00955     return &spec._value;
00956   case Shader::SMF_first:
00957     return &spec._cache[0];
00958   default:
00959     // should never get here
00960     spec._value = LMatrix4::ident_mat();
00961     return &spec._value;
00962   }
00963 }
00964 
00965 ////////////////////////////////////////////////////////////////////
00966 //     Function: GraphicsStateGuardian::fetch_specified_part
00967 //       Access: Public
00968 //  Description: See fetch_specified_value
00969 ////////////////////////////////////////////////////////////////////
00970 const LMatrix4 *GraphicsStateGuardian::
00971 fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &t) {
00972   switch(part) {
00973   case Shader::SMO_identity: {
00974     return &LMatrix4::ident_mat();
00975   }
00976   case Shader::SMO_window_size: {
00977     t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
00978                                  _current_display_region->get_pixel_height(),
00979                                  0.0);
00980     return &t;
00981   }
00982   case Shader::SMO_pixel_size: {
00983     t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
00984                                  _current_display_region->get_pixel_height(),
00985                                  0.0);
00986     return &t;
00987   }
00988   case Shader::SMO_texpad_x: {
00989     Texture *tex = _target_shader->get_shader_input_texture(name);
00990     nassertr(tex != 0, &LMatrix4::zeros_mat());
00991     int sx = tex->get_x_size() - tex->get_pad_x_size();
00992     int sy = tex->get_y_size() - tex->get_pad_y_size();
00993     int sz = tex->get_z_size() - tex->get_pad_z_size();
00994     double cx = (sx * 0.5) / tex->get_x_size();
00995     double cy = (sy * 0.5) / tex->get_y_size();
00996     double cz = (sz * 0.5) / tex->get_z_size();
00997     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
00998     return &t;
00999   }
01000   case Shader::SMO_texpix_x: {
01001     Texture *tex = _target_shader->get_shader_input_texture(name);
01002     nassertr(tex != 0, &LMatrix4::zeros_mat());
01003     double px = 1.0 / tex->get_x_size();
01004     double py = 1.0 / tex->get_y_size();
01005     double pz = 1.0 / tex->get_z_size();
01006     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
01007     return &t;
01008   }
01009   case Shader::SMO_attr_material: {
01010     const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
01011     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
01012     if (target_material->is_off()) {
01013       t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
01014       return &t;
01015     }
01016     Material *m = target_material->get_material();
01017     LVecBase4 const &amb = m->get_ambient();
01018     LVecBase4 const &dif = m->get_diffuse();
01019     LVecBase4 const &emm = m->get_emission();
01020     LVecBase4 spc = m->get_specular();
01021     spc[3] = m->get_shininess();
01022     t = LMatrix4(amb[0],amb[1],amb[2],amb[3],
01023                   dif[0],dif[1],dif[2],dif[3],
01024                   emm[0],emm[1],emm[2],emm[3],
01025                   spc[0],spc[1],spc[2],spc[3]);
01026     return &t;
01027   }
01028   case Shader::SMO_attr_color: {
01029     const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot()));
01030     if (target_color->get_color_type() != ColorAttrib::T_flat) {
01031       return &LMatrix4::ones_mat();
01032     }
01033     LVecBase4 c = target_color->get_color();
01034     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
01035     return &t;
01036   }
01037   case Shader::SMO_attr_colorscale: {
01038     const ColorScaleAttrib *target_color = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot()));
01039     if (target_color->is_identity()) {
01040       return &LMatrix4::ones_mat();
01041     }
01042     LVecBase4 cs = target_color->get_scale();
01043     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]);
01044     return &t;
01045   }
01046   case Shader::SMO_attr_fog: {
01047     const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
01048     Fog *fog = target_fog->get_fog();
01049     if (fog == (Fog*) NULL) {
01050       return &LMatrix4::ones_mat();
01051     }
01052     PN_stdfloat start, end;
01053     fog->get_linear_range(start, end);
01054     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,fog->get_exp_density(),start,end,1.0f/(end-start));
01055     return &t;
01056   }
01057   case Shader::SMO_attr_fogcolor: {
01058     const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
01059     Fog *fog = target_fog->get_fog();
01060     if (fog == (Fog*) NULL) {
01061       return &LMatrix4::ones_mat();
01062     }
01063     LVecBase4 c = fog->get_color();
01064     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
01065     return &t;
01066   }
01067   case Shader::SMO_alight_x: {
01068     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01069     nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
01070     AmbientLight *lt;
01071     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
01072     LColor const &c = lt->get_color();
01073     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
01074     return &t;
01075   }
01076   case Shader::SMO_satten_x: {
01077     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01078     nassertr(!np.is_empty(), &LMatrix4::ones_mat());
01079     Spotlight *lt;
01080     DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
01081     LVecBase3 const &a = lt->get_attenuation();
01082     PN_stdfloat x = lt->get_exponent();
01083     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x);
01084     return &t;
01085   }
01086   case Shader::SMO_dlight_x: {
01087     // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE
01088     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01089     nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
01090     DirectionalLight *lt;
01091     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
01092     LColor const &c = lt->get_color();
01093     LColor const &s = lt->get_specular_color();
01094     t = np.get_net_transform()->get_mat() *
01095       get_scene()->get_world_transform()->get_mat();
01096     LVecBase3 d = -(t.xform_vec(lt->get_direction()));
01097     d.normalize();
01098     LVecBase3 h = d + LVecBase3(0,-1,0);
01099     h.normalize();
01100     t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],c[3],d[0],d[1],d[2],0,h[0],h[1],h[2],0);
01101     return &t;
01102   }
01103   case Shader::SMO_plight_x: {
01104     // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION
01105     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01106     nassertr(!np.is_empty(), &LMatrix4::ones_mat());
01107     PointLight *lt;
01108     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
01109     LColor const &c = lt->get_color();
01110     LColor const &s = lt->get_specular_color();
01111     t = np.get_net_transform()->get_mat() *
01112       get_scene()->get_world_transform()->get_mat();
01113     LVecBase3 p = (t.xform_point(lt->get_point()));
01114     LVecBase3 a = lt->get_attenuation();
01115     t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,a[0],a[1],a[2],0);
01116     return &t;
01117   }
01118   case Shader::SMO_slight_x: {
01119     // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION
01120     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01121     nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
01122     Spotlight *lt;
01123     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
01124     Lens *lens = lt->get_lens();
01125     nassertr(lens != (Lens *)NULL, &LMatrix4::zeros_mat());
01126     LColor const &c = lt->get_color();
01127     LColor const &s = lt->get_specular_color();
01128     PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
01129     t = np.get_net_transform()->get_mat() *
01130       get_scene()->get_world_transform()->get_mat();
01131     LVecBase3 p = t.xform_point(lens->get_nodal_point());
01132     LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
01133     t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
01134     return &t;
01135   }
01136   case Shader::SMO_texmat_x: {
01137     const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
01138     const TextureAttrib *ta = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
01139     int stagenr = atoi(name->get_name().c_str());
01140     if (stagenr >= ta->get_num_on_stages()) {
01141       return &LMatrix4::ident_mat();
01142     }
01143     return &tma->get_mat(ta->get_on_stage(stagenr));
01144   }
01145   case Shader::SMO_plane_x: {
01146     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01147     nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
01148     nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
01149     LPlane p = DCAST(PlaneNode, np.node())->get_plane();
01150     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
01151     return &t;
01152   }
01153   case Shader::SMO_clipplane_x: {
01154     const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
01155     int planenr = atoi(name->get_name().c_str());
01156     if (planenr >= cpa->get_num_on_planes()) {
01157       return &LMatrix4::zeros_mat();
01158     }
01159     const NodePath &np = cpa->get_on_plane(planenr);
01160     nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
01161     nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
01162     LPlane p (DCAST(PlaneNode, np.node())->get_plane());
01163     p.xform(np.get_net_transform()->get_mat()); // World-space
01164     t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
01165     return &t;
01166   }
01167   case Shader::SMO_mat_constant_x: {
01168     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01169     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01170     return &(np.node()->get_transform()->get_mat());
01171   }
01172   case Shader::SMO_vec_constant_x: {
01173     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
01174     const PN_stdfloat *data = input.get_data();
01175     t = LMatrix4(data[0],data[1],data[2],data[3],
01176                  data[0],data[1],data[2],data[3],
01177                  data[0],data[1],data[2],data[3],
01178                  data[0],data[1],data[2],data[3]);
01179     return &t;
01180   }
01181   case Shader::SMO_world_to_view: {
01182     return &(get_scene()->get_world_transform()->get_mat());
01183     break;
01184   }
01185   case Shader::SMO_view_to_world: {
01186     return &(get_scene()->get_camera_transform()->get_mat());
01187   }
01188   case Shader::SMO_model_to_view: {
01189     return &(get_external_transform()->get_mat());
01190   }
01191   case Shader::SMO_view_to_model: {
01192     // DANGER: SLOW AND NOT CACHEABLE!
01193     t.invert_from(get_external_transform()->get_mat());
01194     return &t;
01195   }
01196   case Shader::SMO_apiview_to_view: {
01197     return &(_inv_cs_transform->get_mat());
01198   }
01199   case Shader::SMO_view_to_apiview: {
01200     return &(_cs_transform->get_mat());
01201   }
01202   case Shader::SMO_clip_to_view: {
01203     if (_current_lens->get_coordinate_system() == _coordinate_system) {
01204       return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
01205     } else {
01206       t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
01207         LMatrix4::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
01208       return &t;
01209     }
01210   }
01211   case Shader::SMO_view_to_clip: {
01212     if (_current_lens->get_coordinate_system() == _coordinate_system) {
01213       return &(_current_lens->get_projection_mat(_current_stereo_channel));
01214     } else {
01215       t = LMatrix4::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
01216         _current_lens->get_projection_mat(_current_stereo_channel);
01217       return &t;
01218     }
01219   }
01220   case Shader::SMO_apiclip_to_view: {
01221     t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
01222     return &t;
01223   }
01224   case Shader::SMO_view_to_apiclip: {
01225     t = _cs_transform->get_mat() * _projection_mat->get_mat();
01226     return &t;
01227   }
01228   case Shader::SMO_view_x_to_view: {
01229     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01230     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01231     t = np.get_net_transform()->get_mat() *
01232       get_scene()->get_world_transform()->get_mat();
01233     return &t;
01234   }
01235   case Shader::SMO_view_to_view_x: {
01236     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01237     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01238     t = get_scene()->get_camera_transform()->get_mat() *
01239       invert(np.get_net_transform()->get_mat());
01240     return &t;
01241   }
01242   case Shader::SMO_apiview_x_to_view: {
01243     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01244     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01245     t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
01246       np.get_net_transform()->get_mat() *
01247       get_scene()->get_world_transform()->get_mat();
01248     return &t;
01249   }
01250   case Shader::SMO_view_to_apiview_x: {
01251     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01252     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01253     t = (get_scene()->get_camera_transform()->get_mat() *
01254          invert(np.get_net_transform()->get_mat()) *
01255          LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
01256     return &t;
01257   }
01258   case Shader::SMO_clip_x_to_view: {
01259     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01260     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01261     nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
01262     Lens *lens = DCAST(LensNode, np.node())->get_lens();
01263     t = lens->get_projection_mat_inv(_current_stereo_channel) *
01264       LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
01265       np.get_net_transform()->get_mat() *
01266       get_scene()->get_world_transform()->get_mat();
01267     return &t;
01268   }
01269   case Shader::SMO_view_to_clip_x: {
01270     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
01271     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
01272     nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
01273     Lens *lens = DCAST(LensNode, np.node())->get_lens();
01274     t = get_scene()->get_camera_transform()->get_mat() *
01275       invert(np.get_net_transform()->get_mat()) *
01276       LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
01277       lens->get_projection_mat(_current_stereo_channel);
01278     return &t;
01279   }
01280   case Shader::SMO_apiclip_x_to_view: {
01281     // NOT IMPLEMENTED
01282     return &LMatrix4::ident_mat();
01283   }
01284   case Shader::SMO_view_to_apiclip_x: {
01285     // NOT IMPLEMENTED
01286     return &LMatrix4::ident_mat();
01287   }
01288   default:
01289     // should never get here
01290     return &LMatrix4::ident_mat();
01291   }
01292 }
01293 
01294 ////////////////////////////////////////////////////////////////////
01295 //     Function: GraphicsStateGuardian::fetch_ptr_parameter
01296 //       Access: Public
01297 //  Description: Return a pointer to struct ShaderPtrData
01298 ////////////////////////////////////////////////////////////////////
01299 const Shader::ShaderPtrData *GraphicsStateGuardian::
01300 fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
01301   return (_target_shader->get_shader_input_ptr(spec._arg));
01302 }
01303 
01304 ////////////////////////////////////////////////////////////////////
01305 //     Function: GraphicsStateGuardian::prepare_display_region
01306 //       Access: Public, Virtual
01307 //  Description: Makes the specified DisplayRegion current.  All
01308 //               future drawing and clear operations will be
01309 //               constrained within the given DisplayRegion.
01310 ////////////////////////////////////////////////////////////////////
01311 void GraphicsStateGuardian::
01312 prepare_display_region(DisplayRegionPipelineReader *dr) {
01313   _current_display_region = dr->get_object();
01314   _current_stereo_channel = dr->get_stereo_channel();
01315   _current_tex_view_offset = dr->get_tex_view_offset();
01316   _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render();
01317 
01318   _stereo_buffer_mask = ~0;
01319 
01320   Lens::StereoChannel output_channel = dr->get_stereo_channel();
01321   if (dr->get_window()->get_swap_eyes()) {
01322     // Reverse the output channel.
01323     switch (output_channel) {
01324     case Lens::SC_left:
01325       output_channel = Lens::SC_right;
01326       break;
01327 
01328     case Lens::SC_right:
01329       output_channel = Lens::SC_left;
01330       break;
01331 
01332     default:
01333       break;
01334     }
01335   }
01336 
01337   switch (output_channel) {
01338   case Lens::SC_left:
01339     _color_write_mask = dr->get_window()->get_left_eye_color_mask();
01340     if (_current_properties->is_stereo()) {
01341       _stereo_buffer_mask = ~(RenderBuffer::T_front_right | RenderBuffer::T_back_right);
01342     }
01343     break;
01344 
01345   case Lens::SC_right:
01346     _color_write_mask = dr->get_window()->get_right_eye_color_mask();
01347     if (_current_properties->is_stereo()) {
01348       _stereo_buffer_mask = ~(RenderBuffer::T_front_left | RenderBuffer::T_back_left);
01349     }
01350     break;
01351 
01352   case Lens::SC_mono:
01353   case Lens::SC_stereo:
01354     _color_write_mask = ColorWriteAttrib::C_all;
01355   }
01356 }
01357 
01358 ////////////////////////////////////////////////////////////////////
01359 //     Function: GraphicsStateGuardian::clear_before_callback
01360 //       Access: Public, Virtual
01361 //  Description: Resets any non-standard graphics state that might
01362 //               give a callback apoplexy.  Some drivers require that
01363 //               the graphics state be restored to neutral before
01364 //               performing certain operations.  In OpenGL, for
01365 //               instance, this closes any open vertex buffers.
01366 ////////////////////////////////////////////////////////////////////
01367 void GraphicsStateGuardian::
01368 clear_before_callback() {
01369 }
01370 
01371 ////////////////////////////////////////////////////////////////////
01372 //     Function: GraphicsStateGuardian::clear_state_and_transform
01373 //       Access: Public, Virtual
01374 //  Description: Forgets the current graphics state and current
01375 //               transform, so that the next call to
01376 //               set_state_and_transform() will have to reload
01377 //               everything.  This is a good thing to call when you
01378 //               are no longer sure what the graphics state is.  This
01379 //               should only be called from the draw thread.
01380 ////////////////////////////////////////////////////////////////////
01381 void GraphicsStateGuardian::
01382 clear_state_and_transform() {
01383   // Re-issue the modelview and projection transforms.
01384   reissue_transforms();
01385 
01386   // Now clear the state flags to unknown.
01387   _state_rs = RenderState::make_empty();
01388   _state_mask.clear();
01389 }
01390 
01391 ////////////////////////////////////////////////////////////////////
01392 //     Function: GraphicsStateGuardian::remove_window
01393 //       Access: Public, Virtual
01394 //  Description: This is simply a transparent call to
01395 //               GraphicsEngine::remove_window().  It exists primary
01396 //               to support removing a window from that compiles
01397 //               before the display module, and therefore has no
01398 //               knowledge of a GraphicsEngine object.
01399 ////////////////////////////////////////////////////////////////////
01400 void GraphicsStateGuardian::
01401 remove_window(GraphicsOutputBase *window) {
01402   nassertv(_engine != (GraphicsEngine *)NULL);
01403   GraphicsOutput *win;
01404   DCAST_INTO_V(win, window);
01405   _engine->remove_window(win);
01406 }
01407 
01408 ////////////////////////////////////////////////////////////////////
01409 //     Function: GraphicsStateGuardian::prepare_lens
01410 //       Access: Public, Virtual
01411 //  Description: Makes the current lens (whichever lens was most
01412 //               recently specified with set_scene()) active, so
01413 //               that it will transform future rendered geometry.
01414 //               Normally this is only called from the draw process,
01415 //               and usually it is called by set_scene().
01416 //
01417 //               The return value is true if the lens is acceptable,
01418 //               false if it is not.
01419 ////////////////////////////////////////////////////////////////////
01420 bool GraphicsStateGuardian::
01421 prepare_lens() {
01422   return false;
01423 }
01424 
01425 ////////////////////////////////////////////////////////////////////
01426 //     Function: GraphicsStateGuardian::calc_projection_mat
01427 //       Access: Public, Virtual
01428 //  Description: Given a lens, this function calculates the appropriate
01429 //               projection matrix for this gsg.  The result depends
01430 //               on the peculiarities of the rendering API.
01431 ////////////////////////////////////////////////////////////////////
01432 CPT(TransformState) GraphicsStateGuardian::
01433 calc_projection_mat(const Lens *lens) {
01434   if (lens == (Lens *)NULL) {
01435     return NULL;
01436   }
01437 
01438   if (!lens->is_linear()) {
01439     return NULL;
01440   }
01441 
01442   return TransformState::make_identity();
01443 }
01444 
01445 ////////////////////////////////////////////////////////////////////
01446 //     Function: GraphicsStateGuardian::begin_frame
01447 //       Access: Public, Virtual
01448 //  Description: Called before each frame is rendered, to allow the
01449 //               GSG a chance to do any internal cleanup before
01450 //               beginning the frame.
01451 //
01452 //               The return value is true if successful (in which case
01453 //               the frame will be drawn and end_frame() will be
01454 //               called later), or false if unsuccessful (in which
01455 //               case nothing will be drawn and end_frame() will not
01456 //               be called).
01457 ////////////////////////////////////////////////////////////////////
01458 bool GraphicsStateGuardian::
01459 begin_frame(Thread *current_thread) {
01460   _prepared_objects->begin_frame(this, current_thread);
01461 
01462   // We should reset the state to the default at the beginning of
01463   // every frame.  Although this will incur additional overhead,
01464   // particularly in a simple scene, it helps ensure that states that
01465   // have changed properties since last time without changing
01466   // attribute pointers--like textures, lighting, or fog--will still
01467   // be accurately updated.
01468   _state_rs = RenderState::make_empty();
01469   _state_mask.clear();
01470 
01471   return !_needs_reset;
01472 }
01473 
01474 ////////////////////////////////////////////////////////////////////
01475 //     Function: GraphicsStateGuardian::begin_scene
01476 //       Access: Published, Virtual
01477 //  Description: Called between begin_frame() and end_frame() to mark
01478 //               the beginning of drawing commands for a "scene"
01479 //               (usually a particular DisplayRegion) within a frame.
01480 //               All 3-D drawing commands, except the clear operation,
01481 //               must be enclosed within begin_scene() .. end_scene().
01482 //               This must be called in the draw thread.
01483 //
01484 //               The return value is true if successful (in which case
01485 //               the scene will be drawn and end_scene() will be
01486 //               called later), or false if unsuccessful (in which
01487 //               case nothing will be drawn and end_scene() will not
01488 //               be called).
01489 ////////////////////////////////////////////////////////////////////
01490 bool GraphicsStateGuardian::
01491 begin_scene() {
01492   return true;
01493 }
01494 
01495 ////////////////////////////////////////////////////////////////////
01496 //     Function: GraphicsStateGuardian::end_scene
01497 //       Access: Published, Virtual
01498 //  Description: Called between begin_frame() and end_frame() to mark
01499 //               the end of drawing commands for a "scene" (usually a
01500 //               particular DisplayRegion) within a frame.  All 3-D
01501 //               drawing commands, except the clear operation, must be
01502 //               enclosed within begin_scene() .. end_scene().
01503 ////////////////////////////////////////////////////////////////////
01504 void GraphicsStateGuardian::
01505 end_scene() {
01506   // We should clear this pointer now, so that we don't keep unneeded
01507   // reference counts dangling.  We keep around a "null" scene setup
01508   // object instead of using a null pointer to avoid special-case code
01509   // in set_state_and_transform.
01510   _scene_setup = _scene_null;
01511 
01512   // Undo any lighting we had enabled last scene, to force the lights
01513   // to be reissued, in case their parameters or positions have
01514   // changed between scenes.
01515   int i;
01516   for (i = 0; i < _num_lights_enabled; ++i) {
01517     enable_light(i, false);
01518   }
01519   _num_lights_enabled = 0;
01520 
01521   // Ditto for the clipping planes.
01522   for (i = 0; i < _num_clip_planes_enabled; ++i) {
01523     enable_clip_plane(i, false);
01524   }
01525   _num_clip_planes_enabled = 0;
01526 
01527   // Put the state into the 'unknown' state, forcing a reload.
01528   _state_rs = RenderState::make_empty();
01529   _state_mask.clear();
01530 }
01531 
01532 ////////////////////////////////////////////////////////////////////
01533 //     Function: GraphicsStateGuardian::end_frame
01534 //       Access: Public, Virtual
01535 //  Description: Called after each frame is rendered, to allow the
01536 //               GSG a chance to do any internal cleanup after
01537 //               rendering the frame, and before the window flips.
01538 ////////////////////////////////////////////////////////////////////
01539 void GraphicsStateGuardian::
01540 end_frame(Thread *current_thread) {
01541   _prepared_objects->end_frame(current_thread);
01542 
01543   // Flush any PStatCollectors.
01544   _data_transferred_pcollector.flush_level();
01545 
01546   _primitive_batches_pcollector.flush_level();
01547   _primitive_batches_tristrip_pcollector.flush_level();
01548   _primitive_batches_trifan_pcollector.flush_level();
01549   _primitive_batches_tri_pcollector.flush_level();
01550   _primitive_batches_other_pcollector.flush_level();
01551   _vertices_tristrip_pcollector.flush_level();
01552   _vertices_trifan_pcollector.flush_level();
01553   _vertices_tri_pcollector.flush_level();
01554   _vertices_other_pcollector.flush_level();
01555 
01556   _state_pcollector.flush_level();
01557   _texture_state_pcollector.flush_level();
01558   _transform_state_pcollector.flush_level();
01559   _draw_primitive_pcollector.flush_level();
01560 
01561   // Evict any textures and/or vbuffers that exceed our texture memory.
01562   _prepared_objects->_graphics_memory_lru.begin_epoch();
01563 }
01564 
01565 ////////////////////////////////////////////////////////////////////
01566 //     Function: GraphicsStateGuardian::depth_offset_decals
01567 //       Access: Public, Virtual
01568 //  Description: Returns true if this GSG can implement decals using a
01569 //               DepthOffsetAttrib, or false if that is unreliable
01570 //               and the three-step rendering process should be used
01571 //               instead.
01572 ////////////////////////////////////////////////////////////////////
01573 bool GraphicsStateGuardian::
01574 depth_offset_decals() {
01575   return true;
01576 }
01577 
01578 ////////////////////////////////////////////////////////////////////
01579 //     Function: GraphicsStateGuardian::begin_decal_base_first
01580 //       Access: Public, Virtual
01581 //  Description: Called during draw to begin a three-step rendering
01582 //               phase to draw decals.  The first step,
01583 //               begin_decal_base_first(), is called prior to drawing the
01584 //               base geometry.  It should set up whatever internal
01585 //               state is appropriate, as well as returning a
01586 //               RenderState object that should be applied to the base
01587 //               geometry for rendering.
01588 ////////////////////////////////////////////////////////////////////
01589 CPT(RenderState) GraphicsStateGuardian::
01590 begin_decal_base_first() {
01591   // Turn off writing the depth buffer to render the base geometry.
01592   static CPT(RenderState) decal_base_first;
01593   if (decal_base_first == (const RenderState *)NULL) {
01594     decal_base_first = RenderState::make
01595       (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
01596        RenderState::get_max_priority());
01597   }
01598   return decal_base_first;
01599 }
01600 
01601 ////////////////////////////////////////////////////////////////////
01602 //     Function: GraphicsStateGuardian::begin_decal_nested
01603 //       Access: Public, Virtual
01604 //  Description: Called during draw to begin a three-step rendering
01605 //               phase to draw decals.  The second step,
01606 //               begin_decal_nested(), is called after drawing the
01607 //               base geometry and prior to drawing any of the nested
01608 //               decal geometry that is to be applied to the base
01609 //               geometry.
01610 ////////////////////////////////////////////////////////////////////
01611 CPT(RenderState) GraphicsStateGuardian::
01612 begin_decal_nested() {
01613   // We should keep the depth buffer off during this operation, so
01614   // that decals on decals will render properly.
01615   static CPT(RenderState) decal_nested;
01616   if (decal_nested == (const RenderState *)NULL) {
01617     decal_nested = RenderState::make
01618       (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
01619        RenderState::get_max_priority());
01620   }
01621   return decal_nested;
01622 }
01623 
01624 ////////////////////////////////////////////////////////////////////
01625 //     Function: GraphicsStateGuardian::begin_decal_base_second
01626 //       Access: Public, Virtual
01627 //  Description: Called during draw to begin a three-step rendering
01628 //               phase to draw decals.  The third step,
01629 //               begin_decal_base_second(), is called after drawing the
01630 //               base geometry and the nested decal geometry, and
01631 //               prior to drawing the base geometry one more time (if
01632 //               needed).
01633 //
01634 //               It should return a RenderState object appropriate for
01635 //               rendering the base geometry the second time, or NULL
01636 //               if it is not necessary to re-render the base
01637 //               geometry.
01638 ////////////////////////////////////////////////////////////////////
01639 CPT(RenderState) GraphicsStateGuardian::
01640 begin_decal_base_second() {
01641   // Now let the depth buffer go back on, but turn off writing the
01642   // color buffer to render the base geometry after the second pass.
01643   // Also, turn off texturing since there's no need for it now.
01644   static CPT(RenderState) decal_base_second;
01645   if (decal_base_second == (const RenderState *)NULL) {
01646     decal_base_second = RenderState::make
01647       (ColorWriteAttrib::make(ColorWriteAttrib::C_off),
01648        // On reflection, we need to leave texturing on so the alpha
01649        // test mechanism can work (if it is enabled, e.g. we are
01650        // rendering an object with M_dual transparency).
01651        //       TextureAttrib::make_off(),
01652        RenderState::get_max_priority());
01653   }
01654   return decal_base_second;
01655 }
01656 
01657 ////////////////////////////////////////////////////////////////////
01658 //     Function: GraphicsStateGuardian::finish_decal
01659 //       Access: Public, Virtual
01660 //  Description: Called during draw to clean up after decals are
01661 //               finished.
01662 ////////////////////////////////////////////////////////////////////
01663 void GraphicsStateGuardian::
01664 finish_decal() {
01665   // No need to do anything special here.
01666 }
01667 
01668 ////////////////////////////////////////////////////////////////////
01669 //     Function: GraphicsStateGuardian::begin_draw_primitives()
01670 //       Access: Public, Virtual
01671 //  Description: Called before a sequence of draw_primitive()
01672 //               functions are called, this should prepare the vertex
01673 //               data for rendering.  It returns true if the vertices
01674 //               are ok, false to abort this group of primitives.
01675 ////////////////////////////////////////////////////////////////////
01676 bool GraphicsStateGuardian::
01677 begin_draw_primitives(const GeomPipelineReader *geom_reader,
01678                       const GeomMunger *munger,
01679                       const GeomVertexDataPipelineReader *data_reader,
01680                       bool force) {
01681   _munger = munger;
01682   _data_reader = data_reader;
01683   return _data_reader->has_vertex();
01684 }
01685 
01686 ////////////////////////////////////////////////////////////////////
01687 //     Function: GraphicsStateGuardian::draw_triangles
01688 //       Access: Public, Virtual
01689 //  Description: Draws a series of disconnected triangles.
01690 ////////////////////////////////////////////////////////////////////
01691 bool GraphicsStateGuardian::
01692 draw_triangles(const GeomPrimitivePipelineReader *, bool) {
01693   return false;
01694 }
01695 
01696 ////////////////////////////////////////////////////////////////////
01697 //     Function: GraphicsStateGuardian::draw_tristrips
01698 //       Access: Public, Virtual
01699 //  Description: Draws a series of triangle strips.
01700 ////////////////////////////////////////////////////////////////////
01701 bool GraphicsStateGuardian::
01702 draw_tristrips(const GeomPrimitivePipelineReader *, bool) {
01703   return false;
01704 }
01705 
01706 ////////////////////////////////////////////////////////////////////
01707 //     Function: GraphicsStateGuardian::draw_trifans
01708 //       Access: Public, Virtual
01709 //  Description: Draws a series of triangle fans.
01710 ////////////////////////////////////////////////////////////////////
01711 bool GraphicsStateGuardian::
01712 draw_trifans(const GeomPrimitivePipelineReader *, bool) {
01713   return false;
01714 }
01715 
01716 ////////////////////////////////////////////////////////////////////
01717 //     Function: GraphicsStateGuardian::draw_lines
01718 //       Access: Public, Virtual
01719 //  Description: Draws a series of disconnected line segments.
01720 ////////////////////////////////////////////////////////////////////
01721 bool GraphicsStateGuardian::
01722 draw_lines(const GeomPrimitivePipelineReader *, bool) {
01723   return false;
01724 }
01725 
01726 ////////////////////////////////////////////////////////////////////
01727 //     Function: GraphicsStateGuardian::draw_linestrips
01728 //       Access: Public, Virtual
01729 //  Description: Draws a series of line strips.
01730 ////////////////////////////////////////////////////////////////////
01731 bool GraphicsStateGuardian::
01732 draw_linestrips(const GeomPrimitivePipelineReader *, bool) {
01733   return false;
01734 }
01735 
01736 ////////////////////////////////////////////////////////////////////
01737 //     Function: GraphicsStateGuardian::draw_points
01738 //       Access: Public, Virtual
01739 //  Description: Draws a series of disconnected points.
01740 ////////////////////////////////////////////////////////////////////
01741 bool GraphicsStateGuardian::
01742 draw_points(const GeomPrimitivePipelineReader *, bool) {
01743   return false;
01744 }
01745 
01746 ////////////////////////////////////////////////////////////////////
01747 //     Function: GraphicsStateGuardian::end_draw_primitives()
01748 //       Access: Public, Virtual
01749 //  Description: Called after a sequence of draw_primitive()
01750 //               functions are called, this should do whatever cleanup
01751 //               is appropriate.
01752 ////////////////////////////////////////////////////////////////////
01753 void GraphicsStateGuardian::
01754 end_draw_primitives() {
01755   _munger = NULL;
01756   _data_reader = NULL;
01757 }
01758 
01759 ////////////////////////////////////////////////////////////////////
01760 //     Function: GraphicsStateGuardian::reset
01761 //       Access: Public, Virtual
01762 //  Description: Resets all internal state as if the gsg were newly
01763 //               created.
01764 ////////////////////////////////////////////////////////////////////
01765 void GraphicsStateGuardian::
01766 reset() {
01767   _needs_reset = false;
01768   _is_valid = false;
01769 
01770   _state_rs = RenderState::make_empty();
01771   _target_rs = NULL;
01772   _state_mask.clear();
01773   _internal_transform = _cs_transform;
01774   _scene_null = new SceneSetup;
01775   _scene_setup = _scene_null;
01776 
01777   _color_write_mask = ColorWriteAttrib::C_all;
01778 
01779   _has_scene_graph_color = false;
01780   _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01781   _transform_stale = true;
01782   _color_blend_involves_color_scale = false;
01783   _texture_involves_color_scale = false;
01784   _vertex_colors_enabled = true;
01785   _lighting_enabled = false;
01786   _num_lights_enabled = 0;
01787   _num_clip_planes_enabled = 0;
01788   _clip_planes_enabled = false;
01789 
01790   _color_scale_enabled = false;
01791   _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
01792   _has_texture_alpha_scale = false;
01793 
01794   _has_material_force_color = false;
01795   _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01796   _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
01797 
01798   _tex_gen_modifies_mat = false;
01799   _last_max_stage_index = 0;
01800 
01801   _is_valid = true;
01802 
01803   if (_stencil_render_states) {
01804     delete _stencil_render_states;
01805     _stencil_render_states = 0;
01806   }
01807   _stencil_render_states = new StencilRenderStates (this);
01808 }
01809 
01810 ////////////////////////////////////////////////////////////////////
01811 //     Function: GraphicsStateGuardian::set_state_and_transform
01812 //       Access: Public
01813 //  Description: Simultaneously resets the render state and the
01814 //               transform state.
01815 //
01816 //               This transform specified is the "internal" net
01817 //               transform, already converted into the GSG's internal
01818 //               coordinate space by composing it to
01819 //               get_cs_transform().  (Previously, this used to be the
01820 //               "external" net transform, with the assumption that
01821 //               that GSG would convert it internally, but that is no
01822 //               longer the case.)
01823 //
01824 //               Special case: if (state==NULL), then the target
01825 //               state is already stored in _target.
01826 ////////////////////////////////////////////////////////////////////
01827 void GraphicsStateGuardian::
01828 set_state_and_transform(const RenderState *state,
01829                         const TransformState *trans) {
01830 }
01831 
01832 ////////////////////////////////////////////////////////////////////
01833 //     Function: GraphicsStateGuardian::clear
01834 //       Access: Public
01835 //  Description: Clears the framebuffer within the current
01836 //               DisplayRegion, according to the flags indicated by
01837 //               the given DrawableRegion object.
01838 //
01839 //               This does not set the DisplayRegion first.  You
01840 //               should call prepare_display_region() to specify the
01841 //               region you wish the clear operation to apply to.
01842 ////////////////////////////////////////////////////////////////////
01843 void GraphicsStateGuardian::
01844 clear(DrawableRegion *clearable) {
01845 }
01846 
01847 ////////////////////////////////////////////////////////////////////
01848 //     Function: GraphicsStateGuardian::get_render_buffer
01849 //       Access: Public
01850 //  Description: Returns a RenderBuffer object suitable for operating
01851 //               on the requested set of buffers.  buffer_type is the
01852 //               union of all the desired RenderBuffer::Type values.
01853 ////////////////////////////////////////////////////////////////////
01854 RenderBuffer GraphicsStateGuardian::
01855 get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
01856   return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
01857 }
01858 
01859 ////////////////////////////////////////////////////////////////////
01860 //     Function: GraphicsStateGuardian::get_cs_transform
01861 //       Access: Public, Virtual
01862 //  Description: Returns a transform that converts from the GSG's
01863 //               external coordinate system (as returned by
01864 //               get_coordinate_system()) to its internal coordinate
01865 //               system (as returned by
01866 //               get_internal_coordinate_system()).  This is used for
01867 //               rendering.
01868 ////////////////////////////////////////////////////////////////////
01869 const TransformState *GraphicsStateGuardian::
01870 get_cs_transform() const {
01871   return _cs_transform;
01872 }
01873 
01874 ////////////////////////////////////////////////////////////////////
01875 //     Function: GraphicsStateGuardian::do_issue_clip_plane
01876 //       Access: Public
01877 //  Description: This is fundametically similar to do_issue_light(), with
01878 //               calls to apply_clip_plane() and enable_clip_planes(),
01879 //               as appropriate.
01880 ////////////////////////////////////////////////////////////////////
01881 void GraphicsStateGuardian::
01882 do_issue_clip_plane() {
01883   int num_enabled = 0;
01884   int num_on_planes = 0;
01885 
01886   const ClipPlaneAttrib *target_clip_plane = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
01887   if (target_clip_plane != (ClipPlaneAttrib *)NULL) {
01888     CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
01889 
01890     num_on_planes = new_plane->get_num_on_planes();
01891     for (int li = 0; li < num_on_planes; li++) {
01892       NodePath plane = new_plane->get_on_plane(li);
01893       nassertv(!plane.is_empty());
01894       PlaneNode *plane_node;
01895       DCAST_INTO_V(plane_node, plane.node());
01896       if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) {
01897         // Clipping should be enabled before we apply any planes.
01898         if (!_clip_planes_enabled) {
01899           enable_clip_planes(true);
01900           _clip_planes_enabled = true;
01901         }
01902         
01903         enable_clip_plane(num_enabled, true);
01904         if (num_enabled == 0) {
01905           begin_bind_clip_planes();
01906         }
01907         
01908         bind_clip_plane(plane, num_enabled);
01909         num_enabled++;
01910       }
01911     }
01912   }
01913 
01914   int i;
01915   for (i = num_enabled; i < _num_clip_planes_enabled; ++i) {
01916     enable_clip_plane(i, false);
01917   }
01918   _num_clip_planes_enabled = num_enabled;
01919 
01920   // If no planes were set, disable clipping
01921   if (num_enabled == 0) {
01922     if (_clip_planes_enabled) {
01923       enable_clip_planes(false);
01924       _clip_planes_enabled = false;
01925     }
01926   } else {
01927     end_bind_clip_planes();
01928   }
01929 }
01930 
01931 ////////////////////////////////////////////////////////////////////
01932 //     Function: GraphicsStateGuardian::do_issue_color
01933 //       Access: Public
01934 //  Description: This method is defined in the base class because it
01935 //               is likely that this functionality will be used for
01936 //               all (or at least most) kinds of
01937 //               GraphicsStateGuardians--it's not specific to any one
01938 //               rendering backend.
01939 //
01940 //               The ColorAttribute just changes the interpretation of
01941 //               the color on the vertices, and fiddles with
01942 //               _vertex_colors_enabled, etc.
01943 ////////////////////////////////////////////////////////////////////
01944 void GraphicsStateGuardian::
01945 do_issue_color() {
01946   const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot()));
01947   switch (target_color->get_color_type()) {
01948   case ColorAttrib::T_flat:
01949     // Color attribute flat: it specifies a scene graph color that
01950     // overrides the vertex color.
01951     _scene_graph_color = target_color->get_color();
01952     _has_scene_graph_color = true;
01953     _vertex_colors_enabled = false;
01954     break;
01955 
01956   case ColorAttrib::T_off:
01957     // Color attribute off: it specifies that no scene graph color is
01958     // in effect, and vertex color is not important either.
01959     _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01960     _has_scene_graph_color = false;
01961     _vertex_colors_enabled = false;
01962     break;
01963 
01964   case ColorAttrib::T_vertex:
01965     // Color attribute vertex: it specifies that vertex color should
01966     // be revealed.
01967     _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
01968     _has_scene_graph_color = false;
01969     _vertex_colors_enabled = true;
01970     break;
01971   }
01972 
01973   if (_color_scale_via_lighting) {
01974     _state_mask.clear_bit(LightAttrib::get_class_slot());
01975     _state_mask.clear_bit(MaterialAttrib::get_class_slot());
01976 
01977     determine_light_color_scale();
01978   }
01979 }
01980 
01981 ////////////////////////////////////////////////////////////////////
01982 //     Function: GraphicsStateGuardian::do_issue_color_scale
01983 //       Access: Public, Virtual
01984 //  Description:
01985 ////////////////////////////////////////////////////////////////////
01986 void GraphicsStateGuardian::
01987 do_issue_color_scale() {
01988   // If the previous color scale had set a special texture, clear the
01989   // texture now.
01990   if (_has_texture_alpha_scale) {
01991     _state_mask.clear_bit(TextureAttrib::get_class_slot());
01992   }
01993 
01994   const ColorScaleAttrib *target_color_scale = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot()));
01995   _color_scale_enabled = target_color_scale->has_scale();
01996   _current_color_scale = target_color_scale->get_scale();
01997   _has_texture_alpha_scale = false;
01998 
01999   if (_color_blend_involves_color_scale) {
02000     _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
02001   }
02002   if (_texture_involves_color_scale) {
02003     _state_mask.clear_bit(TextureAttrib::get_class_slot());
02004   }
02005   if (_color_scale_via_lighting) {
02006     _state_mask.clear_bit(LightAttrib::get_class_slot());
02007     _state_mask.clear_bit(MaterialAttrib::get_class_slot());
02008 
02009     determine_light_color_scale();
02010   }
02011 
02012   if (_alpha_scale_via_texture && !_has_scene_graph_color &&
02013       target_color_scale->has_alpha_scale()) {
02014     // This color scale will set a special texture--so again, clear
02015     // the texture.
02016     _state_mask.clear_bit(TextureAttrib::get_class_slot());
02017     _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
02018 
02019     _has_texture_alpha_scale = true;
02020   }
02021 }
02022 
02023 ////////////////////////////////////////////////////////////////////
02024 //     Function: GraphicsStateGuardian::do_issue_light
02025 //       Access: Protected, Virtual
02026 //  Description: This implementation of do_issue_light() assumes
02027 //               we have a limited number of hardware lights
02028 //               available.  This function assigns each light to a
02029 //               different hardware light id, trying to keep each
02030 //               light associated with the same id where possible, but
02031 //               reusing id's when necessary.  When it is no longer
02032 //               possible to reuse existing id's (e.g. all id's are in
02033 //               use), the next sequential id is assigned (if
02034 //               available).
02035 //
02036 //               It will call apply_light() each time a light is
02037 //               assigned to a particular id for the first time in a
02038 //               given frame, and it will subsequently call
02039 //               enable_light() to enable or disable each light as the
02040 //               frame is rendered, as well as enable_lighting() to
02041 //               enable or disable overall lighting.
02042 ////////////////////////////////////////////////////////////////////
02043 void GraphicsStateGuardian::
02044 do_issue_light() {
02045   // Initialize the current ambient light total and newly enabled
02046   // light list
02047   LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
02048   int i;
02049 
02050   int num_enabled = 0;
02051   int num_on_lights = 0;
02052 
02053   const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
02054   if (display_cat.is_spam()) {
02055     display_cat.spam()
02056       << "do_issue_light: " << target_light << "\n";
02057   }
02058   if (target_light != (LightAttrib *)NULL) {
02059     CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights);
02060     if (display_cat.is_spam()) {
02061       new_light->write(display_cat.spam(false), 2);
02062     }
02063 
02064     num_on_lights = new_light->get_num_on_lights();
02065     for (int li = 0; li < num_on_lights; li++) {
02066       NodePath light = new_light->get_on_light(li);
02067       nassertv(!light.is_empty());
02068       Light *light_obj = light.node()->as_light();
02069       nassertv(light_obj != (Light *)NULL);
02070 
02071       // Lighting should be enabled before we apply any lights.
02072       if (!_lighting_enabled) {
02073         enable_lighting(true);
02074         _lighting_enabled = true;
02075       }
02076 
02077       if (light_obj->get_type() == AmbientLight::get_class_type()) {
02078         // Ambient lights don't require specific light ids; simply add
02079         // in the ambient contribution to the current total
02080         cur_ambient_light += light_obj->get_color();
02081 
02082       } else {
02083         const LColor &color = light_obj->get_color();
02084         // Don't bother binding the light if it has no color to contribute.
02085         if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
02086           enable_light(num_enabled, true);
02087           if (num_enabled == 0) {
02088             begin_bind_lights();
02089           }
02090           
02091           light_obj->bind(this, light, num_enabled);
02092           num_enabled++;
02093         }
02094       }
02095     }
02096   }
02097 
02098   for (i = num_enabled; i < _num_lights_enabled; ++i) {
02099     enable_light(i, false);
02100   }
02101   _num_lights_enabled = num_enabled;
02102 
02103   // If no lights were set, disable lighting
02104   if (num_on_lights == 0) {
02105     if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f))) {
02106       // Unless we need lighting anyway to apply a color or color
02107       // scale.
02108       if (!_lighting_enabled) {
02109         enable_lighting(true);
02110         _lighting_enabled = true;
02111       }
02112       set_ambient_light(LColor(1.0f, 1.0f, 1.0f, 1.0f));
02113 
02114     } else {
02115       if (_lighting_enabled) {
02116         enable_lighting(false);
02117         _lighting_enabled = false;
02118       }
02119     }
02120 
02121   } else {
02122     set_ambient_light(cur_ambient_light);
02123   }
02124 
02125   if (num_enabled != 0) {
02126     end_bind_lights();
02127   }
02128 }
02129 
02130 ////////////////////////////////////////////////////////////////////
02131 //     Function: GraphicsStateGuardian::framebuffer_copy_to_texture
02132 //       Access: Public, Virtual
02133 //  Description: Copy the pixels within the indicated display
02134 //               region from the framebuffer into texture memory.
02135 //
02136 //               If z > -1, it is the cube map index into which to
02137 //               copy.
02138 ////////////////////////////////////////////////////////////////////
02139 bool GraphicsStateGuardian::
02140 framebuffer_copy_to_texture(Texture *, int, const DisplayRegion *,
02141                             const RenderBuffer &) {
02142   return false;
02143 }
02144 
02145 
02146 ////////////////////////////////////////////////////////////////////
02147 //     Function: GraphicsStateGuardian::framebuffer_copy_to_ram
02148 //       Access: Public, Virtual
02149 //  Description: Copy the pixels within the indicated display region
02150 //               from the framebuffer into system memory, not texture
02151 //               memory.  Returns true on success, false on failure.
02152 //
02153 //               This completely redefines the ram image of the
02154 //               indicated texture.
02155 ////////////////////////////////////////////////////////////////////
02156 bool GraphicsStateGuardian::
02157 framebuffer_copy_to_ram(Texture *, int, const DisplayRegion *,
02158                         const RenderBuffer &) {
02159   return false;
02160 }
02161 
02162 ////////////////////////////////////////////////////////////////////
02163 //     Function: GraphicsStateGuardian::bind_light
02164 //       Access: Public, Virtual
02165 //  Description: Called the first time a particular light has been
02166 //               bound to a given id within a frame, this should set
02167 //               up the associated hardware light with the light's
02168 //               properties.
02169 ////////////////////////////////////////////////////////////////////
02170 void GraphicsStateGuardian::
02171 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
02172 }
02173 
02174 ////////////////////////////////////////////////////////////////////
02175 //     Function: GraphicsStateGuardian::bind_light
02176 //       Access: Public, Virtual
02177 //  Description: Called the first time a particular light has been
02178 //               bound to a given id within a frame, this should set
02179 //               up the associated hardware light with the light's
02180 //               properties.
02181 ////////////////////////////////////////////////////////////////////
02182 void GraphicsStateGuardian::
02183 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
02184 }
02185 
02186 ////////////////////////////////////////////////////////////////////
02187 //     Function: GraphicsStateGuardian::bind_light
02188 //       Access: Public, Virtual
02189 //  Description: Called the first time a particular light has been
02190 //               bound to a given id within a frame, this should set
02191 //               up the associated hardware light with the light's
02192 //               properties.
02193 ////////////////////////////////////////////////////////////////////
02194 void GraphicsStateGuardian::
02195 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
02196 }
02197 
02198 #ifdef DO_PSTATS
02199 ////////////////////////////////////////////////////////////////////
02200 //     Function: GraphicsStateGuardian::init_frame_pstats
02201 //       Access: Public, Static
02202 //  Description: Initializes the relevant PStats data at the beginning
02203 //               of the frame.
02204 ////////////////////////////////////////////////////////////////////
02205 void GraphicsStateGuardian::
02206 init_frame_pstats() {
02207   if (PStatClient::is_connected()) {
02208     _data_transferred_pcollector.clear_level();
02209     _vertex_buffer_switch_pcollector.clear_level();
02210     _index_buffer_switch_pcollector.clear_level();
02211 
02212     _primitive_batches_pcollector.clear_level();
02213     _primitive_batches_tristrip_pcollector.clear_level();
02214     _primitive_batches_trifan_pcollector.clear_level();
02215     _primitive_batches_tri_pcollector.clear_level();
02216     _primitive_batches_other_pcollector.clear_level();
02217     _vertices_tristrip_pcollector.clear_level();
02218     _vertices_trifan_pcollector.clear_level();
02219     _vertices_tri_pcollector.clear_level();
02220     _vertices_other_pcollector.clear_level();
02221 
02222     _state_pcollector.clear_level();
02223     _transform_state_pcollector.clear_level();
02224     _texture_state_pcollector.clear_level();
02225   }
02226 }
02227 #endif  // DO_PSTATS
02228 
02229 
02230 ////////////////////////////////////////////////////////////////////
02231 //     Function: GraphicsStateGuardian::create_gamma_table
02232 //       Access: Public, Static
02233 //  Description: Create a gamma table.
02234 ////////////////////////////////////////////////////////////////////
02235 void GraphicsStateGuardian::
02236 create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
02237   int i;
02238 
02239   if (gamma <= 0.0) {
02240     // avoid divide by zero and negative exponents
02241     gamma = 1.0;
02242   }
02243   
02244   for (i = 0; i < 256; i++) {
02245     double g;
02246     double x;
02247     PN_stdfloat gamma_correction;
02248     
02249     x = ((double) i / 255.0);
02250     gamma_correction = 1.0 / gamma;    
02251     x = pow (x, (double) gamma_correction);
02252     if (x > 1.00) {
02253       x = 1.0;
02254     }
02255 
02256     g = x * 65535.0;    
02257     red_table [i] = (int)g;
02258     green_table [i] = (int)g;
02259     blue_table [i] = (int)g;
02260   }    
02261 }
02262 
02263 ////////////////////////////////////////////////////////////////////
02264 //     Function: GraphicsStateGuardian::reissue_transforms
02265 //       Access: Protected, Virtual
02266 //  Description: Called by clear_state_and_transform() to ensure that
02267 //               the current modelview and projection matrices are
02268 //               properly loaded in the graphics state, after a
02269 //               callback might have mucked them up.
02270 ////////////////////////////////////////////////////////////////////
02271 void GraphicsStateGuardian::
02272 reissue_transforms() {
02273 }
02274 
02275 ////////////////////////////////////////////////////////////////////
02276 //     Function: GraphicsStateGuardian::enable_lighting
02277 //       Access: Protected, Virtual
02278 //  Description: Intended to be overridden by a derived class to
02279 //               enable or disable the use of lighting overall.  This
02280 //               is called by do_issue_light() according to whether any
02281 //               lights are in use or not.
02282 ////////////////////////////////////////////////////////////////////
02283 void GraphicsStateGuardian::
02284 enable_lighting(bool enable) {
02285 }
02286 
02287 ////////////////////////////////////////////////////////////////////
02288 //     Function: GraphicsStateGuardian::set_ambient_light
02289 //       Access: Protected, Virtual
02290 //  Description: Intended to be overridden by a derived class to
02291 //               indicate the color of the ambient light that should
02292 //               be in effect.  This is called by do_issue_light() after
02293 //               all other lights have been enabled or disabled.
02294 ////////////////////////////////////////////////////////////////////
02295 void GraphicsStateGuardian::
02296 set_ambient_light(const LColor &color) {
02297 }
02298 
02299 ////////////////////////////////////////////////////////////////////
02300 //     Function: GraphicsStateGuardian::enable_light
02301 //       Access: Protected, Virtual
02302 //  Description: Intended to be overridden by a derived class to
02303 //               enable the indicated light id.  A specific Light will
02304 //               already have been bound to this id via bind_light().
02305 ////////////////////////////////////////////////////////////////////
02306 void GraphicsStateGuardian::
02307 enable_light(int light_id, bool enable) {
02308 }
02309 
02310 ////////////////////////////////////////////////////////////////////
02311 //     Function: GraphicsStateGuardian::begin_bind_lights
02312 //       Access: Protected, Virtual
02313 //  Description: Called immediately before bind_light() is called,
02314 //               this is intended to provide the derived class a hook
02315 //               in which to set up some state (like transform) that
02316 //               might apply to several lights.
02317 //
02318 //               The sequence is: begin_bind_lights() will be called,
02319 //               then one or more bind_light() calls, then
02320 //               end_bind_lights().
02321 ////////////////////////////////////////////////////////////////////
02322 void GraphicsStateGuardian::
02323 begin_bind_lights() {
02324 }
02325 
02326 ////////////////////////////////////////////////////////////////////
02327 //     Function: GraphicsStateGuardian::end_bind_lights
02328 //       Access: Protected, Virtual
02329 //  Description: Called after before bind_light() has been called one
02330 //               or more times (but before any geometry is issued or
02331 //               additional state is changed), this is intended to
02332 //               clean up any temporary changes to the state that may
02333 //               have been made by begin_bind_lights().
02334 ////////////////////////////////////////////////////////////////////
02335 void GraphicsStateGuardian::
02336 end_bind_lights() {
02337 }
02338 
02339 ////////////////////////////////////////////////////////////////////
02340 //     Function: GraphicsStateGuardian::enable_clip_planes
02341 //       Access: Protected, Virtual
02342 //  Description: Intended to be overridden by a derived class to
02343 //               enable or disable the use of clipping planes overall.
02344 //               This is called by do_issue_clip_plane() according to
02345 //               whether any planes are in use or not.
02346 ////////////////////////////////////////////////////////////////////
02347 void GraphicsStateGuardian::
02348 enable_clip_planes(bool enable) {
02349 }
02350 
02351 ////////////////////////////////////////////////////////////////////
02352 //     Function: GraphicsStateGuardian::enable_clip_plane
02353 //       Access: Protected, Virtual
02354 //  Description: Intended to be overridden by a derived class to
02355 //               enable the indicated plane id.  A specific PlaneNode
02356 //               will already have been bound to this id via
02357 //               bind_clip_plane().
02358 ////////////////////////////////////////////////////////////////////
02359 void GraphicsStateGuardian::
02360 enable_clip_plane(int plane_id, bool enable) {
02361 }
02362 
02363 ////////////////////////////////////////////////////////////////////
02364 //     Function: GraphicsStateGuardian::begin_bind_clip_planes
02365 //       Access: Protected, Virtual
02366 //  Description: Called immediately before bind_clip_plane() is called,
02367 //               this is intended to provide the derived class a hook
02368 //               in which to set up some state (like transform) that
02369 //               might apply to several planes.
02370 //
02371 //               The sequence is: begin_bind_clip_planes() will be
02372 //               called, then one or more bind_clip_plane() calls,
02373 //               then end_bind_clip_planes().
02374 ////////////////////////////////////////////////////////////////////
02375 void GraphicsStateGuardian::
02376 begin_bind_clip_planes() {
02377 }
02378 
02379 ////////////////////////////////////////////////////////////////////
02380 //     Function: GraphicsStateGuardian::bind_clip_plane
02381 //       Access: Public, Virtual
02382 //  Description: Called the first time a particular clipping plane has been
02383 //               bound to a given id within a frame, this should set
02384 //               up the associated hardware (or API) clipping plane
02385 //               with the plane's properties.
02386 ////////////////////////////////////////////////////////////////////
02387 void GraphicsStateGuardian::
02388 bind_clip_plane(const NodePath &plane, int plane_id) {
02389 }
02390 
02391 ////////////////////////////////////////////////////////////////////
02392 //     Function: GraphicsStateGuardian::end_bind_clip_planes
02393 //       Access: Protected, Virtual
02394 //  Description: Called after before bind_clip_plane() has been called one
02395 //               or more times (but before any geometry is issued or
02396 //               additional state is changed), this is intended to
02397 //               clean up any temporary changes to the state that may
02398 //               have been made by begin_bind_clip_planes().
02399 ////////////////////////////////////////////////////////////////////
02400 void GraphicsStateGuardian::
02401 end_bind_clip_planes() {
02402 }
02403 
02404 ////////////////////////////////////////////////////////////////////
02405 //     Function: GraphicsStateGuardian::determine_target_texture
02406 //       Access: Protected
02407 //  Description: Assigns _target_texture and _target_tex_gen
02408 //               based on the _target_rs.
02409 ////////////////////////////////////////////////////////////////////
02410 void GraphicsStateGuardian::
02411 determine_target_texture() {
02412   const TextureAttrib *target_texture = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
02413   const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
02414 
02415   nassertv(target_texture != (TextureAttrib *)NULL &&
02416            target_tex_gen != (TexGenAttrib *)NULL);
02417   _target_texture = target_texture;
02418   _target_tex_gen = target_tex_gen;
02419   
02420   if (_has_texture_alpha_scale) {
02421     PT(TextureStage) stage = get_alpha_scale_texture_stage();
02422     PT(Texture) texture = TexturePool::get_alpha_scale_map();
02423     
02424     _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
02425     _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
02426                                (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
02427   }
02428 
02429   int max_texture_stages = get_max_texture_stages();
02430   _target_texture = _target_texture->filter_to_max(max_texture_stages);
02431   nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
02432 }
02433 
02434 ////////////////////////////////////////////////////////////////////
02435 //     Function: GraphicsStateGuardian::free_pointers
02436 //       Access: Protected, Virtual
02437 //  Description: Frees some memory that was explicitly allocated
02438 //               within the glgsg.
02439 ////////////////////////////////////////////////////////////////////
02440 void GraphicsStateGuardian::
02441 free_pointers() {
02442 }
02443 
02444 ////////////////////////////////////////////////////////////////////
02445 //     Function: GraphicsStateGuardian::close_gsg
02446 //       Access: Protected, Virtual
02447 //  Description: This is called by the associated GraphicsWindow when
02448 //               close_window() is called.  It should null out the
02449 //               _win pointer and possibly free any open resources
02450 //               associated with the GSG.
02451 ////////////////////////////////////////////////////////////////////
02452 void GraphicsStateGuardian::
02453 close_gsg() {
02454   // Protect from multiple calls, and also inform any other functions
02455   // not to try to create new stuff while we're going down.
02456   if (_closing_gsg) {
02457     return;
02458   }
02459   _closing_gsg = true;
02460 
02461   if (display_cat.is_debug()) {
02462     display_cat.debug()
02463       << this << " close_gsg " << get_type() << "\n";
02464   }
02465   free_pointers();
02466 
02467   // As tempting as it may be to try to release all the textures and
02468   // geoms now, we can't, because we might not be the currently-active
02469   // GSG (this is particularly important in OpenGL, which maintains
02470   // one currently-active GL state in each thread).  If we start
02471   // deleting textures, we'll be inadvertently deleting textures from
02472   // some other OpenGL state.
02473 
02474   // Fortunately, it doesn't really matter, since the graphics API
02475   // will be responsible for cleaning up anything we don't clean up
02476   // explicitly.  We'll just let them drop.
02477 
02478   // However, if any objects have recently been released, we have to
02479   // ensure they are actually deleted properly.
02480   Thread *current_thread = Thread::get_current_thread();
02481   _prepared_objects->begin_frame(this, current_thread);
02482   _prepared_objects->end_frame(current_thread);
02483 }
02484 
02485 ////////////////////////////////////////////////////////////////////
02486 //     Function: GraphicsStateGuardian::panic_deactivate
02487 //       Access: Protected
02488 //  Description: This is called internally when it is determined that
02489 //               things are just fubar.  It temporarily deactivates
02490 //               the GSG just so things don't get out of hand, and
02491 //               throws an event so the application can deal with this
02492 //               if it needs to.
02493 ////////////////////////////////////////////////////////////////////
02494 void GraphicsStateGuardian::
02495 panic_deactivate() {
02496   if (_active) {
02497     display_cat.error()
02498       << "Deactivating " << get_type() << ".\n";
02499     set_active(false);
02500     throw_event("panic-deactivate-gsg", this);
02501   }
02502 }
02503 
02504 ////////////////////////////////////////////////////////////////////
02505 //     Function: GraphicsStateGuardian::determine_light_color_scale
02506 //       Access: Protected
02507 //  Description: Called whenever the color or color scale is changed,
02508 //               if _color_scale_via_lighting is true.  This will
02509 //               rederive _material_force_color and _light_color_scale
02510 //               appropriately.
02511 ////////////////////////////////////////////////////////////////////
02512 void GraphicsStateGuardian::
02513 determine_light_color_scale() {
02514   if (_has_scene_graph_color) {
02515     // If we have a scene graph color, it, plus the color scale, goes
02516     // directly into the material; we don't color scale the
02517     // lights--this allows an alpha color scale to work properly.
02518     _has_material_force_color = true;
02519     _material_force_color = _scene_graph_color;
02520     _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
02521     if (!_color_blend_involves_color_scale && _color_scale_enabled) {
02522       _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
02523                                 _scene_graph_color[1] * _current_color_scale[1],
02524                                 _scene_graph_color[2] * _current_color_scale[2],
02525                                 _scene_graph_color[3] * _current_color_scale[3]);
02526     }
02527 
02528   } else {
02529     // Otherise, leave the materials alone, but we might still scale
02530     // the lights.
02531     _has_material_force_color = false;
02532     _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
02533     if (!_color_blend_involves_color_scale && _color_scale_enabled) {
02534       _light_color_scale = _current_color_scale;
02535     }
02536   }
02537 }
02538 
02539 ////////////////////////////////////////////////////////////////////
02540 //     Function: GraphicsStateGuardian::get_unlit_state
02541 //       Access: Protected, Static
02542 //  Description:
02543 ////////////////////////////////////////////////////////////////////
02544 CPT(RenderState) GraphicsStateGuardian::
02545 get_unlit_state() {
02546   static CPT(RenderState) state = NULL;
02547   if (state == (const RenderState *)NULL) {
02548     state = RenderState::make(LightAttrib::make_all_off());
02549   }
02550   return state;
02551 }
02552 
02553 ////////////////////////////////////////////////////////////////////
02554 //     Function: GraphicsStateGuardian::get_unclipped_state
02555 //       Access: Protected, Static
02556 //  Description:
02557 ////////////////////////////////////////////////////////////////////
02558 CPT(RenderState) GraphicsStateGuardian::
02559 get_unclipped_state() {
02560   static CPT(RenderState) state = NULL;
02561   if (state == (const RenderState *)NULL) {
02562     state = RenderState::make(ClipPlaneAttrib::make_all_off());
02563   }
02564   return state;
02565 }
02566 
02567 ////////////////////////////////////////////////////////////////////
02568 //     Function: GraphicsStateGuardian::get_untextured_state
02569 //       Access: Protected, Static
02570 //  Description:
02571 ////////////////////////////////////////////////////////////////////
02572 CPT(RenderState) GraphicsStateGuardian::
02573 get_untextured_state() {
02574   static CPT(RenderState) state = NULL;
02575   if (state == (const RenderState *)NULL) {
02576     state = RenderState::make(TextureAttrib::make_off());
02577   }
02578   return state;
02579 }
02580 
02581 ////////////////////////////////////////////////////////////////////
02582 //     Function: GraphicsStateGuardian::async_reload_texture
02583 //       Access: Protected
02584 //  Description: Should be called when a texture is encountered that
02585 //               needs to have its RAM image reloaded, and
02586 //               get_incomplete_render() is true.  This will fire off
02587 //               a thread on the current Loader object that will
02588 //               request the texture to load its image.  The image
02589 //               will be available at some point in the future (no
02590 //               event will be generated).
02591 ////////////////////////////////////////////////////////////////////
02592 void GraphicsStateGuardian::
02593 async_reload_texture(TextureContext *tc) {
02594   nassertv(_loader != (Loader *)NULL);
02595 
02596   int priority = 0;
02597   if (_current_display_region != (DisplayRegion *)NULL) {
02598     priority = _current_display_region->get_texture_reload_priority();
02599   }
02600 
02601   string task_name = string("reload:") + tc->get_texture()->get_name();
02602   PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
02603   
02604   // See if we are already loading this task.
02605   AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
02606   int num_tasks = orig_tasks.get_num_tasks();
02607   for (int ti = 0; ti < num_tasks; ++ti) {
02608     AsyncTask *task = orig_tasks.get_task(ti);
02609     if (task->is_exact_type(TextureReloadRequest::get_class_type()) &&
02610         DCAST(TextureReloadRequest, task)->get_texture() == tc->get_texture()) {
02611       // This texture is already queued to be reloaded.  Don't queue
02612       // it again, just make sure the priority is updated, and return.
02613       task->set_priority(max(task->get_priority(), priority));
02614       return;
02615     }
02616   }
02617 
02618   // This texture has not yet been queued to be reloaded.  Queue it up
02619   // now.
02620   PT(AsyncTask) request = 
02621     new TextureReloadRequest(task_name,
02622                              _prepared_objects, tc->get_texture(),
02623                              _supports_compressed_texture);
02624   request->set_priority(priority);
02625   _loader->load_async(request);
02626 }
02627 
02628 ////////////////////////////////////////////////////////////////////
02629 //     Function: GraphicsStateGuardian::make_shadow_buffer
02630 //       Access: Protected
02631 //  Description: Creates a depth buffer for shadow mapping. This
02632 //               is a convenience function for the ShaderGenerator;
02633 //               putting this directly in the ShaderGenerator would
02634 //               cause circular dependency issues.
02635 //               Returns the depth texture.
02636 ////////////////////////////////////////////////////////////////////
02637 PT(Texture) GraphicsStateGuardian::
02638 make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
02639   // Make sure everything is valid.
02640   nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
02641            light_np.node()->is_of_type(PointLight::get_class_type()) ||
02642            light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
02643 
02644   PT(LightLensNode) light = DCAST(LightLensNode, light_np.node());
02645   if (light == NULL || !light->_shadow_caster) {
02646     return NULL;
02647   }
02648 
02649   bool is_point = light->is_of_type(PointLight::get_class_type());
02650 
02651   nassertr(light->_sbuffers.count(this) == 0, NULL);
02652 
02653   display_cat.debug() << "Constructing shadow buffer for light '" << light->get_name()
02654     << "', size=" << light->_sb_xsize << "x" << light->_sb_ysize
02655     << ", sort=" << light->_sb_sort << "\n";
02656 
02657   // Setup some flags and properties
02658   FrameBufferProperties fbp;
02659   fbp.set_depth_bits(1); // We only need depth
02660   WindowProperties props = WindowProperties::size(light->_sb_xsize, light->_sb_ysize);
02661   int flags = GraphicsPipe::BF_refuse_window;
02662   if (is_point) {
02663     flags |= GraphicsPipe::BF_size_square;
02664   }
02665 
02666   // Create the buffer
02667   PT(GraphicsOutput) sbuffer = get_engine()->make_output(get_pipe(), light->get_name(),
02668       light->_sb_sort, fbp, props, flags, this, DCAST(GraphicsOutput, host));
02669   nassertr(sbuffer != NULL, NULL);
02670 
02671   // Create a texture and fill it in with some data to workaround an OpenGL error
02672   PT(Texture) tex = new Texture(light->get_name());
02673   if (is_point) {
02674     if (light->_sb_xsize != light->_sb_ysize) {
02675       display_cat.error()
02676         << "PointLight shadow buffers must have an equal width and height!\n";
02677     }
02678     tex->setup_cube_map(light->_sb_xsize, Texture::T_float, Texture::F_depth_component);
02679   } else {
02680     tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_float, Texture::F_depth_component);
02681   }
02682   tex->make_ram_image();
02683   sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
02684 
02685   // Set the wrap mode
02686   if (is_point) {
02687     tex->set_wrap_u(Texture::WM_clamp);
02688     tex->set_wrap_v(Texture::WM_clamp);
02689   } else {
02690     tex->set_wrap_u(Texture::WM_border_color);
02691     tex->set_wrap_v(Texture::WM_border_color);
02692     tex->set_border_color(LVecBase4(1, 1, 1, 1));
02693   }
02694 
02695   if (get_supports_shadow_filter()) {
02696     // If we have the ARB_shadow extension, enable shadow filtering.
02697     tex->set_minfilter(Texture::FT_shadow);
02698     tex->set_magfilter(Texture::FT_shadow);
02699   } else {
02700     // We only accept linear - this tells the GPU to use hardware PCF.
02701     tex->set_minfilter(Texture::FT_linear);
02702     tex->set_magfilter(Texture::FT_linear);
02703   }
02704 
02705   // Assign display region(s) to the buffer and camera
02706   if (is_point) {
02707     for (int i = 0; i < 6; ++i) {
02708       PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
02709       dr->set_lens_index(i);
02710       dr->set_cube_map_index(i);
02711       dr->set_camera(light_np);
02712       dr->set_clear_depth_active(true);
02713     }
02714   } else {
02715     PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
02716     dr->set_camera(light_np);
02717     dr->set_clear_depth_active(true);
02718   }
02719   light->_sbuffers[this] = sbuffer;
02720 
02721   return tex;
02722 }
02723 
02724 ////////////////////////////////////////////////////////////////////
02725 //     Function: GraphicsStateGuardian::get_driver_vendor
02726 //       Access: Public, Virtual
02727 //  Description: Returns the vendor of the video card driver 
02728 ////////////////////////////////////////////////////////////////////
02729 string GraphicsStateGuardian::
02730 get_driver_vendor() {
02731   return string("0");
02732 }
02733 
02734 ////////////////////////////////////////////////////////////////////
02735 //     Function: GraphicsStateGuardian::get_driver_vendor
02736 //       Access: Public, Virtual
02737 //  Description: Returns GL_Renderer
02738 ////////////////////////////////////////////////////////////////////
02739 string GraphicsStateGuardian::get_driver_renderer() {
02740   return string("0");
02741 }
02742 
02743 ////////////////////////////////////////////////////////////////////
02744 //     Function: GraphicsStateGuardian::get_driver_version
02745 //       Access: Public, Virtual
02746 //  Description: Returns driver version
02747 ////////////////////////////////////////////////////////////////////
02748 string GraphicsStateGuardian::
02749 get_driver_version() {
02750   return string("0");
02751 }
02752 
02753 ////////////////////////////////////////////////////////////////////
02754 //     Function: GraphicsStateGuardian::get_driver_version_major
02755 //       Access: Public, Virtual
02756 //  Description: Returns major version of the video driver
02757 ////////////////////////////////////////////////////////////////////
02758 int GraphicsStateGuardian::
02759 get_driver_version_major() {
02760   return -1;
02761 }
02762 
02763 ////////////////////////////////////////////////////////////////////
02764 //     Function: GraphicsStateGuardian::get_driver_version_minor
02765 //       Access: Public, Virtual
02766 //  Description: Returns the minor version of the video driver
02767 ////////////////////////////////////////////////////////////////////
02768 int GraphicsStateGuardian::
02769 get_driver_version_minor() {
02770   return -1;
02771 }
02772 
02773 ////////////////////////////////////////////////////////////////////
02774 //     Function: GraphicsStateGuardian::get_driver_shader_version_major
02775 //       Access: Public, Virtual
02776 //  Description: Returns the major version of the shader model
02777 ////////////////////////////////////////////////////////////////////
02778 int GraphicsStateGuardian::
02779 get_driver_shader_version_major() {
02780   return -1;
02781 }
02782 
02783 ////////////////////////////////////////////////////////////////////
02784 //     Function: GraphicsStateGuardian::get_driver_shader_version_minor
02785 //       Access: Public, Virtual
02786 //  Description: Returns the minor version of the shader model
02787 ////////////////////////////////////////////////////////////////////
02788 int GraphicsStateGuardian::
02789 get_driver_shader_version_minor() {
02790   return -1;
02791 }
 All Classes Functions Variables Enumerations