Panda3D
 All Classes Functions Variables Enumerations
graphicsStateGuardian.cxx
1 // Filename: graphicsStateGuardian.cxx
2 // Created by: drose (02eb99)
3 // Updated by: fperazzi, PandaSE (05May10) (added fetch_ptr_parameter,
4 // _max_2d_texture_array_layers, _supports_2d_texture_array,
5 // get_supports_cg_profile)
6 //
7 ////////////////////////////////////////////////////////////////////
8 //
9 // PANDA 3D SOFTWARE
10 // Copyright (c) Carnegie Mellon University. All rights reserved.
11 //
12 // All use of this software is subject to the terms of the revised BSD
13 // license. You should have received a copy of this license along
14 // with this source code in a file named "LICENSE."
15 //
16 ////////////////////////////////////////////////////////////////////
17 
18 #include "graphicsStateGuardian.h"
19 #include "graphicsEngine.h"
20 #include "config_display.h"
21 #include "textureContext.h"
22 #include "vertexBufferContext.h"
23 #include "indexBufferContext.h"
24 #include "renderBuffer.h"
25 #include "light.h"
26 #include "planeNode.h"
27 #include "ambientLight.h"
28 #include "throw_event.h"
29 #include "clockObject.h"
30 #include "pStatTimer.h"
31 #include "pStatGPUTimer.h"
32 #include "geomTristrips.h"
33 #include "geomTrifans.h"
34 #include "geomLinestrips.h"
35 #include "colorWriteAttrib.h"
36 #include "shader.h"
37 #include "pnotify.h"
38 #include "drawableRegion.h"
39 #include "displayRegion.h"
40 #include "graphicsOutput.h"
41 #include "texturePool.h"
42 #include "geomMunger.h"
43 #include "ambientLight.h"
44 #include "directionalLight.h"
45 #include "pointLight.h"
46 #include "spotlight.h"
47 #include "textureReloadRequest.h"
48 #include "shaderAttrib.h"
49 #include "materialAttrib.h"
50 #include "depthWriteAttrib.h"
51 #include "lightAttrib.h"
52 #include "texGenAttrib.h"
53 #include "shaderGenerator.h"
54 #include "lightLensNode.h"
55 #include "colorAttrib.h"
56 #include "colorScaleAttrib.h"
57 #include "clipPlaneAttrib.h"
58 #include "fogAttrib.h"
59 #include "config_pstats.h"
60 
61 #include <algorithm>
62 #include <limits.h>
63 
64 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
65 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
66 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
67 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
68 PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer");
69 PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer");
70 PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
71 PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
72 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
73 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
74 PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches");
75 PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector("Primitive batches:Triangle strips");
76 PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector("Primitive batches:Triangle fans");
77 PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector("Primitive batches:Triangles");
78 PStatCollector GraphicsStateGuardian::_primitive_batches_patch_pcollector("Primitive batches:Patches");
79 PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector("Primitive batches:Other");
80 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips");
81 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans");
82 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles");
83 PStatCollector GraphicsStateGuardian::_vertices_patch_pcollector("Vertices:Patches");
84 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector("Vertices:Other");
85 PStatCollector GraphicsStateGuardian::_state_pcollector("State changes");
86 PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes:Transforms");
87 PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures");
88 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive:Draw");
89 PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector("Draw:Set State");
90 PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear");
91 PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush");
92 PStatCollector GraphicsStateGuardian::_compute_dispatch_pcollector("Draw:Compute dispatch");
93 
94 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
95 PStatCollector GraphicsStateGuardian::_wait_timer_pcollector("Wait:Timer Queries");
96 PStatCollector GraphicsStateGuardian::_timer_queries_pcollector("Timer queries");
97 PStatCollector GraphicsStateGuardian::_command_latency_pcollector("Command latency");
98 
99 PStatCollector GraphicsStateGuardian::_prepare_pcollector("Draw:Prepare");
100 PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector("Draw:Prepare:Texture");
101 PStatCollector GraphicsStateGuardian::_prepare_sampler_pcollector("Draw:Prepare:Sampler");
102 PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector("Draw:Prepare:Geom");
103 PStatCollector GraphicsStateGuardian::_prepare_shader_pcollector("Draw:Prepare:Shader");
104 PStatCollector GraphicsStateGuardian::_prepare_vertex_buffer_pcollector("Draw:Prepare:Vertex buffer");
105 PStatCollector GraphicsStateGuardian::_prepare_index_buffer_pcollector("Draw:Prepare:Index buffer");
106 
107 PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform");
108 PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test");
109 PStatCollector GraphicsStateGuardian::_draw_set_state_antialias_pcollector("Draw:Set State:Antialias");
110 PStatCollector GraphicsStateGuardian::_draw_set_state_clip_plane_pcollector("Draw:Set State:Clip plane");
111 PStatCollector GraphicsStateGuardian::_draw_set_state_color_pcollector("Draw:Set State:Color");
112 PStatCollector GraphicsStateGuardian::_draw_set_state_cull_face_pcollector("Draw:Set State:Cull face");
113 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_offset_pcollector("Draw:Set State:Depth offset");
114 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_test_pcollector("Draw:Set State:Depth test");
115 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_write_pcollector("Draw:Set State:Depth write");
116 PStatCollector GraphicsStateGuardian::_draw_set_state_render_mode_pcollector("Draw:Set State:Render mode");
117 PStatCollector GraphicsStateGuardian::_draw_set_state_rescale_normal_pcollector("Draw:Set State:Rescale normal");
118 PStatCollector GraphicsStateGuardian::_draw_set_state_shade_model_pcollector("Draw:Set State:Shade model");
119 PStatCollector GraphicsStateGuardian::_draw_set_state_blending_pcollector("Draw:Set State:Blending");
120 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_pcollector("Draw:Set State:Shader");
121 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_parameters_pcollector("Draw:Set State:Shader Parameters");
122 PStatCollector GraphicsStateGuardian::_draw_set_state_texture_pcollector("Draw:Set State:Texture");
123 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_matrix_pcollector("Draw:Set State:Tex matrix");
124 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_gen_pcollector("Draw:Set State:Tex gen");
125 PStatCollector GraphicsStateGuardian::_draw_set_state_material_pcollector("Draw:Set State:Material");
126 PStatCollector GraphicsStateGuardian::_draw_set_state_light_pcollector("Draw:Set State:Light");
127 PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector("Draw:Set State:Stencil");
128 PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector("Draw:Set State:Fog");
129 PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector("Draw:Set State:Scissor");
130 
131 PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL;
132 
133 TypeHandle GraphicsStateGuardian::_type_handle;
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: GraphicsStateGuardian::Constructor
137 // Access: Public
138 // Description:
139 ////////////////////////////////////////////////////////////////////
140 
142 GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
143  GraphicsEngine *engine, GraphicsPipe *pipe) :
144  _internal_coordinate_system(internal_coordinate_system),
145  _pipe(pipe),
146  _engine(engine)
147 {
148  _coordinate_system = CS_invalid;
149  _internal_transform = TransformState::make_identity();
150 
151  set_coordinate_system(get_default_coordinate_system());
152 
153  _data_reader = (GeomVertexDataPipelineReader *)NULL;
154  _current_display_region = (DisplayRegion*)NULL;
155  _current_stereo_channel = Lens::SC_mono;
156  _current_tex_view_offset = 0;
157  _current_lens = (Lens *)NULL;
158  _projection_mat = TransformState::make_identity();
159  _projection_mat_inv = TransformState::make_identity();
160 
161  _needs_reset = true;
162  _is_valid = false;
163  _current_properties = NULL;
164  _closing_gsg = false;
165  _active = true;
166  _prepared_objects = new PreparedGraphicsObjects;
167  _stereo_buffer_mask = ~0;
168  _incomplete_render = allow_incomplete_render;
169  _effective_incomplete_render = false;
170  _loader = Loader::get_global_ptr();
171 
172  _is_hardware = false;
173  _prefers_triangle_strips = false;
174  _max_vertices_per_array = INT_MAX;
175  _max_vertices_per_primitive = INT_MAX;
176 
177  // Initially, we set this to 1 (the default--no multitexturing
178  // supported). A derived GSG may set this differently if it
179  // supports multitexturing.
180  _max_texture_stages = 1;
181 
182  // Also initially, we assume there are no limits on texture sizes,
183  // and that 3-d and cube-map textures are not supported.
184  _max_texture_dimension = -1;
185  _max_3d_texture_dimension = 0;
186  _max_2d_texture_array_layers = 0;
187  _max_cube_map_dimension = 0;
188 
189  // Assume we don't support these fairly advanced texture combiner
190  // modes.
191  _supports_texture_combine = false;
192  _supports_texture_saved_result = false;
193  _supports_texture_dot3 = false;
194 
195  _supports_3d_texture = false;
196  _supports_2d_texture_array = false;
197  _supports_cube_map = false;
198  _supports_tex_non_pow2 = false;
199  _supports_texture_srgb = false;
200  _supports_compressed_texture = false;
201  _compressed_texture_formats.clear();
202  _compressed_texture_formats.set_bit(Texture::CM_off);
203 
204  // Assume no limits on number of lights or clip planes.
205  _max_lights = -1;
206  _max_clip_planes = -1;
207 
208  // Assume no vertex blending capability.
209  _max_vertex_transforms = 0;
210  _max_vertex_transform_indices = 0;
211 
212  _supports_occlusion_query = false;
213  _supports_timer_query = false;
214 
215 #ifdef DO_PSTATS
216  _timer_queries_active = false;
217  _last_query_frame = 0;
218  _last_num_queried = 0;
219  //_timer_delta = 0.0;
220 
221  _pstats_gpu_thread = -1;
222 #endif
223 
224  // Initially, we set this to false; a GSG that knows it has this
225  // property should set it to true.
226  _copy_texture_inverted = false;
227 
228  // Similarly with these capabilities flags.
229  _supports_multisample = false;
230  _supports_generate_mipmap = false;
231  _supports_depth_texture = false;
232  _supports_depth_stencil = false;
233  _supports_shadow_filter = false;
234  _supports_sampler_objects = false;
235  _supports_basic_shaders = false;
236  _supports_geometry_shaders = false;
237  _supports_tessellation_shaders = false;
238  _supports_glsl = false;
239 
240  _supports_stencil = false;
241  _supports_stencil_wrap = false;
242  _supports_two_sided_stencil = false;
243  _supports_geometry_instancing = false;
244 
245  // Assume a maximum of 1 render target in absence of MRT.
246  _max_color_targets = 1;
247 
248  _supported_geom_rendering = 0;
249 
250  // If this is true, then we can apply a color and/or color scale by
251  // twiddling the material and/or ambient light (which could mean
252  // enabling lighting even without a LightAttrib).
253  _color_scale_via_lighting = color_scale_via_lighting;
254 
255  // Similarly for applying a texture to achieve uniform alpha
256  // scaling.
257  _alpha_scale_via_texture = alpha_scale_via_texture;
258 
259  // Few GSG's can do this, since it requires touching each vertex as
260  // it is rendered.
261  _runtime_color_scale = false;
262 
263  // The default is no shader support.
264  _auto_detect_shader_model = SM_00;
265  _shader_model = SM_00;
266 
267  _gamma = 1.0f;
268  _texture_quality_override = Texture::QL_default;
269 }
270 
271 ////////////////////////////////////////////////////////////////////
272 // Function: GraphicsStateGuardian::Destructor
273 // Access: Public, Virtual
274 // Description:
275 ////////////////////////////////////////////////////////////////////
276 GraphicsStateGuardian::
277 ~GraphicsStateGuardian() {
278  remove_gsg(this);
280 }
281 
282 ////////////////////////////////////////////////////////////////////
283 // Function: GraphicsStateGuardian::get_engine
284 // Access: Published
285 // Description: Returns the graphics engine that created this GSG.
286 // Since there is normally only one GraphicsEngine
287 // object in an application, this is usually the same as
288 // the global GraphicsEngine.
289 ////////////////////////////////////////////////////////////////////
291 get_engine() const {
292  nassertr(_engine != (GraphicsEngine *)NULL, GraphicsEngine::get_global_ptr());
293  return _engine;
294 }
295 
296 ////////////////////////////////////////////////////////////////////
297 // Function: GraphicsStateGuardian::get_supports_multisample
298 // Access: Published, Virtual
299 // Description: Returns true if this particular GSG supports using
300 // the multisample bits to provide antialiasing, and
301 // also supports M_multisample and M_multisample_mask
302 // transparency modes. If this is not true for a
303 // particular GSG, Panda will map the M_multisample
304 // modes to M_binary.
305 //
306 // This method is declared virtual solely so that it can
307 // be queried from cullResult.cxx.
308 ////////////////////////////////////////////////////////////////////
311  return _supports_multisample;
312 }
313 
314 ////////////////////////////////////////////////////////////////////
315 // Function: GraphicsStateGuardian::get_supported_geom_rendering
316 // Access: Published, Virtual
317 // Description: Returns the union of Geom::GeomRendering values that
318 // this particular GSG can support directly. If a Geom
319 // needs to be rendered that requires some additional
320 // properties, the StandardMunger and/or the
321 // CullableObject will convert it as needed.
322 //
323 // This method is declared virtual solely so that it can
324 // be queried from cullableObject.cxx.
325 ////////////////////////////////////////////////////////////////////
328  return _supported_geom_rendering;
329 }
330 
331 ////////////////////////////////////////////////////////////////////
332 // Function: GraphicsStateGuardian::get_supports_cg_profile
333 // Access: Published, Virtual
334 // Description: Returns true if this particular GSG supports the
335 // specified Cg Shader Profile.
336 ////////////////////////////////////////////////////////////////////
338 get_supports_cg_profile(const string &name) const {
339  return false;
340 }
341 
342 ////////////////////////////////////////////////////////////////////
343 // Function: GraphicsStateGuardian::set_coordinate_system
344 // Access: Published
345 // Description: Changes the coordinate system in effect on this
346 // particular gsg. This is also called the "external"
347 // coordinate system, since it is the coordinate system
348 // used by the scene graph, external to to GSG.
349 //
350 // Normally, this will be the default coordinate system,
351 // but it might be set differently at runtime. It will
352 // automatically be copied from the current lens's
353 // coordinate system as each DisplayRegion is rendered.
354 ////////////////////////////////////////////////////////////////////
356 set_coordinate_system(CoordinateSystem cs) {
357  if (cs == CS_default) {
358  cs = get_default_coordinate_system();
359  }
360  if (_coordinate_system == cs) {
361  return;
362  }
363  _coordinate_system = cs;
364 
365  // Changing the external coordinate system changes the cs_transform.
366  if (_internal_coordinate_system == CS_default ||
367  _internal_coordinate_system == _coordinate_system) {
368  _cs_transform = TransformState::make_identity();
369  _inv_cs_transform = TransformState::make_identity();
370 
371  } else {
372  _cs_transform =
373  TransformState::make_mat
374  (LMatrix4::convert_mat(_coordinate_system,
375  _internal_coordinate_system));
376  _inv_cs_transform =
377  TransformState::make_mat
378  (LMatrix4::convert_mat(_internal_coordinate_system,
379  _coordinate_system));
380  }
381 }
382 
383 ////////////////////////////////////////////////////////////////////
384 // Function: GraphicsStateGuardian::get_internal_coordinate_system
385 // Access: Published, Virtual
386 // Description: Returns the coordinate system used internally by the
387 // GSG. This may be the same as the external coordinate
388 // system reported by get_coordinate_system(), or it may
389 // be something different.
390 //
391 // In any case, vertices that have been transformed
392 // before being handed to the GSG (that is, vertices
393 // with a contents value of C_clip_point) will be
394 // expected to be in this coordinate system.
395 ////////////////////////////////////////////////////////////////////
396 CoordinateSystem GraphicsStateGuardian::
398  return _internal_coordinate_system;
399 }
400 
401 ////////////////////////////////////////////////////////////////////
402 // Function: GraphicsStateGuardian::get_prepared_objects
403 // Access: Public, Virtual
404 // Description: Returns the set of texture and geom objects that have
405 // been prepared with this GSG (and possibly other GSG's
406 // that share objects).
407 ////////////////////////////////////////////////////////////////////
410  return _prepared_objects;
411 }
412 
413 ////////////////////////////////////////////////////////////////////
414 // Function: GraphicsStateGuardian::set_gamma
415 // Access: Published, Virtual
416 // Description: Set gamma. Returns true on success.
417 ////////////////////////////////////////////////////////////////////
419 set_gamma(PN_stdfloat gamma) {
420  _gamma = gamma;
421 
422  return false;
423 }
424 
425 ////////////////////////////////////////////////////////////////////
426 // Function: GraphicsStateGuardian::get_gamma
427 // Access: Published
428 // Description: Get the current gamma setting.
429 ////////////////////////////////////////////////////////////////////
430 PN_stdfloat GraphicsStateGuardian::
431 get_gamma(PN_stdfloat gamma) {
432  return _gamma;
433 }
434 
435 ////////////////////////////////////////////////////////////////////
436 // Function: GraphicsStateGuardian::restore_gamma
437 // Access: Published, Virtual
438 // Description: Restore original gamma setting.
439 ////////////////////////////////////////////////////////////////////
442 }
443 
444 ////////////////////////////////////////////////////////////////////
445 // Function: GraphicsStateGuardian::traverse_prepared_textures
446 // Access: Public
447 // Description: Calls the indicated function on all
448 // currently-prepared textures, or until the callback
449 // function returns false.
450 ////////////////////////////////////////////////////////////////////
452 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
453  void *callback_arg) {
454  ReMutexHolder holder(_prepared_objects->_lock);
455  PreparedGraphicsObjects::Textures::const_iterator ti;
456  for (ti = _prepared_objects->_prepared_textures.begin();
457  ti != _prepared_objects->_prepared_textures.end();
458  ++ti) {
459  bool result = (*func)(*ti, callback_arg);
460  if (!result) {
461  return;
462  }
463  }
464 }
465 
466 #ifndef NDEBUG
467 ////////////////////////////////////////////////////////////////////
468 // Function: GraphicsStateGuardian::set_flash_texture
469 // Access: Published
470 // Description: Sets the "flash texture". This is a debug feature;
471 // when enabled, the specified texture will begin
472 // flashing in the scene, helping you to find it
473 // visually.
474 //
475 // The texture also flashes with a color code: blue for
476 // mipmap level 0, yellow for mipmap level 1, and red
477 // for mipmap level 2 or higher (even for textures that
478 // don't have mipmaps). This gives you an idea of the
479 // choice of the texture size. If it is blue, the
480 // texture is being drawn the proper size or magnified;
481 // if it is yellow, it is being minified a little bit;
482 // and if it red, it is being minified considerably. If
483 // you see a red texture when you are right in front of
484 // it, you should consider reducing the size of the
485 // texture to avoid wasting texture memory.
486 //
487 // Not all rendering backends support the flash_texture
488 // feature. Presently, it is only supported by OpenGL.
489 ////////////////////////////////////////////////////////////////////
492  _flash_texture = tex;
493 }
494 #endif // NDEBUG
495 
496 #ifndef NDEBUG
497 ////////////////////////////////////////////////////////////////////
498 // Function: GraphicsStateGuardian::clear_flash_texture
499 // Access: Published
500 // Description: Resets the "flash texture", so that no textures will
501 // flash. See set_flash_texture().
502 ////////////////////////////////////////////////////////////////////
505  _flash_texture = NULL;
506 }
507 #endif // NDEBUG
508 
509 #ifndef NDEBUG
510 ////////////////////////////////////////////////////////////////////
511 // Function: GraphicsStateGuardian::get_flash_texture
512 // Access: Published
513 // Description: Returns the current "flash texture", if any, or NULL
514 // if none. See set_flash_texture().
515 ////////////////////////////////////////////////////////////////////
518  return _flash_texture;
519 }
520 #endif // NDEBUG
521 
522 ////////////////////////////////////////////////////////////////////
523 // Function: GraphicsStateGuardian::set_scene
524 // Access: Published
525 // Description: Sets the SceneSetup object that indicates the initial
526 // camera position, etc. This must be called before
527 // traversal begins. Returns true if the scene is
528 // acceptable, false if something's wrong. This should
529 // be called in the draw thread only.
530 ////////////////////////////////////////////////////////////////////
532 set_scene(SceneSetup *scene_setup) {
533  _scene_setup = scene_setup;
534  _current_lens = scene_setup->get_lens();
535  if (_current_lens == (Lens *)NULL) {
536  return false;
537  }
538 
539  set_coordinate_system(_current_lens->get_coordinate_system());
540 
541  _projection_mat = calc_projection_mat(_current_lens);
542  if (_projection_mat == 0) {
543  return false;
544  }
545  _projection_mat_inv = _projection_mat->get_inverse();
546  return prepare_lens();
547 }
548 
549 ////////////////////////////////////////////////////////////////////
550 // Function: GraphicsStateGuardian::get_scene
551 // Access: Published, Virtual
552 // Description: Returns the current SceneSetup object.
553 ////////////////////////////////////////////////////////////////////
555 get_scene() const {
556  return _scene_setup;
557 }
558 
559 ////////////////////////////////////////////////////////////////////
560 // Function: GraphicsStateGuardian::prepare_texture
561 // Access: Public, Virtual
562 // Description: Creates whatever structures the GSG requires to
563 // represent the texture internally, and returns a
564 // newly-allocated TextureContext object with this data.
565 // It is the responsibility of the calling function to
566 // later call release_texture() with this same pointer
567 // (which will also delete the pointer).
568 //
569 // This function should not be called directly to
570 // prepare a texture. Instead, call Texture::prepare().
571 ////////////////////////////////////////////////////////////////////
574  return (TextureContext *)NULL;
575 }
576 
577 ////////////////////////////////////////////////////////////////////
578 // Function: GraphicsStateGuardian::update_texture
579 // Access: Public, Virtual
580 // Description: Ensures that the current Texture data is refreshed
581 // onto the GSG. This means updating the texture
582 // properties and/or re-uploading the texture image, if
583 // necessary. This should only be called within the
584 // draw thread.
585 //
586 // If force is true, this function will not return until
587 // the texture has been fully uploaded. If force is
588 // false, the function may choose to upload a simple
589 // version of the texture instead, if the texture is not
590 // fully resident (and if get_incomplete_render() is
591 // true).
592 ////////////////////////////////////////////////////////////////////
595  return true;
596 }
597 
598 ////////////////////////////////////////////////////////////////////
599 // Function: GraphicsStateGuardian::release_texture
600 // Access: Public, Virtual
601 // Description: Frees the resources previously allocated via a call
602 // to prepare_texture(), including deleting the
603 // TextureContext itself, if it is non-NULL.
604 ////////////////////////////////////////////////////////////////////
607 }
608 
609 ////////////////////////////////////////////////////////////////////
610 // Function: GraphicsStateGuardian::extract_texture_data
611 // Access: Public, Virtual
612 // Description: This method should only be called by the
613 // GraphicsEngine. Do not call it directly; call
614 // GraphicsEngine::extract_texture_data() instead.
615 //
616 // This method will be called in the draw thread to
617 // download the texture memory's image into its
618 // ram_image value. It returns true on success, false
619 // otherwise.
620 ////////////////////////////////////////////////////////////////////
623  return false;
624 }
625 
626 ////////////////////////////////////////////////////////////////////
627 // Function: GraphicsStateGuardian::prepare_sampler
628 // Access: Public, Virtual
629 // Description: Creates whatever structures the GSG requires to
630 // represent the sampler internally, and returns a
631 // newly-allocated SamplerContext object with this data.
632 // It is the responsibility of the calling function to
633 // later call release_sampler() with this same pointer
634 // (which will also delete the pointer).
635 //
636 // This function should not be called directly to
637 // prepare a sampler. Instead, call Texture::prepare().
638 ////////////////////////////////////////////////////////////////////
640 prepare_sampler(const SamplerState &sampler) {
641  return (SamplerContext *)NULL;
642 }
643 
644 ////////////////////////////////////////////////////////////////////
645 // Function: GraphicsStateGuardian::release_sampler
646 // Access: Public, Virtual
647 // Description: Frees the resources previously allocated via a call
648 // to prepare_sampler(), including deleting the
649 // SamplerContext itself, if it is non-NULL.
650 ////////////////////////////////////////////////////////////////////
653 }
654 
655 ////////////////////////////////////////////////////////////////////
656 // Function: GraphicsStateGuardian::prepare_geom
657 // Access: Public, Virtual
658 // Description: Prepares the indicated Geom for retained-mode
659 // rendering, by creating whatever structures are
660 // necessary in the GSG (for instance, vertex buffers).
661 // Returns the newly-allocated GeomContext that can be
662 // used to render the geom.
663 ////////////////////////////////////////////////////////////////////
666  return (GeomContext *)NULL;
667 }
668 
669 ////////////////////////////////////////////////////////////////////
670 // Function: GraphicsStateGuardian::release_geom
671 // Access: Public, Virtual
672 // Description: Frees the resources previously allocated via a call
673 // to prepare_geom(), including deleting the GeomContext
674 // itself, if it is non-NULL.
675 //
676 // This function should not be called directly to
677 // prepare a Geom. Instead, call Geom::prepare().
678 ////////////////////////////////////////////////////////////////////
681 }
682 
683 ////////////////////////////////////////////////////////////////////
684 // Function: GraphicsStateGuardian::prepare_shader
685 // Access: Public, Virtual
686 // Description: Compile a vertex/fragment shader body.
687 ////////////////////////////////////////////////////////////////////
690  return (ShaderContext *)NULL;
691 }
692 
693 ////////////////////////////////////////////////////////////////////
694 // Function: GraphicsStateGuardian::release_shader
695 // Access: Public, Virtual
696 // Description: Releases the resources allocated by prepare_shader
697 ////////////////////////////////////////////////////////////////////
700 }
701 
702 ////////////////////////////////////////////////////////////////////
703 // Function: GraphicsStateGuardian::prepare_vertex_buffer
704 // Access: Public, Virtual
705 // Description: Prepares the indicated buffer for retained-mode
706 // rendering.
707 ////////////////////////////////////////////////////////////////////
710  return (VertexBufferContext *)NULL;
711 }
712 
713 ////////////////////////////////////////////////////////////////////
714 // Function: GraphicsStateGuardian::release_vertex_buffer
715 // Access: Public, Virtual
716 // Description: Frees the resources previously allocated via a call
717 // to prepare_data(), including deleting the
718 // VertexBufferContext itself, if necessary.
719 ////////////////////////////////////////////////////////////////////
722 }
723 
724 ////////////////////////////////////////////////////////////////////
725 // Function: GraphicsStateGuardian::prepare_index_buffer
726 // Access: Public, Virtual
727 // Description: Prepares the indicated buffer for retained-mode
728 // rendering.
729 ////////////////////////////////////////////////////////////////////
732  return (IndexBufferContext *)NULL;
733 }
734 
735 ////////////////////////////////////////////////////////////////////
736 // Function: GraphicsStateGuardian::release_index_buffer
737 // Access: Public, Virtual
738 // Description: Frees the resources previously allocated via a call
739 // to prepare_data(), including deleting the
740 // IndexBufferContext itself, if necessary.
741 ////////////////////////////////////////////////////////////////////
744 }
745 
746 ////////////////////////////////////////////////////////////////////
747 // Function: GraphicsStateGuardian::begin_occlusion_query
748 // Access: Public, Virtual
749 // Description: Begins a new occlusion query. After this call, you
750 // may call begin_draw_primitives() and
751 // draw_triangles()/draw_whatever() repeatedly.
752 // Eventually, you should call end_occlusion_query()
753 // before the end of the frame; that will return a new
754 // OcclusionQueryContext object that will tell you how
755 // many pixels represented by the bracketed geometry
756 // passed the depth test.
757 //
758 // It is not valid to call begin_occlusion_query()
759 // between another begin_occlusion_query()
760 // .. end_occlusion_query() sequence.
761 ////////////////////////////////////////////////////////////////////
764  nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
765 }
766 
767 ////////////////////////////////////////////////////////////////////
768 // Function: GraphicsStateGuardian::end_occlusion_query
769 // Access: Public, Virtual
770 // Description: Ends a previous call to begin_occlusion_query().
771 // This call returns the OcclusionQueryContext object
772 // that will (eventually) report the number of pixels
773 // that passed the depth test between the call to
774 // begin_occlusion_query() and end_occlusion_query().
775 ////////////////////////////////////////////////////////////////////
777 end_occlusion_query() {
778  nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
779  PT(OcclusionQueryContext) result = _current_occlusion_query;
780  _current_occlusion_query = NULL;
781  return result;
782 }
783 
784 ////////////////////////////////////////////////////////////////////
785 // Function: GraphicsStateGuardian::issue_timer_query
786 // Access: Public, Virtual
787 // Description: Adds a timer query to the command stream, associated
788 // with the given PStats collector index.
789 ////////////////////////////////////////////////////////////////////
791 issue_timer_query(int pstats_index) {
792  return NULL;
793 }
794 
795 ////////////////////////////////////////////////////////////////////
796 // Function: GraphicsStateGuardian::dispatch_compute
797 // Access: Public, Virtual
798 // Description: Dispatches a currently bound compute shader using
799 // the given work group counts.
800 ////////////////////////////////////////////////////////////////////
802 dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) {
803  nassertv(false /* Compute shaders not supported by GSG */);
804 }
805 
806 ////////////////////////////////////////////////////////////////////
807 // Function: GraphicsStateGuardian::get_geom_munger
808 // Access: Public, Virtual
809 // Description: Looks up or creates a GeomMunger object to munge
810 // vertices appropriate to this GSG for the indicated
811 // state.
812 ////////////////////////////////////////////////////////////////////
814 get_geom_munger(const RenderState *state, Thread *current_thread) {
815  // We can cast the RenderState to a non-const object because we are
816  // only updating a cache within the RenderState, not really changing
817  // any of its properties.
818  RenderState *nc_state = ((RenderState *)state);
819 
820  // Before we even look up the map, see if the _last_mi value points
821  // to this GSG. This is likely because we tend to visit the same
822  // state multiple times during a frame. Also, this might well be
823  // the only GSG in the world anyway.
824  if (!nc_state->_mungers.empty()) {
825  RenderState::Mungers::const_iterator mi = nc_state->_last_mi;
826  if (!(*mi).first.was_deleted() && (*mi).first == this) {
827  if ((*mi).second->is_registered()) {
828  return (*mi).second;
829  }
830  }
831  }
832 
833  // Nope, we have to look it up in the map.
834  RenderState::Mungers::iterator mi = nc_state->_mungers.find(this);
835  if (mi != nc_state->_mungers.end() && !(*mi).first.was_deleted()) {
836  if ((*mi).second->is_registered()) {
837  nc_state->_last_mi = mi;
838  return (*mi).second;
839  }
840  // This GeomMunger is no longer registered. Remove it from the
841  // map.
842  nc_state->_mungers.erase(mi);
843  }
844 
845  // Nothing in the map; create a new entry.
846  PT(GeomMunger) munger = make_geom_munger(nc_state, current_thread);
847  nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger);
848 
849  mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
850  nc_state->_last_mi = mi;
851 
852  return munger;
853 }
854 
855 ////////////////////////////////////////////////////////////////////
856 // Function: GraphicsStateGuardian::make_geom_munger
857 // Access: Public, Virtual
858 // Description: Creates a new GeomMunger object to munge vertices
859 // appropriate to this GSG for the indicated state.
860 ////////////////////////////////////////////////////////////////////
862 make_geom_munger(const RenderState *state, Thread *current_thread) {
863  // The default implementation returns no munger at all, but
864  // presumably, every kind of GSG needs some special munging action,
865  // so real GSG's will override this to return something more
866  // useful.
867  return NULL;
868 }
869 
870 ////////////////////////////////////////////////////////////////////
871 // Function: GraphicsStateGuardian::compute_distance_to
872 // Access: Public, Virtual
873 // Description: This function will compute the distance to the
874 // indicated point, assumed to be in eye coordinates,
875 // from the camera plane. The point is assumed to be
876 // in the GSG's internal coordinate system.
877 ////////////////////////////////////////////////////////////////////
878 PN_stdfloat GraphicsStateGuardian::
879 compute_distance_to(const LPoint3 &point) const {
880  switch (_internal_coordinate_system) {
881  case CS_zup_right:
882  return point[1];
883 
884  case CS_yup_right:
885  return -point[2];
886 
887  case CS_zup_left:
888  return -point[1];
889 
890  case CS_yup_left:
891  return point[2];
892 
893  default:
894  gsg_cat.error()
895  << "Invalid coordinate system in compute_distance_to: "
896  << (int)_internal_coordinate_system << "\n";
897  return 0.0f;
898  }
899 }
900 
901 ////////////////////////////////////////////////////////////////////
902 // Function: GraphicsStateGuardian::fetch_specified_value
903 // Access: Public
904 // Description: The gsg contains a large number of useful matrices:
905 //
906 // * the world transform,
907 // * the modelview matrix,
908 // * the cs_transform,
909 // * etc, etc.
910 //
911 // A shader can request any of these values, and
912 // furthermore, it can request that various compositions,
913 // inverses, and transposes be performed. The
914 // ShaderMatSpec is a data structure indicating what
915 // datum is desired and what conversions to perform.
916 // This routine, fetch_specified_value, is responsible for
917 // doing the actual retrieval and conversions.
918 //
919 // Some values, like the following, aren't matrices:
920 //
921 // * window size
922 // * texture coordinates of card center
923 //
924 // This routine can fetch these values as well, by
925 // shoehorning them into a matrix. In this way, we avoid
926 // the need for a separate routine to fetch these values.
927 //
928 // The "altered" bits indicate what parts of the
929 // state_and_transform have changed since the last
930 // time this particular ShaderMatSpec was evaluated.
931 // This may allow data to be cached and not reevaluated.
932 //
933 ////////////////////////////////////////////////////////////////////
936  LVecBase3 v;
937 
938  if (altered & spec._dep[0]) {
939  const LMatrix4 *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0], spec._index);
940  if (t != &spec._cache[0]) {
941  spec._cache[0] = *t;
942  }
943  }
944  if (altered & spec._dep[1]) {
945  const LMatrix4 *t = fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1], spec._index);
946  if (t != &spec._cache[1]) {
947  spec._cache[1] = *t;
948  }
949  }
950 
951  switch(spec._func) {
952  case Shader::SMF_compose:
953  spec._value.multiply(spec._cache[0], spec._cache[1]);
954  return &spec._value;
955  case Shader::SMF_transform_dlight:
956  spec._value = spec._cache[0];
957  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2));
958  v.normalize();
959  spec._value.set_row(2, v);
960  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
961  v.normalize();
962  spec._value.set_row(3, v);
963  return &spec._value;
964  case Shader::SMF_transform_plight:
965  spec._value = spec._cache[0];
966  spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
967  return &spec._value;
968  case Shader::SMF_transform_slight:
969  spec._value = spec._cache[0];
970  spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
971  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
972  v.normalize();
973  spec._value.set_row(3, v);
974  return &spec._value;
975  case Shader::SMF_first:
976  return &spec._cache[0];
977  default:
978  // should never get here
979  spec._value = LMatrix4::ident_mat();
980  return &spec._value;
981  }
982 }
983 
984 ////////////////////////////////////////////////////////////////////
985 // Function: GraphicsStateGuardian::fetch_specified_part
986 // Access: Public
987 // Description: See fetch_specified_value
988 ////////////////////////////////////////////////////////////////////
990 fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
991  LMatrix4 &t, int index) {
992  switch (part) {
993  case Shader::SMO_identity: {
994  return &LMatrix4::ident_mat();
995  }
996  case Shader::SMO_window_size: {
997  t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
998  _current_display_region->get_pixel_height(),
999  0.0);
1000  return &t;
1001  }
1002  case Shader::SMO_pixel_size: {
1003  t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
1004  _current_display_region->get_pixel_height(),
1005  0.0);
1006  return &t;
1007  }
1008  case Shader::SMO_frame_time: {
1009  PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
1010  t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
1011  return &t;
1012  }
1013  case Shader::SMO_frame_delta: {
1014  PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
1015  t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
1016  return &t;
1017  }
1018  case Shader::SMO_texpad_x: {
1019  Texture *tex = _target_shader->get_shader_input_texture(name);
1020  nassertr(tex != 0, &LMatrix4::zeros_mat());
1021  int sx = tex->get_x_size() - tex->get_pad_x_size();
1022  int sy = tex->get_y_size() - tex->get_pad_y_size();
1023  int sz = tex->get_z_size() - tex->get_pad_z_size();
1024  double cx = (sx * 0.5) / tex->get_x_size();
1025  double cy = (sy * 0.5) / tex->get_y_size();
1026  double cz = (sz * 0.5) / tex->get_z_size();
1027  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
1028  return &t;
1029  }
1030  case Shader::SMO_texpix_x: {
1031  Texture *tex = _target_shader->get_shader_input_texture(name);
1032  nassertr(tex != 0, &LMatrix4::zeros_mat());
1033  double px = 1.0 / tex->get_x_size();
1034  double py = 1.0 / tex->get_y_size();
1035  double pz = 1.0 / tex->get_z_size();
1036  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
1037  return &t;
1038  }
1039  case Shader::SMO_attr_material: {
1040  const MaterialAttrib *target_material = (const MaterialAttrib *)
1041  _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
1042  // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
1043  if (target_material->is_off()) {
1044  t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
1045  return &t;
1046  }
1047  Material *m = target_material->get_material();
1048  LVecBase4 const &amb = m->get_ambient();
1049  LVecBase4 const &dif = m->get_diffuse();
1050  LVecBase4 const &emm = m->get_emission();
1051  LVecBase4 spc = m->get_specular();
1052  spc[3] = m->get_shininess();
1053  t = LMatrix4(amb[0],amb[1],amb[2],amb[3],
1054  dif[0],dif[1],dif[2],dif[3],
1055  emm[0],emm[1],emm[2],emm[3],
1056  spc[0],spc[1],spc[2],spc[3]);
1057  return &t;
1058  }
1059  case Shader::SMO_attr_color: {
1060  const ColorAttrib *target_color = (const ColorAttrib *)
1061  _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
1062  if (target_color->get_color_type() != ColorAttrib::T_flat) {
1063  return &LMatrix4::ones_mat();
1064  }
1065  LVecBase4 c = target_color->get_color();
1066  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
1067  return &t;
1068  }
1069  case Shader::SMO_attr_colorscale: {
1070  const ColorScaleAttrib *target_color = (const ColorScaleAttrib *)
1071  _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
1072  if (target_color->is_identity()) {
1073  return &LMatrix4::ones_mat();
1074  }
1075  LVecBase4 cs = target_color->get_scale();
1076  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]);
1077  return &t;
1078  }
1079  case Shader::SMO_attr_fog: {
1080  const FogAttrib *target_fog = (const FogAttrib *)
1081  _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1082  Fog *fog = target_fog->get_fog();
1083  if (fog == (Fog*) NULL) {
1084  return &LMatrix4::ones_mat();
1085  }
1086  PN_stdfloat start, end;
1087  fog->get_linear_range(start, end);
1088  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,fog->get_exp_density(),start,end,1.0f/(end-start));
1089  return &t;
1090  }
1091  case Shader::SMO_attr_fogcolor: {
1092  const FogAttrib *target_fog = (const FogAttrib *)
1093  _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1094  Fog *fog = target_fog->get_fog();
1095  if (fog == (Fog*) NULL) {
1096  return &LMatrix4::ones_mat();
1097  }
1098  LVecBase4 c = fog->get_color();
1099  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
1100  return &t;
1101  }
1102  case Shader::SMO_alight_x: {
1103  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1104  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1105  AmbientLight *lt;
1106  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1107  LColor const &c = lt->get_color();
1108  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
1109  return &t;
1110  }
1111  case Shader::SMO_satten_x: {
1112  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1113  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1114  Spotlight *lt;
1115  DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
1116  LVecBase3 const &a = lt->get_attenuation();
1117  PN_stdfloat x = lt->get_exponent();
1118  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x);
1119  return &t;
1120  }
1121  case Shader::SMO_dlight_x: {
1122  // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE
1123  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1124  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1125  DirectionalLight *lt;
1126  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1127  LColor const &c = lt->get_color();
1128  LColor const &s = lt->get_specular_color();
1129  t = np.get_net_transform()->get_mat() *
1130  get_scene()->get_world_transform()->get_mat();
1131  LVecBase3 d = -(t.xform_vec(lt->get_direction()));
1132  d.normalize();
1133  LVecBase3 h = d + LVecBase3(0,-1,0);
1134  h.normalize();
1135  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);
1136  return &t;
1137  }
1138  case Shader::SMO_plight_x: {
1139  // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION
1140  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1141  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1142  PointLight *lt;
1143  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1144  LColor const &c = lt->get_color();
1145  LColor const &s = lt->get_specular_color();
1146  t = np.get_net_transform()->get_mat() *
1147  get_scene()->get_world_transform()->get_mat();
1148  LVecBase3 p = (t.xform_point(lt->get_point()));
1149  LVecBase3 a = lt->get_attenuation();
1150  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);
1151  return &t;
1152  }
1153  case Shader::SMO_slight_x: {
1154  // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION
1155  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1156  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1157  Spotlight *lt;
1158  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1159  Lens *lens = lt->get_lens();
1160  nassertr(lens != (Lens *)NULL, &LMatrix4::zeros_mat());
1161  LColor const &c = lt->get_color();
1162  LColor const &s = lt->get_specular_color();
1163  PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
1164  t = np.get_net_transform()->get_mat() *
1165  get_scene()->get_world_transform()->get_mat();
1166  LVecBase3 p = t.xform_point(lens->get_nodal_point());
1167  LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
1168  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);
1169  return &t;
1170  }
1171  case Shader::SMO_light_ambient: {
1172  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1173  const LightAttrib *target_light = (const LightAttrib *)
1174  _target_rs->get_attrib_def(LightAttrib::get_class_slot());
1175 
1176  int num_on_lights = target_light->get_num_on_lights();
1177  if (num_on_lights == 0) {
1178  // There are no lights at all. This means, to follow the fixed-
1179  // function model, we pretend there is an all-white ambient light.
1180  t.set_row(3, LVecBase4(1, 1, 1, 1));
1181  } else {
1182  for (int li = 0; li < num_on_lights; li++) {
1183  NodePath light = target_light->get_on_light(li);
1184  nassertr(!light.is_empty(), &LMatrix4::zeros_mat());
1185  Light *light_obj = light.node()->as_light();
1186  nassertr(light_obj != (Light *)NULL, &LMatrix4::zeros_mat());
1187 
1188  if (light_obj->get_type() == AmbientLight::get_class_type()) {
1189  cur_ambient_light += light_obj->get_color();
1190  }
1191  }
1192  t.set_row(3, cur_ambient_light);
1193  }
1194  return &t;
1195  }
1196  case Shader::SMO_texmat_x: {
1197  const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
1198  const TextureAttrib *ta = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
1199  int stagenr = atoi(name->get_name().c_str());
1200  if (stagenr >= ta->get_num_on_stages()) {
1201  return &LMatrix4::ident_mat();
1202  }
1203  return &tma->get_mat(ta->get_on_stage(stagenr));
1204  }
1205  case Shader::SMO_plane_x: {
1206  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1207  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1208  nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
1209  LPlane p = DCAST(PlaneNode, np.node())->get_plane();
1210  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
1211  return &t;
1212  }
1213  case Shader::SMO_clipplane_x: {
1214  const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
1215  int planenr = atoi(name->get_name().c_str());
1216  if (planenr >= cpa->get_num_on_planes()) {
1217  return &LMatrix4::zeros_mat();
1218  }
1219  const NodePath &np = cpa->get_on_plane(planenr);
1220  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1221  nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
1222  LPlane p (DCAST(PlaneNode, np.node())->get_plane());
1223  p.xform(np.get_net_transform()->get_mat()); // World-space
1224  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
1225  return &t;
1226  }
1227  case Shader::SMO_apiview_clipplane_i: {
1228  const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
1229  if (index >= cpa->get_num_on_planes()) {
1230  return &LMatrix4::zeros_mat();
1231  }
1232 
1233  const NodePath &plane = cpa->get_on_plane(index);
1234  nassertr(!plane.is_empty(), &LMatrix4::zeros_mat());
1235  const PlaneNode *plane_node;
1236  DCAST_INTO_R(plane_node, plane.node(), &LMatrix4::zeros_mat());
1237 
1238  CPT(TransformState) transform =
1239  get_scene()->get_cs_world_transform()->compose(
1240  plane.get_transform(_scene_setup->get_scene_root().get_parent()));
1241 
1242  LPlane xformed_plane = plane_node->get_plane() * transform->get_mat();
1243  t.set_row(3, xformed_plane);
1244  return &t;
1245  }
1246  case Shader::SMO_mat_constant_x: {
1247  return &_target_shader->get_shader_input_matrix(name, t);
1248  }
1249  case Shader::SMO_vec_constant_x: {
1250  const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
1251  const PN_stdfloat *data = input.get_data();
1252  t = LMatrix4(data[0],data[1],data[2],data[3],
1253  data[0],data[1],data[2],data[3],
1254  data[0],data[1],data[2],data[3],
1255  data[0],data[1],data[2],data[3]);
1256  return &t;
1257  }
1258  case Shader::SMO_world_to_view: {
1259  return &(get_scene()->get_world_transform()->get_mat());
1260  break;
1261  }
1262  case Shader::SMO_view_to_world: {
1263  return &(get_scene()->get_camera_transform()->get_mat());
1264  }
1265  case Shader::SMO_model_to_view: {
1266  return &(get_external_transform()->get_mat());
1267  }
1268  case Shader::SMO_model_to_apiview: {
1269  return &(get_internal_transform()->get_mat());
1270  }
1271  case Shader::SMO_view_to_model: {
1272  t = get_external_transform()->get_inverse()->get_mat();
1273  return &t;
1274  }
1275  case Shader::SMO_apiview_to_model: {
1276  t = get_internal_transform()->get_inverse()->get_mat();
1277  return &t;
1278  }
1279  case Shader::SMO_apiview_to_view: {
1280  return &(_inv_cs_transform->get_mat());
1281  }
1282  case Shader::SMO_view_to_apiview: {
1283  return &(_cs_transform->get_mat());
1284  }
1285  case Shader::SMO_clip_to_view: {
1286  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1287  return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
1288  } else {
1289  t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
1290  LMatrix4::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
1291  return &t;
1292  }
1293  }
1294  case Shader::SMO_view_to_clip: {
1295  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1296  return &(_current_lens->get_projection_mat(_current_stereo_channel));
1297  } else {
1298  t = LMatrix4::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
1299  _current_lens->get_projection_mat(_current_stereo_channel);
1300  return &t;
1301  }
1302  }
1303  case Shader::SMO_apiclip_to_view: {
1304  t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
1305  return &t;
1306  }
1307  case Shader::SMO_view_to_apiclip: {
1308  t = _cs_transform->get_mat() * _projection_mat->get_mat();
1309  return &t;
1310  }
1311  case Shader::SMO_apiclip_to_apiview: {
1312  return &(_projection_mat_inv->get_mat());
1313  }
1314  case Shader::SMO_apiview_to_apiclip: {
1315  return &(_projection_mat->get_mat());
1316  }
1317  case Shader::SMO_view_x_to_view: {
1318  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1319  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1320  t = np.get_net_transform()->get_mat() *
1321  get_scene()->get_world_transform()->get_mat();
1322  return &t;
1323  }
1324  case Shader::SMO_view_to_view_x: {
1325  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1326  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1327  t = get_scene()->get_camera_transform()->get_mat() *
1328  np.get_net_transform()->get_inverse()->get_mat();
1329  return &t;
1330  }
1331  case Shader::SMO_apiview_x_to_view: {
1332  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1333  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1334  t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
1335  np.get_net_transform()->get_mat() *
1336  get_scene()->get_world_transform()->get_mat();
1337  return &t;
1338  }
1339  case Shader::SMO_view_to_apiview_x: {
1340  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1341  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1342  t = (get_scene()->get_camera_transform()->get_mat() *
1343  np.get_net_transform()->get_inverse()->get_mat() *
1344  LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
1345  return &t;
1346  }
1347  case Shader::SMO_clip_x_to_view: {
1348  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1349  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1350  nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
1351  Lens *lens = DCAST(LensNode, np.node())->get_lens();
1352  t = lens->get_projection_mat_inv(_current_stereo_channel) *
1353  LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
1354  np.get_net_transform()->get_mat() *
1355  get_scene()->get_world_transform()->get_mat();
1356  return &t;
1357  }
1358  case Shader::SMO_view_to_clip_x: {
1359  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1360  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1361  nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
1362  Lens *lens = DCAST(LensNode, np.node())->get_lens();
1363  t = get_scene()->get_camera_transform()->get_mat() *
1364  np.get_net_transform()->get_inverse()->get_mat() *
1365  LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
1366  lens->get_projection_mat(_current_stereo_channel);
1367  return &t;
1368  }
1369  case Shader::SMO_apiclip_x_to_view: {
1370  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1371  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1372  nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
1373  Lens *lens = DCAST(LensNode, np.node())->get_lens();
1374  t = calc_projection_mat(lens)->get_inverse()->get_mat() *
1375  get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
1376  np.get_net_transform()->get_mat() *
1377  get_scene()->get_world_transform()->get_mat();
1378  return &t;
1379  }
1380  case Shader::SMO_view_to_apiclip_x: {
1381  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1382  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1383  nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
1384  Lens *lens = DCAST(LensNode, np.node())->get_lens();
1385  t = get_scene()->get_camera_transform()->get_mat() *
1386  np.get_net_transform()->get_inverse()->get_mat() *
1387  get_cs_transform_for(lens->get_coordinate_system())->get_mat() *
1388  calc_projection_mat(lens)->get_mat();
1389  return &t;
1390  }
1391  case Shader::SMO_vec_constant_x_attrib: {
1392  // This system is not ideal. It will be improved in the future.
1393  if (_target_shader->has_shader_input(name)) {
1394  // There is an input specifying precisely this whole thing, with
1395  // dot and all. Support this, even if only for backward compatibility.
1396  const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
1397  t = LMatrix4(data[0],data[1],data[2],data[3],
1398  data[0],data[1],data[2],data[3],
1399  data[0],data[1],data[2],data[3],
1400  data[0],data[1],data[2],data[3]);
1401  return &t;
1402  }
1403 
1404  const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
1405  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1406 
1407  CPT_InternalName attrib = name->get_basename();
1408 
1409  static const CPT_InternalName IN_ambient("ambient");
1410  static const CPT_InternalName IN_diffuse("diffuse");
1411  static const CPT_InternalName IN_specular("specular");
1412  static const CPT_InternalName IN_position("position");
1413  static const CPT_InternalName IN_halfVector("halfVector");
1414  static const CPT_InternalName IN_spotDirection("spotDirection");
1415  static const CPT_InternalName IN_spotCutoff("spotCutoff");
1416  static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
1417  static const CPT_InternalName IN_spotExponent("spotExponent");
1418  static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
1419  static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
1420  static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
1421 
1422  if (attrib == IN_ambient) {
1423  Light *light = np.node()->as_light();
1424  nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
1425  if (np.node()->is_of_type(AmbientLight::get_class_type())) {
1426  LColor c = light->get_color();
1427  c.componentwise_mult(_light_color_scale);
1428  t.set_row(3, c);
1429  } else {
1430  // Non-ambient lights don't currently have an ambient color in Panda3D.
1431  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1432  }
1433  return &t;
1434 
1435  } else if (attrib == IN_diffuse) {
1436  Light *light = np.node()->as_light();
1437  nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
1438  if (np.node()->is_of_type(AmbientLight::get_class_type())) {
1439  // Ambient light has no diffuse color.
1440  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1441  } else {
1442  LColor c = light->get_color();
1443  c.componentwise_mult(_light_color_scale);
1444  t.set_row(3, c);
1445  }
1446  return &t;
1447 
1448  } else if (attrib == IN_specular) {
1449  Light *light = np.node()->as_light();
1450  nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
1451  t.set_row(3, light->get_specular_color());
1452  return &t;
1453 
1454  } else if (attrib == IN_position) {
1455  if (np.node()->is_of_type(AmbientLight::get_class_type())) {
1456  // Ambient light has no position.
1457  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
1458  return &t;
1459  } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
1460  DirectionalLight *light;
1461  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1462 
1463  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1464  LVector3 dir = -(light->get_direction() * transform->get_mat());
1465  dir *= get_scene()->get_cs_world_transform()->get_mat();
1466  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
1467  return &t;
1468  } else {
1469  LightLensNode *light;
1470  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1471  Lens *lens = light->get_lens();
1472  nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
1473 
1474  CPT(TransformState) transform =
1475  get_scene()->get_cs_world_transform()->compose(
1476  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1477 
1478  const LMatrix4 &light_mat = transform->get_mat();
1479  LPoint3 pos = lens->get_nodal_point() * light_mat;
1480  t = LMatrix4::translate_mat(pos);
1481  return &t;
1482  }
1483 
1484  } else if (attrib == IN_halfVector) {
1485  if (np.node()->is_of_type(AmbientLight::get_class_type())) {
1486  // Ambient light has no half-vector.
1487  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
1488  return &t;
1489  } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
1490  DirectionalLight *light;
1491  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1492 
1493  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1494  LVector3 dir = -(light->get_direction() * transform->get_mat());
1495  dir *= get_scene()->get_cs_world_transform()->get_mat();
1496  dir.normalize();
1497  dir += LVector3(0, 0, 1);
1498  dir.normalize();
1499  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
1500  return &t;
1501  } else {
1502  LightLensNode *light;
1503  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1504  Lens *lens = light->get_lens();
1505  nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
1506 
1507  CPT(TransformState) transform =
1508  get_scene()->get_cs_world_transform()->compose(
1509  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1510 
1511  const LMatrix4 &light_mat = transform->get_mat();
1512  LPoint3 pos = lens->get_nodal_point() * light_mat;
1513  pos.normalize();
1514  pos += LVector3(0, 0, 1);
1515  pos.normalize();
1516  t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
1517  return &t;
1518  }
1519 
1520  } else if (attrib == IN_spotDirection) {
1521  if (np.node()->is_of_type(AmbientLight::get_class_type())) {
1522  // Ambient light has no spot direction.
1523  t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
1524  return &t;
1525  } else {
1526  LightLensNode *light;
1527  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1528  Lens *lens = light->get_lens();
1529  nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
1530 
1531  CPT(TransformState) transform =
1532  get_scene()->get_cs_world_transform()->compose(
1533  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1534 
1535  const LMatrix4 &light_mat = transform->get_mat();
1536  LVector3 dir = lens->get_view_vector() * light_mat;
1537  t.set_row(3, dir);
1538  return &t;
1539  }
1540 
1541  } else if (attrib == IN_spotCutoff) {
1542  if (np.node()->is_of_type(Spotlight::get_class_type())) {
1543  LightLensNode *light;
1544  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1545  Lens *lens = light->get_lens();
1546  nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
1547 
1548  float cutoff = lens->get_hfov() * 0.5f;
1549  t.set_row(3, LVecBase4(cutoff));
1550  return &t;
1551  } else {
1552  // Other lights have no cut-off.
1553  t.set_row(3, LVecBase4(180));
1554  return &t;
1555  }
1556 
1557  } else if (attrib == IN_spotCosCutoff) {
1558  if (np.node()->is_of_type(Spotlight::get_class_type())) {
1559  LightLensNode *light;
1560  DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
1561  Lens *lens = light->get_lens();
1562  nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
1563 
1564  float cutoff = lens->get_hfov() * 0.5f;
1565  t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
1566  return &t;
1567  } else {
1568  // Other lights have no cut-off.
1569  t.set_row(3, LVecBase4(-1));
1570  return &t;
1571  }
1572  } else if (attrib == IN_spotExponent) {
1573  Light *light = np.node()->as_light();
1574  nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
1575 
1576  t.set_row(3, LVecBase4(light->get_exponent()));
1577  return &t;
1578 
1579  } else if (attrib == IN_constantAttenuation) {
1580  Light *light = np.node()->as_light();
1581  nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
1582 
1583  t.set_row(3, LVecBase4(light->get_attenuation()[0]));
1584  return &t;
1585 
1586  } else if (attrib == IN_linearAttenuation) {
1587  Light *light = np.node()->as_light();
1588  nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
1589 
1590  t.set_row(3, LVecBase4(light->get_attenuation()[1]));
1591  return &t;
1592 
1593  } else if (attrib == IN_quadraticAttenuation) {
1594  Light *light = np.node()->as_light();
1595  nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
1596 
1597  t.set_row(3, LVecBase4(light->get_attenuation()[2]));
1598  return &t;
1599 
1600  } else {
1601  display_cat.error()
1602  << "Shader input requests invalid attribute " << *name
1603  << " from node " << np << "\n";
1604  return &LMatrix4::ident_mat();
1605  }
1606  }
1607  default:
1608  nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
1609  return &LMatrix4::ident_mat();
1610  }
1611 }
1612 
1613 ////////////////////////////////////////////////////////////////////
1614 // Function: GraphicsStateGuardian::fetch_ptr_parameter
1615 // Access: Public
1616 // Description: Return a pointer to struct ShaderPtrData
1617 ////////////////////////////////////////////////////////////////////
1620  return (_target_shader->get_shader_input_ptr(spec._arg));
1621 }
1622 
1623 ////////////////////////////////////////////////////////////////////
1624 // Function: GraphicsStateGuardian::prepare_display_region
1625 // Access: Public, Virtual
1626 // Description: Makes the specified DisplayRegion current. All
1627 // future drawing and clear operations will be
1628 // constrained within the given DisplayRegion.
1629 ////////////////////////////////////////////////////////////////////
1632  _current_display_region = dr->get_object();
1633  _current_stereo_channel = dr->get_stereo_channel();
1634  _current_tex_view_offset = dr->get_tex_view_offset();
1635  _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render();
1636 
1637  _stereo_buffer_mask = ~0;
1638 
1639  Lens::StereoChannel output_channel = dr->get_stereo_channel();
1640  if (dr->get_window()->get_swap_eyes()) {
1641  // Reverse the output channel.
1642  switch (output_channel) {
1643  case Lens::SC_left:
1644  output_channel = Lens::SC_right;
1645  break;
1646 
1647  case Lens::SC_right:
1648  output_channel = Lens::SC_left;
1649  break;
1650 
1651  default:
1652  break;
1653  }
1654  }
1655 
1656  switch (output_channel) {
1657  case Lens::SC_left:
1658  _color_write_mask = dr->get_window()->get_left_eye_color_mask();
1659  if (_current_properties->is_stereo()) {
1660  _stereo_buffer_mask = ~RenderBuffer::T_right;
1661  }
1662  break;
1663 
1664  case Lens::SC_right:
1665  _color_write_mask = dr->get_window()->get_right_eye_color_mask();
1666  if (_current_properties->is_stereo()) {
1667  _stereo_buffer_mask = ~RenderBuffer::T_left;
1668  }
1669  break;
1670 
1671  case Lens::SC_mono:
1672  case Lens::SC_stereo:
1673  _color_write_mask = ColorWriteAttrib::C_all;
1674  }
1675 }
1676 
1677 ////////////////////////////////////////////////////////////////////
1678 // Function: GraphicsStateGuardian::clear_before_callback
1679 // Access: Public, Virtual
1680 // Description: Resets any non-standard graphics state that might
1681 // give a callback apoplexy. Some drivers require that
1682 // the graphics state be restored to neutral before
1683 // performing certain operations. In OpenGL, for
1684 // instance, this closes any open vertex buffers.
1685 ////////////////////////////////////////////////////////////////////
1688 }
1689 
1690 ////////////////////////////////////////////////////////////////////
1691 // Function: GraphicsStateGuardian::clear_state_and_transform
1692 // Access: Public, Virtual
1693 // Description: Forgets the current graphics state and current
1694 // transform, so that the next call to
1695 // set_state_and_transform() will have to reload
1696 // everything. This is a good thing to call when you
1697 // are no longer sure what the graphics state is. This
1698 // should only be called from the draw thread.
1699 ////////////////////////////////////////////////////////////////////
1702  // Re-issue the modelview and projection transforms.
1703  reissue_transforms();
1704 
1705  // Now clear the state flags to unknown.
1706  _state_rs = RenderState::make_empty();
1707  _state_mask.clear();
1708 }
1709 
1710 ////////////////////////////////////////////////////////////////////
1711 // Function: GraphicsStateGuardian::remove_window
1712 // Access: Public, Virtual
1713 // Description: This is simply a transparent call to
1714 // GraphicsEngine::remove_window(). It exists primary
1715 // to support removing a window from that compiles
1716 // before the display module, and therefore has no
1717 // knowledge of a GraphicsEngine object.
1718 ////////////////////////////////////////////////////////////////////
1721  nassertv(_engine != (GraphicsEngine *)NULL);
1722  GraphicsOutput *win;
1723  DCAST_INTO_V(win, window);
1724  _engine->remove_window(win);
1725 }
1726 
1727 ////////////////////////////////////////////////////////////////////
1728 // Function: GraphicsStateGuardian::prepare_lens
1729 // Access: Public, Virtual
1730 // Description: Makes the current lens (whichever lens was most
1731 // recently specified with set_scene()) active, so
1732 // that it will transform future rendered geometry.
1733 // Normally this is only called from the draw process,
1734 // and usually it is called by set_scene().
1735 //
1736 // The return value is true if the lens is acceptable,
1737 // false if it is not.
1738 ////////////////////////////////////////////////////////////////////
1741  return false;
1742 }
1743 
1744 ////////////////////////////////////////////////////////////////////
1745 // Function: GraphicsStateGuardian::calc_projection_mat
1746 // Access: Public, Virtual
1747 // Description: Given a lens, this function calculates the appropriate
1748 // projection matrix for this gsg. The result depends
1749 // on the peculiarities of the rendering API.
1750 ////////////////////////////////////////////////////////////////////
1751 CPT(TransformState) GraphicsStateGuardian::
1752 calc_projection_mat(const Lens *lens) {
1753  if (lens == (Lens *)NULL) {
1754  return NULL;
1755  }
1756 
1757  if (!lens->is_linear()) {
1758  return NULL;
1759  }
1760 
1761  return TransformState::make_identity();
1762 }
1763 
1764 ////////////////////////////////////////////////////////////////////
1765 // Function: GraphicsStateGuardian::begin_frame
1766 // Access: Public, Virtual
1767 // Description: Called before each frame is rendered, to allow the
1768 // GSG a chance to do any internal cleanup before
1769 // beginning the frame.
1770 //
1771 // The return value is true if successful (in which case
1772 // the frame will be drawn and end_frame() will be
1773 // called later), or false if unsuccessful (in which
1774 // case nothing will be drawn and end_frame() will not
1775 // be called).
1776 ////////////////////////////////////////////////////////////////////
1778 begin_frame(Thread *current_thread) {
1779  _prepared_objects->begin_frame(this, current_thread);
1780 
1781  // We should reset the state to the default at the beginning of
1782  // every frame. Although this will incur additional overhead,
1783  // particularly in a simple scene, it helps ensure that states that
1784  // have changed properties since last time without changing
1785  // attribute pointers--like textures, lighting, or fog--will still
1786  // be accurately updated.
1787  _state_rs = RenderState::make_empty();
1788  _state_mask.clear();
1789 
1790 #ifdef DO_PSTATS
1791  // We have to do this here instead of in GraphicsEngine because
1792  // we need a current context to issue timer queries.
1794  if (_last_query_frame < frame) {
1795  _last_query_frame = frame;
1796  _timer_queries_pcollector.clear_level();
1797 
1798  // Now is a good time to flush previous frame's queries. We
1799  // may not actually have all of the previous frame's results
1800  // in yet, but that's okay; the GPU data is allowed to lag a
1801  // few frames behind.
1803 
1804  if (_timer_queries_active) {
1805  // Issue a stop and start event for collector 0, marking the
1806  // beginning of the new frame.
1807  issue_timer_query(0x8000);
1808  issue_timer_query(0x0000);
1809  }
1810  }
1811 #endif
1812 
1813  return !_needs_reset;
1814 }
1815 
1816 ////////////////////////////////////////////////////////////////////
1817 // Function: GraphicsStateGuardian::begin_scene
1818 // Access: Published, Virtual
1819 // Description: Called between begin_frame() and end_frame() to mark
1820 // the beginning of drawing commands for a "scene"
1821 // (usually a particular DisplayRegion) within a frame.
1822 // All 3-D drawing commands, except the clear operation,
1823 // must be enclosed within begin_scene() .. end_scene().
1824 // This must be called in the draw thread.
1825 //
1826 // The return value is true if successful (in which case
1827 // the scene will be drawn and end_scene() will be
1828 // called later), or false if unsuccessful (in which
1829 // case nothing will be drawn and end_scene() will not
1830 // be called).
1831 ////////////////////////////////////////////////////////////////////
1834  return true;
1835 }
1836 
1837 ////////////////////////////////////////////////////////////////////
1838 // Function: GraphicsStateGuardian::end_scene
1839 // Access: Published, Virtual
1840 // Description: Called between begin_frame() and end_frame() to mark
1841 // the end of drawing commands for a "scene" (usually a
1842 // particular DisplayRegion) within a frame. All 3-D
1843 // drawing commands, except the clear operation, must be
1844 // enclosed within begin_scene() .. end_scene().
1845 ////////////////////////////////////////////////////////////////////
1848  // We should clear this pointer now, so that we don't keep unneeded
1849  // reference counts dangling. We keep around a "null" scene setup
1850  // object instead of using a null pointer to avoid special-case code
1851  // in set_state_and_transform.
1852  _scene_setup = _scene_null;
1853 
1854  // Undo any lighting we had enabled last scene, to force the lights
1855  // to be reissued, in case their parameters or positions have
1856  // changed between scenes.
1857  int i;
1858  for (i = 0; i < _num_lights_enabled; ++i) {
1859  enable_light(i, false);
1860  }
1861  _num_lights_enabled = 0;
1862 
1863  // Ditto for the clipping planes.
1864  for (i = 0; i < _num_clip_planes_enabled; ++i) {
1865  enable_clip_plane(i, false);
1866  }
1867  _num_clip_planes_enabled = 0;
1868 
1869  // Put the state into the 'unknown' state, forcing a reload.
1870  _state_rs = RenderState::make_empty();
1871  _state_mask.clear();
1872 }
1873 
1874 ////////////////////////////////////////////////////////////////////
1875 // Function: GraphicsStateGuardian::end_frame
1876 // Access: Public, Virtual
1877 // Description: Called after each frame is rendered, to allow the
1878 // GSG a chance to do any internal cleanup after
1879 // rendering the frame, and before the window flips.
1880 ////////////////////////////////////////////////////////////////////
1882 end_frame(Thread *current_thread) {
1883  _prepared_objects->end_frame(current_thread);
1884 
1885  // Flush any PStatCollectors.
1886  _data_transferred_pcollector.flush_level();
1887 
1888  _primitive_batches_pcollector.flush_level();
1889  _primitive_batches_tristrip_pcollector.flush_level();
1890  _primitive_batches_trifan_pcollector.flush_level();
1891  _primitive_batches_tri_pcollector.flush_level();
1892  _primitive_batches_patch_pcollector.flush_level();
1893  _primitive_batches_other_pcollector.flush_level();
1894  _vertices_tristrip_pcollector.flush_level();
1895  _vertices_trifan_pcollector.flush_level();
1896  _vertices_tri_pcollector.flush_level();
1897  _vertices_patch_pcollector.flush_level();
1898  _vertices_other_pcollector.flush_level();
1899 
1900  _state_pcollector.flush_level();
1901  _texture_state_pcollector.flush_level();
1902  _transform_state_pcollector.flush_level();
1903  _draw_primitive_pcollector.flush_level();
1904 
1905  // Evict any textures and/or vbuffers that exceed our texture memory.
1906  _prepared_objects->_graphics_memory_lru.begin_epoch();
1907 }
1908 
1909 ////////////////////////////////////////////////////////////////////
1910 // Function: GraphicsStateGuardian::flush_timer_queries
1911 // Access: Public
1912 // Description: Called by the graphics engine on the draw thread
1913 // to check the status of the running timer queries
1914 // and submit their results to the PStats server.
1915 ////////////////////////////////////////////////////////////////////
1918 #ifdef DO_PSTATS
1919  // This uses the lower-level PStats interfaces for now because
1920  // of all the unnecessary overhead that would otherwise be incurred
1921  // when adding such a large amount of data at once.
1922 
1923  PStatClient *client = PStatClient::get_global_pstats();
1924 
1925  if (!client->client_is_connected()) {
1926  _timer_queries_active = false;
1927  return;
1928  }
1929 
1930  if (!_timer_queries_active) {
1931  if (pstats_gpu_timing && _supports_timer_query) {
1932  // Check if timer queries should be enabled.
1933  _timer_queries_active = true;
1934  } else {
1935  return;
1936  }
1937  }
1938 
1939  // Currently, we use one thread per GSG, for convenience. In the
1940  // future, we may want to try and use one thread per graphics card.
1941  if (_pstats_gpu_thread == -1) {
1942  _pstats_gpu_thread = client->make_gpu_thread(get_driver_renderer()).get_index();
1943  }
1944  PStatThread gpu_thread(client, _pstats_gpu_thread);
1945 
1946  // Get the results of all the timer queries.
1947  int first = 0;
1948  if (!_pending_timer_queries.empty()) {
1949  int count = _pending_timer_queries.size();
1950  if (count == 0) {
1951  return;
1952  }
1953 
1954  PStatGPUTimer timer(this, _wait_timer_pcollector);
1955 
1956  if (_last_num_queried > 0) {
1957  // We know how many queries were available last frame, and this
1958  // usually stays fairly constant, so use this as a starting point.
1959  int i = min(_last_num_queried, count) - 1;
1960 
1961  if (_pending_timer_queries[i]->is_answer_ready()) {
1962  first = count;
1963  while (i < count - 1) {
1964  if (!_pending_timer_queries[++i]->is_answer_ready()) {
1965  first = i;
1966  break;
1967  }
1968  }
1969  } else {
1970  first = 0;
1971  while (i > 0) {
1972  if (_pending_timer_queries[--i]->is_answer_ready()) {
1973  first = i + 1;
1974  break;
1975  }
1976  }
1977  }
1978  } else {
1979  // We figure out which tasks the GPU has already finished by doing
1980  // a binary search for the first query that does not have an answer
1981  // ready. We know then that everything before that must be ready.
1982  while (count > 0) {
1983  int step = count / 2;
1984  int i = first + step;
1985  if (_pending_timer_queries[i]->is_answer_ready()) {
1986  first += step + 1;
1987  count -= step + 1;
1988  } else {
1989  count = step;
1990  }
1991  }
1992  }
1993 
1994  if (first <= 0) {
1995  return;
1996  }
1997 
1998  _last_num_queried = first;
1999 
2000  int frame_index = ClockObject::get_global_clock()->get_frame_count();
2001 
2002  for (int i = 0; i < first; ++i) {
2003  CPT(TimerQueryContext) query = _pending_timer_queries[i];
2004 
2005  double time_data = query->get_timestamp(); // + _timer_delta;
2006 
2007  if (query->_pstats_index == _command_latency_pcollector.get_index()) {
2008  // Special case for the latency pcollector.
2009  PStatCollectorDef *cdef;
2010  cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
2011  _pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
2012 
2013  } else if (query->_pstats_index & 0x8000) {
2014  _pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
2015 
2016  } else {
2017  _pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
2018  }
2019 
2020  // We found an end-frame marker (a stop event for collector 0).
2021  // This means that the GPU actually caught up with that frame,
2022  // and we can flush the GPU thread's frame data to the pstats server.
2023  if (query->_pstats_index == 0x8000) {
2024  gpu_thread.add_frame(_pstats_gpu_data);
2025  _pstats_gpu_data.clear();
2026  }
2027  }
2028  }
2029 
2030  if (first > 0) {
2031  // Do this out of the scope of _wait_timer_pcollector.
2032  _pending_timer_queries.erase(
2033  _pending_timer_queries.begin(),
2034  _pending_timer_queries.begin() + first
2035  );
2036  _timer_queries_pcollector.add_level_now(first);
2037  }
2038 #endif
2039 }
2040 
2041 ////////////////////////////////////////////////////////////////////
2042 // Function: GraphicsStateGuardian::depth_offset_decals
2043 // Access: Public, Virtual
2044 // Description: Returns true if this GSG can implement decals using a
2045 // DepthOffsetAttrib, or false if that is unreliable
2046 // and the three-step rendering process should be used
2047 // instead.
2048 ////////////////////////////////////////////////////////////////////
2051  return true;
2052 }
2053 
2054 ////////////////////////////////////////////////////////////////////
2055 // Function: GraphicsStateGuardian::begin_decal_base_first
2056 // Access: Public, Virtual
2057 // Description: Called during draw to begin a three-step rendering
2058 // phase to draw decals. The first step,
2059 // begin_decal_base_first(), is called prior to drawing the
2060 // base geometry. It should set up whatever internal
2061 // state is appropriate, as well as returning a
2062 // RenderState object that should be applied to the base
2063 // geometry for rendering.
2064 ////////////////////////////////////////////////////////////////////
2066 begin_decal_base_first() {
2067  // Turn off writing the depth buffer to render the base geometry.
2068  static CPT(RenderState) decal_base_first;
2069  if (decal_base_first == (const RenderState *)NULL) {
2070  decal_base_first = RenderState::make
2071  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2073  }
2074  return decal_base_first;
2075 }
2076 
2077 ////////////////////////////////////////////////////////////////////
2078 // Function: GraphicsStateGuardian::begin_decal_nested
2079 // Access: Public, Virtual
2080 // Description: Called during draw to begin a three-step rendering
2081 // phase to draw decals. The second step,
2082 // begin_decal_nested(), is called after drawing the
2083 // base geometry and prior to drawing any of the nested
2084 // decal geometry that is to be applied to the base
2085 // geometry.
2086 ////////////////////////////////////////////////////////////////////
2088 begin_decal_nested() {
2089  // We should keep the depth buffer off during this operation, so
2090  // that decals on decals will render properly.
2091  static CPT(RenderState) decal_nested;
2092  if (decal_nested == (const RenderState *)NULL) {
2093  decal_nested = RenderState::make
2094  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2096  }
2097  return decal_nested;
2098 }
2099 
2100 ////////////////////////////////////////////////////////////////////
2101 // Function: GraphicsStateGuardian::begin_decal_base_second
2102 // Access: Public, Virtual
2103 // Description: Called during draw to begin a three-step rendering
2104 // phase to draw decals. The third step,
2105 // begin_decal_base_second(), is called after drawing the
2106 // base geometry and the nested decal geometry, and
2107 // prior to drawing the base geometry one more time (if
2108 // needed).
2109 //
2110 // It should return a RenderState object appropriate for
2111 // rendering the base geometry the second time, or NULL
2112 // if it is not necessary to re-render the base
2113 // geometry.
2114 ////////////////////////////////////////////////////////////////////
2116 begin_decal_base_second() {
2117  // Now let the depth buffer go back on, but turn off writing the
2118  // color buffer to render the base geometry after the second pass.
2119  // Also, turn off texturing since there's no need for it now.
2120  static CPT(RenderState) decal_base_second;
2121  if (decal_base_second == (const RenderState *)NULL) {
2122  decal_base_second = RenderState::make
2123  (ColorWriteAttrib::make(ColorWriteAttrib::C_off),
2124  // On reflection, we need to leave texturing on so the alpha
2125  // test mechanism can work (if it is enabled, e.g. we are
2126  // rendering an object with M_dual transparency).
2127  // TextureAttrib::make_off(),
2129  }
2130  return decal_base_second;
2131 }
2132 
2133 ////////////////////////////////////////////////////////////////////
2134 // Function: GraphicsStateGuardian::finish_decal
2135 // Access: Public, Virtual
2136 // Description: Called during draw to clean up after decals are
2137 // finished.
2138 ////////////////////////////////////////////////////////////////////
2141  // No need to do anything special here.
2142 }
2143 
2144 ////////////////////////////////////////////////////////////////////
2145 // Function: GraphicsStateGuardian::begin_draw_primitives()
2146 // Access: Public, Virtual
2147 // Description: Called before a sequence of draw_primitive()
2148 // functions are called, this should prepare the vertex
2149 // data for rendering. It returns true if the vertices
2150 // are ok, false to abort this group of primitives.
2151 ////////////////////////////////////////////////////////////////////
2154  const GeomMunger *munger,
2155  const GeomVertexDataPipelineReader *data_reader,
2156  bool force) {
2157  _munger = munger;
2158  _data_reader = data_reader;
2159  return _data_reader->has_vertex();
2160 }
2161 
2162 ////////////////////////////////////////////////////////////////////
2163 // Function: GraphicsStateGuardian::draw_triangles
2164 // Access: Public, Virtual
2165 // Description: Draws a series of disconnected triangles.
2166 ////////////////////////////////////////////////////////////////////
2169  return false;
2170 }
2171 
2172 ////////////////////////////////////////////////////////////////////
2173 // Function: GraphicsStateGuardian::draw_tristrips
2174 // Access: Public, Virtual
2175 // Description: Draws a series of triangle strips.
2176 ////////////////////////////////////////////////////////////////////
2179  return false;
2180 }
2181 
2182 ////////////////////////////////////////////////////////////////////
2183 // Function: GraphicsStateGuardian::draw_trifans
2184 // Access: Public, Virtual
2185 // Description: Draws a series of triangle fans.
2186 ////////////////////////////////////////////////////////////////////
2189  return false;
2190 }
2191 
2192 ////////////////////////////////////////////////////////////////////
2193 // Function: GraphicsStateGuardian::draw_patches
2194 // Access: Public, Virtual
2195 // Description: Draws a series of "patches", which can only be
2196 // processed by a tessellation shader.
2197 ////////////////////////////////////////////////////////////////////
2200  return false;
2201 }
2202 
2203 ////////////////////////////////////////////////////////////////////
2204 // Function: GraphicsStateGuardian::draw_lines
2205 // Access: Public, Virtual
2206 // Description: Draws a series of disconnected line segments.
2207 ////////////////////////////////////////////////////////////////////
2210  return false;
2211 }
2212 
2213 ////////////////////////////////////////////////////////////////////
2214 // Function: GraphicsStateGuardian::draw_linestrips
2215 // Access: Public, Virtual
2216 // Description: Draws a series of line strips.
2217 ////////////////////////////////////////////////////////////////////
2220  return false;
2221 }
2222 
2223 ////////////////////////////////////////////////////////////////////
2224 // Function: GraphicsStateGuardian::draw_points
2225 // Access: Public, Virtual
2226 // Description: Draws a series of disconnected points.
2227 ////////////////////////////////////////////////////////////////////
2230  return false;
2231 }
2232 
2233 ////////////////////////////////////////////////////////////////////
2234 // Function: GraphicsStateGuardian::end_draw_primitives()
2235 // Access: Public, Virtual
2236 // Description: Called after a sequence of draw_primitive()
2237 // functions are called, this should do whatever cleanup
2238 // is appropriate.
2239 ////////////////////////////////////////////////////////////////////
2242  _munger = NULL;
2243  _data_reader = NULL;
2244 }
2245 
2246 ////////////////////////////////////////////////////////////////////
2247 // Function: GraphicsStateGuardian::reset
2248 // Access: Public, Virtual
2249 // Description: Resets all internal state as if the gsg were newly
2250 // created.
2251 ////////////////////////////////////////////////////////////////////
2254  _needs_reset = false;
2255  _is_valid = false;
2256 
2257  _state_rs = RenderState::make_empty();
2258  _target_rs = NULL;
2259  _state_mask.clear();
2260  _internal_transform = _cs_transform;
2261  _scene_null = new SceneSetup;
2262  _scene_setup = _scene_null;
2263 
2264  _color_write_mask = ColorWriteAttrib::C_all;
2265 
2266  _has_scene_graph_color = false;
2267  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2268  _transform_stale = true;
2269  _color_blend_involves_color_scale = false;
2270  _texture_involves_color_scale = false;
2271  _vertex_colors_enabled = true;
2272  _lighting_enabled = false;
2273  _num_lights_enabled = 0;
2274  _num_clip_planes_enabled = 0;
2275  _clip_planes_enabled = false;
2276 
2277  _color_scale_enabled = false;
2278  _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2279  _has_texture_alpha_scale = false;
2280 
2281  _has_material_force_color = false;
2282  _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2283  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2284 
2285  _tex_gen_modifies_mat = false;
2286  _last_max_stage_index = 0;
2287 
2288  _is_valid = true;
2289 }
2290 
2291 ////////////////////////////////////////////////////////////////////
2292 // Function: GraphicsStateGuardian::set_state_and_transform
2293 // Access: Public
2294 // Description: Simultaneously resets the render state and the
2295 // transform state.
2296 //
2297 // This transform specified is the "internal" net
2298 // transform, already converted into the GSG's internal
2299 // coordinate space by composing it to
2300 // get_cs_transform(). (Previously, this used to be the
2301 // "external" net transform, with the assumption that
2302 // that GSG would convert it internally, but that is no
2303 // longer the case.)
2304 //
2305 // Special case: if (state==NULL), then the target
2306 // state is already stored in _target.
2307 ////////////////////////////////////////////////////////////////////
2310  const TransformState *trans) {
2311 }
2312 
2313 ////////////////////////////////////////////////////////////////////
2314 // Function: GraphicsStateGuardian::clear
2315 // Access: Public
2316 // Description: Clears the framebuffer within the current
2317 // DisplayRegion, according to the flags indicated by
2318 // the given DrawableRegion object.
2319 //
2320 // This does not set the DisplayRegion first. You
2321 // should call prepare_display_region() to specify the
2322 // region you wish the clear operation to apply to.
2323 ////////////////////////////////////////////////////////////////////
2325 clear(DrawableRegion *clearable) {
2326 }
2327 
2328 ////////////////////////////////////////////////////////////////////
2329 // Function: GraphicsStateGuardian::get_render_buffer
2330 // Access: Public
2331 // Description: Returns a RenderBuffer object suitable for operating
2332 // on the requested set of buffers. buffer_type is the
2333 // union of all the desired RenderBuffer::Type values.
2334 ////////////////////////////////////////////////////////////////////
2336 get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
2337  return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
2338 }
2339 
2340 ////////////////////////////////////////////////////////////////////
2341 // Function: GraphicsStateGuardian::get_cs_transform_for
2342 // Access: Public, Virtual
2343 // Description: Returns what the cs_transform would be set to after a
2344 // call to set_coordinate_system(cs). This is another
2345 // way of saying the cs_transform when rendering the
2346 // scene for a camera with the indicated coordinate
2347 // system.
2348 ////////////////////////////////////////////////////////////////////
2349 CPT(TransformState) GraphicsStateGuardian::
2350 get_cs_transform_for(CoordinateSystem cs) const {
2351  if (_coordinate_system == cs) {
2352  // We've already calculated this.
2353  return _cs_transform;
2354 
2355  } else if (_internal_coordinate_system == CS_default ||
2356  _internal_coordinate_system == cs) {
2357  return TransformState::make_identity();
2358 
2359  } else {
2360  return TransformState::make_mat
2361  (LMatrix4::convert_mat(cs, _internal_coordinate_system));
2362  }
2363 }
2364 
2365 ////////////////////////////////////////////////////////////////////
2366 // Function: GraphicsStateGuardian::get_cs_transform
2367 // Access: Public, Virtual
2368 // Description: Returns a transform that converts from the GSG's
2369 // external coordinate system (as returned by
2370 // get_coordinate_system()) to its internal coordinate
2371 // system (as returned by
2372 // get_internal_coordinate_system()). This is used for
2373 // rendering.
2374 ////////////////////////////////////////////////////////////////////
2375 CPT(TransformState) GraphicsStateGuardian::
2376 get_cs_transform() const {
2377  return _cs_transform;
2378 }
2379 
2380 ////////////////////////////////////////////////////////////////////
2381 // Function: GraphicsStateGuardian::do_issue_clip_plane
2382 // Access: Public
2383 // Description: This is fundametically similar to do_issue_light(), with
2384 // calls to apply_clip_plane() and enable_clip_planes(),
2385 // as appropriate.
2386 ////////////////////////////////////////////////////////////////////
2387 void GraphicsStateGuardian::
2388 do_issue_clip_plane() {
2389  int num_enabled = 0;
2390  int num_on_planes = 0;
2391 
2392  const ClipPlaneAttrib *target_clip_plane = (const ClipPlaneAttrib *)
2393  _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot());
2394 
2395  if (target_clip_plane != (ClipPlaneAttrib *)NULL) {
2396  CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
2397 
2398  num_on_planes = new_plane->get_num_on_planes();
2399  for (int li = 0; li < num_on_planes; li++) {
2400  NodePath plane = new_plane->get_on_plane(li);
2401  nassertv(!plane.is_empty());
2402  PlaneNode *plane_node;
2403  DCAST_INTO_V(plane_node, plane.node());
2404  if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) {
2405  // Clipping should be enabled before we apply any planes.
2406  if (!_clip_planes_enabled) {
2407  enable_clip_planes(true);
2408  _clip_planes_enabled = true;
2409  }
2410 
2411  enable_clip_plane(num_enabled, true);
2412  if (num_enabled == 0) {
2413  begin_bind_clip_planes();
2414  }
2415 
2416  bind_clip_plane(plane, num_enabled);
2417  num_enabled++;
2418  }
2419  }
2420  }
2421 
2422  int i;
2423  for (i = num_enabled; i < _num_clip_planes_enabled; ++i) {
2424  enable_clip_plane(i, false);
2425  }
2426  _num_clip_planes_enabled = num_enabled;
2427 
2428  // If no planes were set, disable clipping
2429  if (num_enabled == 0) {
2430  if (_clip_planes_enabled) {
2431  enable_clip_planes(false);
2432  _clip_planes_enabled = false;
2433  }
2434  } else {
2435  end_bind_clip_planes();
2436  }
2437 }
2438 
2439 ////////////////////////////////////////////////////////////////////
2440 // Function: GraphicsStateGuardian::do_issue_color
2441 // Access: Public
2442 // Description: This method is defined in the base class because it
2443 // is likely that this functionality will be used for
2444 // all (or at least most) kinds of
2445 // GraphicsStateGuardians--it's not specific to any one
2446 // rendering backend.
2447 //
2448 // The ColorAttribute just changes the interpretation of
2449 // the color on the vertices, and fiddles with
2450 // _vertex_colors_enabled, etc.
2451 ////////////////////////////////////////////////////////////////////
2454  const ColorAttrib *target_color = (const ColorAttrib *)
2455  _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
2456 
2457  switch (target_color->get_color_type()) {
2458  case ColorAttrib::T_flat:
2459  // Color attribute flat: it specifies a scene graph color that
2460  // overrides the vertex color.
2461  _scene_graph_color = target_color->get_color();
2462  _has_scene_graph_color = true;
2463  _vertex_colors_enabled = false;
2464  break;
2465 
2466  case ColorAttrib::T_off:
2467  // Color attribute off: it specifies that no scene graph color is
2468  // in effect, and vertex color is not important either.
2469  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2470  _has_scene_graph_color = false;
2471  _vertex_colors_enabled = false;
2472  break;
2473 
2474  case ColorAttrib::T_vertex:
2475  // Color attribute vertex: it specifies that vertex color should
2476  // be revealed.
2477  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2478  _has_scene_graph_color = false;
2479  _vertex_colors_enabled = true;
2480  break;
2481  }
2482 
2483  if (_color_scale_via_lighting) {
2484  _state_mask.clear_bit(LightAttrib::get_class_slot());
2485  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2486 
2487  determine_light_color_scale();
2488  }
2489 }
2490 
2491 ////////////////////////////////////////////////////////////////////
2492 // Function: GraphicsStateGuardian::do_issue_color_scale
2493 // Access: Public, Virtual
2494 // Description:
2495 ////////////////////////////////////////////////////////////////////
2496 void GraphicsStateGuardian::
2497 do_issue_color_scale() {
2498  // If the previous color scale had set a special texture, clear the
2499  // texture now.
2500  if (_has_texture_alpha_scale) {
2501  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2502  }
2503 
2504  const ColorScaleAttrib *target_color_scale = (const ColorScaleAttrib *)
2505  _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
2506 
2507  _color_scale_enabled = target_color_scale->has_scale();
2508  _current_color_scale = target_color_scale->get_scale();
2509  _has_texture_alpha_scale = false;
2510 
2511  if (_color_blend_involves_color_scale) {
2512  _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
2513  }
2514  if (_texture_involves_color_scale) {
2515  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2516  }
2517  if (_color_scale_via_lighting) {
2518  _state_mask.clear_bit(LightAttrib::get_class_slot());
2519  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2520 
2521  determine_light_color_scale();
2522  }
2523 
2524  if (_alpha_scale_via_texture && !_has_scene_graph_color &&
2525  target_color_scale->has_alpha_scale()) {
2526  // This color scale will set a special texture--so again, clear
2527  // the texture.
2528  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2529  _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
2530 
2531  _has_texture_alpha_scale = true;
2532  }
2533 }
2534 
2535 ////////////////////////////////////////////////////////////////////
2536 // Function: GraphicsStateGuardian::do_issue_light
2537 // Access: Protected, Virtual
2538 // Description: This implementation of do_issue_light() assumes
2539 // we have a limited number of hardware lights
2540 // available. This function assigns each light to a
2541 // different hardware light id, trying to keep each
2542 // light associated with the same id where possible, but
2543 // reusing id's when necessary. When it is no longer
2544 // possible to reuse existing id's (e.g. all id's are in
2545 // use), the next sequential id is assigned (if
2546 // available).
2547 //
2548 // It will call apply_light() each time a light is
2549 // assigned to a particular id for the first time in a
2550 // given frame, and it will subsequently call
2551 // enable_light() to enable or disable each light as the
2552 // frame is rendered, as well as enable_lighting() to
2553 // enable or disable overall lighting.
2554 ////////////////////////////////////////////////////////////////////
2557  // Initialize the current ambient light total and newly enabled
2558  // light list
2559  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
2560  int i;
2561 
2562  int num_enabled = 0;
2563  int num_on_lights = 0;
2564 
2565  const LightAttrib *target_light = (const LightAttrib *)
2566  _target_rs->get_attrib_def(LightAttrib::get_class_slot());
2567 
2568  if (display_cat.is_spam()) {
2569  display_cat.spam()
2570  << "do_issue_light: " << target_light << "\n";
2571  }
2572  if (target_light != (LightAttrib *)NULL) {
2573  CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights);
2574  if (display_cat.is_spam()) {
2575  new_light->write(display_cat.spam(false), 2);
2576  }
2577 
2578  num_on_lights = new_light->get_num_on_lights();
2579  for (int li = 0; li < num_on_lights; li++) {
2580  NodePath light = new_light->get_on_light(li);
2581  nassertv(!light.is_empty());
2582  Light *light_obj = light.node()->as_light();
2583  nassertv(light_obj != (Light *)NULL);
2584 
2585  // Lighting should be enabled before we apply any lights.
2586  if (!_lighting_enabled) {
2587  enable_lighting(true);
2588  _lighting_enabled = true;
2589  }
2590 
2591  if (light_obj->get_type() == AmbientLight::get_class_type()) {
2592  // Ambient lights don't require specific light ids; simply add
2593  // in the ambient contribution to the current total
2594  cur_ambient_light += light_obj->get_color();
2595 
2596  } else {
2597  const LColor &color = light_obj->get_color();
2598  // Don't bother binding the light if it has no color to contribute.
2599  if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
2600  enable_light(num_enabled, true);
2601  if (num_enabled == 0) {
2602  begin_bind_lights();
2603  }
2604 
2605  light_obj->bind(this, light, num_enabled);
2606  num_enabled++;
2607  }
2608  }
2609  }
2610  }
2611 
2612  for (i = num_enabled; i < _num_lights_enabled; ++i) {
2613  enable_light(i, false);
2614  }
2615  _num_lights_enabled = num_enabled;
2616 
2617  // If no lights were set, disable lighting
2618  if (num_on_lights == 0) {
2619  if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f))) {
2620  // Unless we need lighting anyway to apply a color or color
2621  // scale.
2622  if (!_lighting_enabled) {
2623  enable_lighting(true);
2624  _lighting_enabled = true;
2625  }
2626  set_ambient_light(LColor(1.0f, 1.0f, 1.0f, 1.0f));
2627 
2628  } else {
2629  if (_lighting_enabled) {
2630  enable_lighting(false);
2631  _lighting_enabled = false;
2632  }
2633  }
2634 
2635  } else {
2636  set_ambient_light(cur_ambient_light);
2637  }
2638 
2639  if (num_enabled != 0) {
2640  end_bind_lights();
2641  }
2642 }
2643 
2644 ////////////////////////////////////////////////////////////////////
2645 // Function: GraphicsStateGuardian::framebuffer_copy_to_texture
2646 // Access: Public, Virtual
2647 // Description: Copy the pixels within the indicated display
2648 // region from the framebuffer into texture memory.
2649 //
2650 // If z > -1, it is the cube map index into which to
2651 // copy.
2652 ////////////////////////////////////////////////////////////////////
2655  const RenderBuffer &) {
2656  return false;
2657 }
2658 
2659 
2660 ////////////////////////////////////////////////////////////////////
2661 // Function: GraphicsStateGuardian::framebuffer_copy_to_ram
2662 // Access: Public, Virtual
2663 // Description: Copy the pixels within the indicated display region
2664 // from the framebuffer into system memory, not texture
2665 // memory. Returns true on success, false on failure.
2666 //
2667 // This completely redefines the ram image of the
2668 // indicated texture.
2669 ////////////////////////////////////////////////////////////////////
2672  const RenderBuffer &) {
2673  return false;
2674 }
2675 
2676 ////////////////////////////////////////////////////////////////////
2677 // Function: GraphicsStateGuardian::bind_light
2678 // Access: Public, Virtual
2679 // Description: Called the first time a particular light has been
2680 // bound to a given id within a frame, this should set
2681 // up the associated hardware light with the light's
2682 // properties.
2683 ////////////////////////////////////////////////////////////////////
2685 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
2686 }
2687 
2688 ////////////////////////////////////////////////////////////////////
2689 // Function: GraphicsStateGuardian::bind_light
2690 // Access: Public, Virtual
2691 // Description: Called the first time a particular light has been
2692 // bound to a given id within a frame, this should set
2693 // up the associated hardware light with the light's
2694 // properties.
2695 ////////////////////////////////////////////////////////////////////
2697 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
2698 }
2699 
2700 ////////////////////////////////////////////////////////////////////
2701 // Function: GraphicsStateGuardian::bind_light
2702 // Access: Public, Virtual
2703 // Description: Called the first time a particular light has been
2704 // bound to a given id within a frame, this should set
2705 // up the associated hardware light with the light's
2706 // properties.
2707 ////////////////////////////////////////////////////////////////////
2709 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
2710 }
2711 
2712 #ifdef DO_PSTATS
2713 ////////////////////////////////////////////////////////////////////
2714 // Function: GraphicsStateGuardian::init_frame_pstats
2715 // Access: Public, Static
2716 // Description: Initializes the relevant PStats data at the beginning
2717 // of the frame.
2718 ////////////////////////////////////////////////////////////////////
2719 void GraphicsStateGuardian::
2720 init_frame_pstats() {
2721  if (PStatClient::is_connected()) {
2722  _data_transferred_pcollector.clear_level();
2723  _vertex_buffer_switch_pcollector.clear_level();
2724  _index_buffer_switch_pcollector.clear_level();
2725 
2726  _primitive_batches_pcollector.clear_level();
2727  _primitive_batches_tristrip_pcollector.clear_level();
2728  _primitive_batches_trifan_pcollector.clear_level();
2729  _primitive_batches_tri_pcollector.clear_level();
2730  _primitive_batches_patch_pcollector.clear_level();
2731  _primitive_batches_other_pcollector.clear_level();
2732  _vertices_tristrip_pcollector.clear_level();
2733  _vertices_trifan_pcollector.clear_level();
2734  _vertices_tri_pcollector.clear_level();
2735  _vertices_patch_pcollector.clear_level();
2736  _vertices_other_pcollector.clear_level();
2737 
2738  _state_pcollector.clear_level();
2739  _transform_state_pcollector.clear_level();
2740  _texture_state_pcollector.clear_level();
2741  }
2742 }
2743 #endif // DO_PSTATS
2744 
2745 
2746 ////////////////////////////////////////////////////////////////////
2747 // Function: GraphicsStateGuardian::create_gamma_table
2748 // Access: Public, Static
2749 // Description: Create a gamma table.
2750 ////////////////////////////////////////////////////////////////////
2752 create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
2753  int i;
2754 
2755  if (gamma <= 0.0) {
2756  // avoid divide by zero and negative exponents
2757  gamma = 1.0;
2758  }
2759 
2760  for (i = 0; i < 256; i++) {
2761  double g;
2762  double x;
2763  PN_stdfloat gamma_correction;
2764 
2765  x = ((double) i / 255.0);
2766  gamma_correction = 1.0 / gamma;
2767  x = pow (x, (double) gamma_correction);
2768  if (x > 1.00) {
2769  x = 1.0;
2770  }
2771 
2772  g = x * 65535.0;
2773  red_table [i] = (int)g;
2774  green_table [i] = (int)g;
2775  blue_table [i] = (int)g;
2776  }
2777 }
2778 
2779 ////////////////////////////////////////////////////////////////////
2780 // Function: GraphicsStateGuardian::reissue_transforms
2781 // Access: Protected, Virtual
2782 // Description: Called by clear_state_and_transform() to ensure that
2783 // the current modelview and projection matrices are
2784 // properly loaded in the graphics state, after a
2785 // callback might have mucked them up.
2786 ////////////////////////////////////////////////////////////////////
2787 void GraphicsStateGuardian::
2788 reissue_transforms() {
2789 }
2790 
2791 ////////////////////////////////////////////////////////////////////
2792 // Function: GraphicsStateGuardian::enable_lighting
2793 // Access: Protected, Virtual
2794 // Description: Intended to be overridden by a derived class to
2795 // enable or disable the use of lighting overall. This
2796 // is called by do_issue_light() according to whether any
2797 // lights are in use or not.
2798 ////////////////////////////////////////////////////////////////////
2799 void GraphicsStateGuardian::
2800 enable_lighting(bool enable) {
2801 }
2802 
2803 ////////////////////////////////////////////////////////////////////
2804 // Function: GraphicsStateGuardian::set_ambient_light
2805 // Access: Protected, Virtual
2806 // Description: Intended to be overridden by a derived class to
2807 // indicate the color of the ambient light that should
2808 // be in effect. This is called by do_issue_light() after
2809 // all other lights have been enabled or disabled.
2810 ////////////////////////////////////////////////////////////////////
2811 void GraphicsStateGuardian::
2812 set_ambient_light(const LColor &color) {
2813 }
2814 
2815 ////////////////////////////////////////////////////////////////////
2816 // Function: GraphicsStateGuardian::enable_light
2817 // Access: Protected, Virtual
2818 // Description: Intended to be overridden by a derived class to
2819 // enable the indicated light id. A specific Light will
2820 // already have been bound to this id via bind_light().
2821 ////////////////////////////////////////////////////////////////////
2822 void GraphicsStateGuardian::
2823 enable_light(int light_id, bool enable) {
2824 }
2825 
2826 ////////////////////////////////////////////////////////////////////
2827 // Function: GraphicsStateGuardian::begin_bind_lights
2828 // Access: Protected, Virtual
2829 // Description: Called immediately before bind_light() is called,
2830 // this is intended to provide the derived class a hook
2831 // in which to set up some state (like transform) that
2832 // might apply to several lights.
2833 //
2834 // The sequence is: begin_bind_lights() will be called,
2835 // then one or more bind_light() calls, then
2836 // end_bind_lights().
2837 ////////////////////////////////////////////////////////////////////
2838 void GraphicsStateGuardian::
2839 begin_bind_lights() {
2840 }
2841 
2842 ////////////////////////////////////////////////////////////////////
2843 // Function: GraphicsStateGuardian::end_bind_lights
2844 // Access: Protected, Virtual
2845 // Description: Called after before bind_light() has been called one
2846 // or more times (but before any geometry is issued or
2847 // additional state is changed), this is intended to
2848 // clean up any temporary changes to the state that may
2849 // have been made by begin_bind_lights().
2850 ////////////////////////////////////////////////////////////////////
2851 void GraphicsStateGuardian::
2852 end_bind_lights() {
2853 }
2854 
2855 ////////////////////////////////////////////////////////////////////
2856 // Function: GraphicsStateGuardian::enable_clip_planes
2857 // Access: Protected, Virtual
2858 // Description: Intended to be overridden by a derived class to
2859 // enable or disable the use of clipping planes overall.
2860 // This is called by do_issue_clip_plane() according to
2861 // whether any planes are in use or not.
2862 ////////////////////////////////////////////////////////////////////
2863 void GraphicsStateGuardian::
2864 enable_clip_planes(bool enable) {
2865 }
2866 
2867 ////////////////////////////////////////////////////////////////////
2868 // Function: GraphicsStateGuardian::enable_clip_plane
2869 // Access: Protected, Virtual
2870 // Description: Intended to be overridden by a derived class to
2871 // enable the indicated plane id. A specific PlaneNode
2872 // will already have been bound to this id via
2873 // bind_clip_plane().
2874 ////////////////////////////////////////////////////////////////////
2875 void GraphicsStateGuardian::
2876 enable_clip_plane(int plane_id, bool enable) {
2877 }
2878 
2879 ////////////////////////////////////////////////////////////////////
2880 // Function: GraphicsStateGuardian::begin_bind_clip_planes
2881 // Access: Protected, Virtual
2882 // Description: Called immediately before bind_clip_plane() is called,
2883 // this is intended to provide the derived class a hook
2884 // in which to set up some state (like transform) that
2885 // might apply to several planes.
2886 //
2887 // The sequence is: begin_bind_clip_planes() will be
2888 // called, then one or more bind_clip_plane() calls,
2889 // then end_bind_clip_planes().
2890 ////////////////////////////////////////////////////////////////////
2891 void GraphicsStateGuardian::
2892 begin_bind_clip_planes() {
2893 }
2894 
2895 ////////////////////////////////////////////////////////////////////
2896 // Function: GraphicsStateGuardian::bind_clip_plane
2897 // Access: Public, Virtual
2898 // Description: Called the first time a particular clipping plane has been
2899 // bound to a given id within a frame, this should set
2900 // up the associated hardware (or API) clipping plane
2901 // with the plane's properties.
2902 ////////////////////////////////////////////////////////////////////
2903 void GraphicsStateGuardian::
2904 bind_clip_plane(const NodePath &plane, int plane_id) {
2905 }
2906 
2907 ////////////////////////////////////////////////////////////////////
2908 // Function: GraphicsStateGuardian::end_bind_clip_planes
2909 // Access: Protected, Virtual
2910 // Description: Called after before bind_clip_plane() has been called one
2911 // or more times (but before any geometry is issued or
2912 // additional state is changed), this is intended to
2913 // clean up any temporary changes to the state that may
2914 // have been made by begin_bind_clip_planes().
2915 ////////////////////////////////////////////////////////////////////
2916 void GraphicsStateGuardian::
2917 end_bind_clip_planes() {
2918 }
2919 
2920 ////////////////////////////////////////////////////////////////////
2921 // Function: GraphicsStateGuardian::determine_target_texture
2922 // Access: Protected
2923 // Description: Assigns _target_texture and _target_tex_gen
2924 // based on the _target_rs.
2925 ////////////////////////////////////////////////////////////////////
2926 void GraphicsStateGuardian::
2927 determine_target_texture() {
2928  const TextureAttrib *target_texture = (const TextureAttrib *)
2929  _target_rs->get_attrib_def(TextureAttrib::get_class_slot());
2930  const TexGenAttrib *target_tex_gen = (const TexGenAttrib *)
2931  _target_rs->get_attrib_def(TexGenAttrib::get_class_slot());
2932 
2933  nassertv(target_texture != (TextureAttrib *)NULL &&
2934  target_tex_gen != (TexGenAttrib *)NULL);
2935  _target_texture = target_texture;
2936  _target_tex_gen = target_tex_gen;
2937 
2938  if (_has_texture_alpha_scale) {
2940  PT(Texture) texture = TexturePool::get_alpha_scale_map();
2941 
2942  _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
2943  _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
2944  (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
2945  }
2946 
2947  int max_texture_stages = get_max_texture_stages();
2948  _target_texture = _target_texture->filter_to_max(max_texture_stages);
2949  nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
2950 }
2951 
2952 ////////////////////////////////////////////////////////////////////
2953 // Function: GraphicsStateGuardian::free_pointers
2954 // Access: Protected, Virtual
2955 // Description: Frees some memory that was explicitly allocated
2956 // within the glgsg.
2957 ////////////////////////////////////////////////////////////////////
2958 void GraphicsStateGuardian::
2959 free_pointers() {
2960 }
2961 
2962 ////////////////////////////////////////////////////////////////////
2963 // Function: GraphicsStateGuardian::close_gsg
2964 // Access: Protected, Virtual
2965 // Description: This is called by the associated GraphicsWindow when
2966 // close_window() is called. It should null out the
2967 // _win pointer and possibly free any open resources
2968 // associated with the GSG.
2969 ////////////////////////////////////////////////////////////////////
2970 void GraphicsStateGuardian::
2971 close_gsg() {
2972  // Protect from multiple calls, and also inform any other functions
2973  // not to try to create new stuff while we're going down.
2974  if (_closing_gsg) {
2975  return;
2976  }
2977  _closing_gsg = true;
2978 
2979  if (display_cat.is_debug()) {
2980  display_cat.debug()
2981  << this << " close_gsg " << get_type() << "\n";
2982  }
2983 
2984  // As tempting as it may be to try to release all the textures and
2985  // geoms now, we can't, because we might not be the currently-active
2986  // GSG (this is particularly important in OpenGL, which maintains
2987  // one currently-active GL state in each thread). If we start
2988  // deleting textures, we'll be inadvertently deleting textures from
2989  // some other OpenGL state.
2990 
2991  // Fortunately, it doesn't really matter, since the graphics API
2992  // will be responsible for cleaning up anything we don't clean up
2993  // explicitly. We'll just let them drop.
2994 
2995  // However, if any objects have recently been released, we have to
2996  // ensure they are actually deleted properly.
2997  Thread *current_thread = Thread::get_current_thread();
2998  _prepared_objects->begin_frame(this, current_thread);
2999  _prepared_objects->end_frame(current_thread);
3000 
3001  // We have to clear the list of timer queries, though, otherwise
3002  // their destructors will cause a crash when they try to access
3003  // the GSG object.
3004 #ifdef DO_PSTATS
3005  _pending_timer_queries.clear();
3006 #endif
3007 
3008  free_pointers();
3009 }
3010 
3011 ////////////////////////////////////////////////////////////////////
3012 // Function: GraphicsStateGuardian::panic_deactivate
3013 // Access: Protected
3014 // Description: This is called internally when it is determined that
3015 // things are just fubar. It temporarily deactivates
3016 // the GSG just so things don't get out of hand, and
3017 // throws an event so the application can deal with this
3018 // if it needs to.
3019 ////////////////////////////////////////////////////////////////////
3020 void GraphicsStateGuardian::
3021 panic_deactivate() {
3022  if (_active) {
3023  display_cat.error()
3024  << "Deactivating " << get_type() << ".\n";
3025  set_active(false);
3026  throw_event("panic-deactivate-gsg", this);
3027  }
3028 }
3029 
3030 ////////////////////////////////////////////////////////////////////
3031 // Function: GraphicsStateGuardian::determine_light_color_scale
3032 // Access: Protected
3033 // Description: Called whenever the color or color scale is changed,
3034 // if _color_scale_via_lighting is true. This will
3035 // rederive _material_force_color and _light_color_scale
3036 // appropriately.
3037 ////////////////////////////////////////////////////////////////////
3038 void GraphicsStateGuardian::
3039 determine_light_color_scale() {
3040  if (_has_scene_graph_color) {
3041  // If we have a scene graph color, it, plus the color scale, goes
3042  // directly into the material; we don't color scale the
3043  // lights--this allows an alpha color scale to work properly.
3044  _has_material_force_color = true;
3045  _material_force_color = _scene_graph_color;
3046  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3047  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3048  _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
3049  _scene_graph_color[1] * _current_color_scale[1],
3050  _scene_graph_color[2] * _current_color_scale[2],
3051  _scene_graph_color[3] * _current_color_scale[3]);
3052  }
3053 
3054  } else {
3055  // Otherise, leave the materials alone, but we might still scale
3056  // the lights.
3057  _has_material_force_color = false;
3058  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3059  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3060  _light_color_scale = _current_color_scale;
3061  }
3062  }
3063 }
3064 
3065 ////////////////////////////////////////////////////////////////////
3066 // Function: GraphicsStateGuardian::get_unlit_state
3067 // Access: Protected, Static
3068 // Description:
3069 ////////////////////////////////////////////////////////////////////
3071 get_unlit_state() {
3072  static CPT(RenderState) state = NULL;
3073  if (state == (const RenderState *)NULL) {
3074  state = RenderState::make(LightAttrib::make_all_off());
3075  }
3076  return state;
3077 }
3078 
3079 ////////////////////////////////////////////////////////////////////
3080 // Function: GraphicsStateGuardian::get_unclipped_state
3081 // Access: Protected, Static
3082 // Description:
3083 ////////////////////////////////////////////////////////////////////
3085 get_unclipped_state() {
3086  static CPT(RenderState) state = NULL;
3087  if (state == (const RenderState *)NULL) {
3088  state = RenderState::make(ClipPlaneAttrib::make_all_off());
3089  }
3090  return state;
3091 }
3092 
3093 ////////////////////////////////////////////////////////////////////
3094 // Function: GraphicsStateGuardian::get_untextured_state
3095 // Access: Protected, Static
3096 // Description:
3097 ////////////////////////////////////////////////////////////////////
3099 get_untextured_state() {
3100  static CPT(RenderState) state = NULL;
3101  if (state == (const RenderState *)NULL) {
3102  state = RenderState::make(TextureAttrib::make_off());
3103  }
3104  return state;
3105 }
3106 
3107 ////////////////////////////////////////////////////////////////////
3108 // Function: GraphicsStateGuardian::async_reload_texture
3109 // Access: Protected
3110 // Description: Should be called when a texture is encountered that
3111 // needs to have its RAM image reloaded, and
3112 // get_incomplete_render() is true. This will fire off
3113 // a thread on the current Loader object that will
3114 // request the texture to load its image. The image
3115 // will be available at some point in the future (no
3116 // event will be generated).
3117 ////////////////////////////////////////////////////////////////////
3118 void GraphicsStateGuardian::
3119 async_reload_texture(TextureContext *tc) {
3120  nassertv(_loader != (Loader *)NULL);
3121 
3122  int priority = 0;
3123  if (_current_display_region != (DisplayRegion *)NULL) {
3124  priority = _current_display_region->get_texture_reload_priority();
3125  }
3126 
3127  string task_name = string("reload:") + tc->get_texture()->get_name();
3128  PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
3129 
3130  // See if we are already loading this task.
3131  AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
3132  int num_tasks = orig_tasks.get_num_tasks();
3133  for (int ti = 0; ti < num_tasks; ++ti) {
3134  AsyncTask *task = orig_tasks.get_task(ti);
3135  if (task->is_exact_type(TextureReloadRequest::get_class_type()) &&
3136  DCAST(TextureReloadRequest, task)->get_texture() == tc->get_texture()) {
3137  // This texture is already queued to be reloaded. Don't queue
3138  // it again, just make sure the priority is updated, and return.
3139  task->set_priority(max(task->get_priority(), priority));
3140  return;
3141  }
3142  }
3143 
3144  // This texture has not yet been queued to be reloaded. Queue it up
3145  // now.
3146  PT(AsyncTask) request =
3147  new TextureReloadRequest(task_name,
3148  _prepared_objects, tc->get_texture(),
3149  _supports_compressed_texture);
3150  request->set_priority(priority);
3151  _loader->load_async(request);
3152 }
3153 
3154 ////////////////////////////////////////////////////////////////////
3155 // Function: GraphicsStateGuardian::make_shadow_buffer
3156 // Access: Protected
3157 // Description: Creates a depth buffer for shadow mapping. This
3158 // is a convenience function for the ShaderGenerator;
3159 // putting this directly in the ShaderGenerator would
3160 // cause circular dependency issues.
3161 // Returns the depth texture.
3162 ////////////////////////////////////////////////////////////////////
3164 make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
3165  // Make sure everything is valid.
3166  nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
3167  light_np.node()->is_of_type(PointLight::get_class_type()) ||
3168  light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
3169 
3170  PT(LightLensNode) light = DCAST(LightLensNode, light_np.node());
3171  if (light == NULL || !light->_shadow_caster) {
3172  return NULL;
3173  }
3174 
3175  bool is_point = light->is_of_type(PointLight::get_class_type());
3176 
3177  nassertr(light->_sbuffers.count(this) == 0, NULL);
3178 
3179  display_cat.debug() << "Constructing shadow buffer for light '" << light->get_name()
3180  << "', size=" << light->_sb_xsize << "x" << light->_sb_ysize
3181  << ", sort=" << light->_sb_sort << "\n";
3182 
3183  // Setup some flags and properties
3185  fbp.set_depth_bits(1); // We only need depth
3186  WindowProperties props = WindowProperties::size(light->_sb_xsize, light->_sb_ysize);
3187  int flags = GraphicsPipe::BF_refuse_window;
3188  if (is_point) {
3189  flags |= GraphicsPipe::BF_size_square;
3190  }
3191 
3192  // Create the buffer
3193  PT(GraphicsOutput) sbuffer = get_engine()->make_output(get_pipe(), light->get_name(),
3194  light->_sb_sort, fbp, props, flags, this, DCAST(GraphicsOutput, host));
3195  nassertr(sbuffer != NULL, NULL);
3196 
3197  // Create a texture and fill it in with some data to workaround an OpenGL error
3198  PT(Texture) tex = new Texture(light->get_name());
3199  if (is_point) {
3200  if (light->_sb_xsize != light->_sb_ysize) {
3201  display_cat.error()
3202  << "PointLight shadow buffers must have an equal width and height!\n";
3203  }
3204  tex->setup_cube_map(light->_sb_xsize, Texture::T_unsigned_byte, Texture::F_depth_component);
3205  } else {
3206  tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_unsigned_byte, Texture::F_depth_component);
3207  }
3208  tex->make_ram_image();
3209  sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
3210 
3211  // Set the wrap mode
3212  if (is_point) {
3213  tex->set_wrap_u(SamplerState::WM_clamp);
3214  tex->set_wrap_v(SamplerState::WM_clamp);
3215  } else {
3216  tex->set_wrap_u(SamplerState::WM_border_color);
3217  tex->set_wrap_v(SamplerState::WM_border_color);
3218  tex->set_border_color(LVecBase4(1, 1, 1, 1));
3219  }
3220 
3222  // If we have the ARB_shadow extension, enable shadow filtering.
3223  tex->set_minfilter(SamplerState::FT_shadow);
3224  tex->set_magfilter(SamplerState::FT_shadow);
3225  } else {
3226  // We only accept linear - this tells the GPU to use hardware PCF.
3227  tex->set_minfilter(SamplerState::FT_linear);
3228  tex->set_magfilter(SamplerState::FT_linear);
3229  }
3230 
3231  // Assign display region(s) to the buffer and camera
3232  if (is_point) {
3233  for (int i = 0; i < 6; ++i) {
3234  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3235  dr->set_lens_index(i);
3236  dr->set_target_tex_page(i);
3237  dr->set_camera(light_np);
3238  dr->set_clear_depth_active(true);
3239  }
3240  } else {
3241  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3242  dr->set_camera(light_np);
3243  dr->set_clear_depth_active(true);
3244  }
3245  light->_sbuffers[this] = sbuffer;
3246 
3247  return tex;
3248 }
3249 
3250 ////////////////////////////////////////////////////////////////////
3251 // Function: GraphicsStateGuardian::has_extension
3252 // Access: Public, Virtual
3253 // Description: Returns true if the GSG implements the extension
3254 // identified by the given string. This currently
3255 // is only implemented by the OpenGL back-end.
3256 ////////////////////////////////////////////////////////////////////
3257 bool GraphicsStateGuardian::
3258 has_extension(const string &extension) const {
3259  return false;
3260 }
3261 
3262 ////////////////////////////////////////////////////////////////////
3263 // Function: GraphicsStateGuardian::get_driver_vendor
3264 // Access: Public, Virtual
3265 // Description: Returns the vendor of the video card driver
3266 ////////////////////////////////////////////////////////////////////
3269  return string();
3270 }
3271 
3272 ////////////////////////////////////////////////////////////////////
3273 // Function: GraphicsStateGuardian::get_driver_renderer
3274 // Access: Public, Virtual
3275 // Description: Returns GL_Renderer
3276 ////////////////////////////////////////////////////////////////////
3278  return string();
3279 }
3280 
3281 ////////////////////////////////////////////////////////////////////
3282 // Function: GraphicsStateGuardian::get_driver_version
3283 // Access: Public, Virtual
3284 // Description: Returns driver version
3285 // This has an implementation-defined meaning, and may
3286 // be "" if the particular graphics implementation
3287 // does not provide a way to query this information.
3288 ////////////////////////////////////////////////////////////////////
3291  return string();
3292 }
3293 
3294 ////////////////////////////////////////////////////////////////////
3295 // Function: GraphicsStateGuardian::get_driver_version_major
3296 // Access: Public, Virtual
3297 // Description: Returns major version of the video driver.
3298 // This has an implementation-defined meaning, and may
3299 // be -1 if the particular graphics implementation
3300 // does not provide a way to query this information.
3301 ////////////////////////////////////////////////////////////////////
3304  return -1;
3305 }
3306 
3307 ////////////////////////////////////////////////////////////////////
3308 // Function: GraphicsStateGuardian::get_driver_version_minor
3309 // Access: Public, Virtual
3310 // Description: Returns the minor version of the video driver.
3311 // This has an implementation-defined meaning, and may
3312 // be -1 if the particular graphics implementation
3313 // does not provide a way to query this information.
3314 ////////////////////////////////////////////////////////////////////
3317  return -1;
3318 }
3319 
3320 ////////////////////////////////////////////////////////////////////
3321 // Function: GraphicsStateGuardian::get_driver_shader_version_major
3322 // Access: Public, Virtual
3323 // Description: Returns the major version of the shader model.
3324 ////////////////////////////////////////////////////////////////////
3327  return -1;
3328 }
3329 
3330 ////////////////////////////////////////////////////////////////////
3331 // Function: GraphicsStateGuardian::get_driver_shader_version_minor
3332 // Access: Public, Virtual
3333 // Description: Returns the minor version of the shader model.
3334 ////////////////////////////////////////////////////////////////////
3337  return -1;
3338 }
void get_linear_range(PN_stdfloat &onset, PN_stdfloat &opaque)
Retrieves the current onset and offset ranges.
Definition: fog.cxx:197
void clear_bit(int index)
Sets the nth bit off.
Definition: bitMask.I:238
const TransformState * get_cs_world_transform() const
Returns the position from the starting node relative to the camera, in the GSG&#39;s internal coordinate ...
Definition: sceneSetup.I:341
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
A light shining from infinitely far away in a particular direction, like sunlight.
virtual int get_driver_version_major()
Returns major version of the video driver.
RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop)
Returns a RenderBuffer object suitable for operating on the requested set of buffers.
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
virtual Light * as_light()
Cross-casts the node to a Light pointer, if it is one of the four kinds of Light nodes, or returns NULL if it is not.
Definition: pandaNode.cxx:2528
const float * get_data() const
Returns the address of the first of the four data elements in the vector.
Definition: lvecBase4.h:745
The abstract interface to all kinds of lights.
Definition: light.h:42
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected points.
virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into system memory...
virtual void end_frame(Thread *current_thread)
Called after each frame is rendered, to allow the GSG a chance to do any internal cleanup after rende...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
virtual bool depth_offset_decals()
Returns true if this GSG can implement decals using a DepthOffsetAttrib, or false if that is unreliab...
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
This is a const pointer to an InternalName, and should be used in lieu of a CPT(InternalName) in func...
Definition: internalName.h:197
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: geomContext.h:39
virtual void release_shader(ShaderContext *sc)
Releases the resources allocated by prepare_shader.
PN_stdfloat get_exp_density() const
Returns the density of the fog for exponential calculations.
Definition: fog.I:228
virtual TextureContext * prepare_texture(Texture *tex)
Creates whatever structures the GSG requires to represent the texture internally, and returns a newly...
const LColor & get_ambient() const
Returns the ambient color setting, if it has been set.
Definition: material.I:82
This is a base class for GraphicsWindow (actually, GraphicsOutput) and DisplayRegion, both of which are conceptually rectangular regions into which drawing commands may be issued.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
int get_pad_z_size() const
Returns size of the pad region.
Definition: texture.I:731
virtual void release_index_buffer(IndexBufferContext *ibc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the IndexBu...
virtual void release_geom(GeomContext *gc)
Frees the resources previously allocated via a call to prepare_geom(), including deleting the GeomCon...
static WindowProperties size(int x_size, int y_size)
Returns a WindowProperties structure with only the size specified.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:45
This loader request will call Texture::get_ram_image() in a sub-thread, to force the texture&#39;s image ...
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
Definition: lmatrix.h:2397
bool get_supports_shadow_filter() const
Returns true if this particular GSG supports the filter mode FT_shadow for depth textures.
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of &quot;patches&quot;, which can only be processed by a tessellation shader.
virtual CoordinateSystem get_internal_coordinate_system() const
Returns the coordinate system used internally by the GSG.
virtual bool update_texture(TextureContext *tc, bool force)
Ensures that the current Texture data is refreshed onto the GSG.
bool is_off() const
Returns true if the MaterialAttrib is an &#39;off&#39; MaterialAttrib, indicating that it should disable the ...
int get_priority() const
Returns the task&#39;s current priority value.
Definition: asyncTask.I:209
Indicates which, if any, material should be applied to geometry.
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
static int get_max_priority()
Returns the maximum priority number (sometimes called override) that may be set on any node...
static void remove_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG destructor to remove a GSG from the available list.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
virtual PN_stdfloat get_exponent() const
For spotlights, returns the exponent that controls the amount of light falloff from the center of the...
Definition: light.cxx:87
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
void clear()
Sets all the bits in the BitMask off.
Definition: bitMask.I:561
A node that contains a Lens.
Definition: lensNode.h:32
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Definition: nodePath.cxx:925
virtual bool get_supports_cg_profile(const string &name) const
Returns true if this particular GSG supports the specified Cg Shader Profile.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:57
This is a special class object that holds all the information returned by a particular GSG to indicat...
virtual bool set_gamma(PN_stdfloat gamma)
Set gamma.
unsigned int get_right_eye_color_mask() const
Returns the color mask in effect when rendering a right-eye view in red_blue stereo mode...
virtual void dispatch_compute(int size_x, int size_y, int size_z)
Dispatches a currently bound compute shader using the given work group counts.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
A list of tasks, for instance as returned by some of the AsyncTaskManager query functions.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
void traverse_prepared_textures(TextureCallback *func, void *callback_arg)
Calls the indicated function on all currently-prepared textures, or until the callback function retur...
Definition: shader.h:50
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
Definition: loader.h:47
This is a special class object that holds all the information returned by a particular GSG to indicat...
bool is_identity() const
Returns true if the ColorScaleAttrib is an identity attrib, false if it is either an off attrib or it...
Material * get_material() const
If the MaterialAttrib is not an &#39;off&#39; MaterialAttrib, returns the material that is associated...
GraphicsPipe * get_pipe() const
Returns the graphics pipe on which this GSG was created.
bool has_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:284
virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const
This function will compute the distance to the indicated point, assumed to be in eye coordinates...
virtual void remove_window(GraphicsOutputBase *window)
This is simply a transparent call to GraphicsEngine::remove_window().
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:74
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
A light source that seems to illuminate all points in space at once.
Definition: ambientLight.h:29
void set_active(bool active)
Sets the active flag associated with the GraphicsStateGuardian.
virtual void restore_gamma()
Restore original gamma setting.
This functions similarly to a LightAttrib.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
Type get_color_type() const
Returns the type of color specified by this ColorAttrib.
Definition: colorAttrib.I:46
Texture * get_texture() const
Returns the pointer to the associated Texture object.
PN_stdfloat get_shininess() const
Returns the shininess exponent of the material.
Definition: material.I:217
virtual SceneSetup * get_scene() const
Returns the current SceneSetup object.
virtual void release_vertex_buffer(VertexBufferContext *vbc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the VertexB...
static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg)
Removes all the mungers from the registry that are associated with the indicated GSG.
Definition: geomMunger.I:67
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Definition: geom.h:401
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
void do_issue_color()
This method is defined in the base class because it is likely that this functionality will be used fo...
virtual void release_sampler(SamplerContext *sc)
Frees the resources previously allocated via a call to prepare_sampler(), including deleting the Samp...
A table of objects that are saved within the graphics context for reference by handle later...
int get_buffer_mask() const
Converts the non-aux bitplanes of the framebuffer into a RenderBuffer::Type.
virtual GeomContext * prepare_geom(Geom *geom)
Prepares the indicated Geom for retained-mode rendering, by creating whatever structures are necessar...
static const LMatrix4f & convert_mat(CoordinateSystem from, CoordinateSystem to)
Returns a matrix that transforms from the indicated coordinate system to the indicated coordinate sys...
Definition: lmatrix.cxx:656
virtual int get_supported_geom_rendering() const
Returns the union of Geom::GeomRendering values that this particular GSG can support directly...
const LColor & get_emission() const
Returns the emission color setting, if it has been set.
Definition: material.I:193
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
Definition: pStatGPUTimer.h:41
The ShaderContext is meant to contain the compiled version of a shader string.
Definition: shaderContext.h:35
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:34
Applies a Fog to the geometry at and below this node.
Definition: fogAttrib.h:27
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips.
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
double get_dt(Thread *current_thread=Thread::get_current_thread()) const
Returns the elapsed time for the previous frame: the number of seconds elapsed between the last two c...
Definition: clockObject.I:141
static Loader * get_global_ptr()
Returns a pointer to the global Loader.
Definition: loader.I:267
A container for the various kinds of properties we might ask to have on a graphics window before we o...
const LColor & get_color() const
Returns the color of the fog.
Definition: fog.I:53
void clear_flash_texture()
Resets the &quot;flash texture&quot;, so that no textures will flash.
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
int get_z_size() const
Returns the depth of the texture image in texels.
Definition: texture.I:663
const LColor & get_color() const
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
Definition: colorAttrib.I:58
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
virtual string get_driver_vendor()
Returns the vendor of the video card driver.
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.I:48
const LVector3 & get_direction() const
Returns the direction in which the light is aimed.
const Shader::ShaderPtrData * fetch_ptr_parameter(const Shader::ShaderPtrSpec &spec)
Return a pointer to struct ShaderPtrData.
Specifies how atmospheric fog effects are applied to geometry.
Definition: fog.h:46
virtual PreparedGraphicsObjects * get_prepared_objects()
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles.
const LVecBase4 & get_scale() const
Returns the scale to be applied to colors.
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
Definition: clockObject.I:113
A container for geometry primitives.
Definition: geom.h:58
virtual void begin_occlusion_query()
Begins a new occlusion query.
virtual void release_texture(TextureContext *tc)
Frees the resources previously allocated via a call to prepare_texture(), including deleting the Text...
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments.
NodePath get_on_plane(int n) const
Returns the nth plane enabled by the attribute, sorted in render order.
A light originating from a single point in space, and shining in a particular direction, with a cone-shaped falloff.
Definition: spotlight.h:37
const LColor & get_specular() const
Returns the specular color setting, if it has been set.
Definition: material.I:156
virtual void do_issue_light()
This implementation of do_issue_light() assumes we have a limited number of hardware lights available...
A lightweight class that represents a single thread of execution to PStats.
Definition: pStatThread.h:31
int get_tex_view_offset()
Returns the current texture view offset for this DisplayRegion.
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:27
virtual ShaderContext * prepare_shader(Shader *shader)
Compile a vertex/fragment shader body.
const TransformState * get_world_transform() const
Returns the position of the starting node relative to the camera.
Definition: sceneSetup.I:295
int get_num_on_planes() const
Returns the number of planes that are enabled by the attribute.
int get_num_on_lights() const
Returns the number of lights that are turned on by the attribute.
Definition: lightAttrib.I:49
This is a base class for the various different classes that represent the result of a frame of render...
Defines the way an object appears in the presence of lighting.
Definition: material.h:34
virtual int get_driver_shader_version_minor()
Returns the minor version of the shader model.
virtual SamplerContext * prepare_sampler(const SamplerState &sampler)
Creates whatever structures the GSG requires to represent the sampler internally, and returns a newly...
Applies a scale to colors in the scene graph and on vertices.
virtual int get_driver_shader_version_major()
Returns the major version of the shader model.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
const LMatrix4 & get_mat() const
Returns the transformation matrix associated with the default texture stage.
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:39
virtual int get_driver_version_minor()
Returns the minor version of the video driver.
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader, bool force)
Called before a sequence of draw_primitive() functions are called, this should prepare the vertex dat...
This is a special class object that holds a handle to the sampler state object given by the graphics ...
bool has_alpha_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the alpha component (ignoring RGB)...
static const LMatrix4f & zeros_mat()
Returns an matrix filled with zeros.
Definition: lmatrix.h:923
Applies a transform matrix to UV&#39;s before they are rendered.
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:43
virtual bool get_supports_multisample() const
Returns true if this particular GSG supports using the multisample bits to provide antialiasing...
bool get_swap_eyes() const
Returns the current setting of the &quot;swap eyes&quot; flag.
void set_priority(int priority)
Specifies a priority value for this task.
Definition: asyncTask.cxx:376
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle fans.
const TransformState * get_camera_transform() const
Returns the position of the camera relative to the starting node.
Definition: sceneSetup.I:271
A thread; that is, a lightweight process.
Definition: thread.h:51
int get_pad_y_size() const
Returns size of the pad region.
Definition: texture.I:720
A derivative of Light and of Camera.
Definition: lightLensNode.h:35
virtual bool has_extension(const string &extension) const
Returns true if the GSG implements the extension identified by the given string.
This is a special class object that holds all the information returned by a particular GSG to indicat...
Encapsulates all the communication with a particular instance of a given rendering backend...
int get_pad_x_size() const
Returns size of the pad region.
Definition: texture.I:709
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a &quot;scene&quot; (usual...
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of line strips.
const LColor & get_color() const
Returns the basic color of the light.
Definition: light.I:70
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise...
Definition: pStatClient.h:269
virtual string get_driver_version()
Returns driver version This has an implementation-defined meaning, and may be &quot;&quot; if the particular gr...
virtual VertexBufferContext * prepare_vertex_buffer(GeomVertexArrayData *data)
Prepares the indicated buffer for retained-mode rendering.
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:61
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:30
static void create_gamma_table(PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table)
Create a gamma table.
virtual const LColor & get_specular_color() const
Returns the color of specular highlights generated by the light.
Definition: light.cxx:99
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:1187
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
LVecBase3f get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
Definition: lmatrix.h:1312
An abstract base class for GraphicsOutput, for all the usual reasons.
Returned from a GSG in response to begin_occlusion_query() .
This class is the main interface to controlling the render process.
virtual void reset()
Resets all internal state as if the gsg were newly created.
const LMatrix4 * fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LMatrix4 &t, int index)
See fetch_specified_value.
This is the preferred interface for loading textures from image files.
Definition: texturePool.h:40
virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into texture memory...
virtual bool begin_frame(Thread *current_thread)
Called before each frame is rendered, to allow the GSG a chance to do any internal cleanup before beg...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
Defines the details about the Collectors: the name, the suggested color, etc.
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:35
const LMatrix4 * fetch_specified_value(Shader::ShaderMatSpec &spec, int altered)
The gsg contains a large number of useful matrices:
NodePath get_on_light(int n) const
Returns the nth light turned on by the attribute, sorted in render order.
Definition: lightAttrib.I:60
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
bool set_scene(SceneSetup *scene_setup)
Sets the SceneSetup object that indicates the initial camera position, etc.
virtual IndexBufferContext * prepare_index_buffer(GeomPrimitive *data)
Prepares the indicated buffer for retained-mode rendering.
void flush_timer_queries()
Called by the graphics engine on the draw thread to check the status of the running timer queries and...
Manages the communications to report statistics via a network connection to a remote PStatServer...
Definition: pStatClient.h:261
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
virtual bool prepare_lens()
Makes the current lens (whichever lens was most recently specified with set_scene()) active...
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:782
Fog * get_fog() const
If the FogAttrib is not an &#39;off&#39; FogAttrib, returns the fog that is associated.
Definition: fogAttrib.I:45
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:38
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
Definition: nodePath.I:965
Computes texture coordinates for geometry automatically based on vertex position and/or normal...
Definition: texGenAttrib.h:36
const LColor & get_diffuse() const
Returns the diffuse color setting, if it has been set.
Definition: material.I:119
virtual void finish_decal()
Called during draw to clean up after decals are finished.
void set_flash_texture(Texture *tex)
Sets the &quot;flash texture&quot;.
Lens::StereoChannel get_stereo_channel() const
Returns whether the DisplayRegion is specified as the left or right channel of a stereo pair...
int get_y_size() const
Returns the height of the texture image in texels.
Definition: texture.I:650
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer, etc.) of a drawing region.
Definition: renderBuffer.h:30
static TextureStage * get_alpha_scale_texture_stage()
Returns the TextureStage that will be used to apply an alpha scale, if get_alpha_scale_via_texture() ...
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
int get_max_texture_stages() const
Returns the maximum number of simultaneous textures that may be applied to geometry with multitexturi...
static const LMatrix4f & ones_mat()
Returns an matrix filled with ones.
Definition: lmatrix.h:913
void set_coordinate_system(CoordinateSystem cs)
Changes the coordinate system in effect on this particular gsg.
A light originating from a single point in space, and shining in all directions.
Definition: pointLight.h:27
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition: sceneSetup.I:164
int get_x_size() const
Returns the width of the texture image in texels.
Definition: texture.I:638
A node that contains a plane.
Definition: planeNode.h:39
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
Definition: lmatrix.h:1667
PN_stdfloat get_gamma(PN_stdfloat gamma)
Get the current gamma setting.
void add_frame(const PStatFrameData &frame_data)
This is a slightly lower-level version of new_frame that also specifies the data to send for this fra...
Definition: pStatThread.I:119
This is the data for one array of a GeomVertexData structure.
virtual const LVecBase3 & get_attenuation() const
Returns the terms of the attenuation equation for the light.
Definition: light.cxx:113
Indicates which set of lights should be considered &quot;on&quot; to illuminate geometry at this level and belo...
Definition: lightAttrib.h:33
unsigned int get_left_eye_color_mask() const
Returns the color mask in effect when rendering a left-eye view in red_blue stereo mode...
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a &quot;scene&quot; ...
Texture * get_flash_texture() const
Returns the current &quot;flash texture&quot;, if any, or NULL if none.
LVecBase3f xform_vec(const LVecBase3f &v) const
The matrix transforms a 3-component vector (without translation component) and returns the result...
Definition: lmatrix.h:1707
virtual string get_driver_renderer()
Returns GL_Renderer.
virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id)
Called the first time a particular light has been bound to a given id within a frame, this should set up the associated hardware light with the light&#39;s properties.
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
Definition: lensNode.I:60