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