Panda3D

graphicsStateGuardian.cxx

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