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