41PStatCollector GraphicsOutput::_make_current_pcollector(
"Draw:Make current");
42PStatCollector GraphicsOutput::_copy_texture_pcollector(
"Draw:Copy texture");
47 CubeFaceDef(
const char *name,
const LPoint3 &look_at,
const LVector3 &up) :
48 _name(name), _look_at(look_at), _up(up) { }
55static CubeFaceDef cube_faces[6] = {
56 CubeFaceDef(
"positive_x", LPoint3(1, 0, 0), LVector3(0, -1, 0)),
57 CubeFaceDef(
"negative_x", LPoint3(-1, 0, 0), LVector3(0, -1, 0)),
58 CubeFaceDef(
"positive_y", LPoint3(0, 1, 0), LVector3(0, 0, 1)),
59 CubeFaceDef(
"negative_y", LPoint3(0, -1, 0), LVector3(0, 0, -1)),
60 CubeFaceDef(
"positive_z", LPoint3(0, 0, 1), LVector3(0, -1, 0)),
61 CubeFaceDef(
"negative_z", LPoint3(0, 0, -1), LVector3(0, -1, 0))
76 bool default_stereo_flags) :
77 _lock(
"GraphicsOutput"),
78 _cull_window_pcollector(_cull_pcollector, name),
79 _draw_window_pcollector(_draw_pcollector, name),
80 _clear_window_pcollector(_draw_window_pcollector,
"Clear"),
90 _fb_properties = fb_prop;
92 _creation_flags = flags;
94 _is_nonzero_size =
false;
97 _is_nonzero_size = (_size[0] > 0 && _size[1] > 0);
99 if (_creation_flags & GraphicsPipe::BF_size_track_host) {
101 _is_nonzero_size =
true;
106 _target_tex_page = -1;
107 _prev_page_dr =
nullptr;
110 _got_child_sort =
false;
111 _internal_sort_index = 0;
112 _inverted = window_inverted;
113 _swap_eyes = swap_eyes;
114 _red_blue_stereo =
false;
115 _left_eye_color_mask = 0x0f;
116 _right_eye_color_mask = 0x0f;
117 _side_by_side_stereo =
false;
118 _sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
119 _sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
120 _delete_flag =
false;
122 if (_fb_properties.is_single_buffered()) {
123 _draw_buffer_type = RenderBuffer::T_front;
125 _draw_buffer_type = RenderBuffer::T_back;
128 if (default_stereo_flags) {
131 _red_blue_stereo = red_blue_stereo && !fb_prop.is_stereo();
132 if (_red_blue_stereo) {
133 _left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
134 _right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
136 _side_by_side_stereo = side_by_side_stereo && !fb_prop.is_stereo();
137 if (_side_by_side_stereo) {
138 _sbs_left_dimensions.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
139 sbs_left_dimensions[2], sbs_left_dimensions[3]);
140 _sbs_right_dimensions.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
141 sbs_right_dimensions[2], sbs_right_dimensions[3]);
148 _overlay_display_region = make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
149 _overlay_display_region->set_active(
false);
150 _overlay_display_region->set_scissor_enabled(
false);
154 CDWriter cdata(_cycler,
true);
155 cdata->_active =
true;
159 set_clear_color_active(
true);
160 set_clear_depth_active(
true);
161 set_clear_stencil_active(
true);
162 set_clear_color(background_color.get_value());
174 nassertv(_pipe ==
nullptr);
179 TotalDisplayRegions::iterator dri;
180 for (dri = _total_display_regions.begin();
181 dri != _total_display_regions.end();
183 (*dri)->_window =
nullptr;
186 _total_display_regions.clear();
187 _overlay_display_region =
nullptr;
196 CDWriter cdata(_cycler,
true);
197 cdata->_textures.clear();
198 ++(cdata->_textures_seq);
199 throw_event(
"render-texture-targets-changed");
238 RenderTexturePlane plane) {
240 if (mode == RTM_none) {
246 if (tex ==
nullptr) {
261 if (plane == RTP_COUNT) {
263 case Texture::F_depth_stencil:
264 plane = RTP_depth_stencil;
267 case Texture::F_depth_component:
268 case Texture::F_depth_component16:
269 case Texture::F_depth_component24:
270 case Texture::F_depth_component32:
283 if (plane == RTP_depth) {
284 _fb_properties.setup_depth_texture(tex);
287 }
else if (plane == RTP_depth_stencil) {
289 if (_fb_properties.get_float_depth()) {
296 }
else if (plane == RTP_color ||
297 plane == RTP_aux_rgba_0 ||
298 plane == RTP_aux_rgba_1 ||
299 plane == RTP_aux_rgba_2 ||
300 plane == RTP_aux_rgba_3) {
301 _fb_properties.setup_color_texture(tex);
304 }
else if (plane == RTP_aux_hrgba_0 ||
305 plane == RTP_aux_hrgba_1 ||
306 plane == RTP_aux_hrgba_2 ||
307 plane == RTP_aux_hrgba_3) {
311 }
else if (plane == RTP_aux_float_0 ||
312 plane == RTP_aux_float_1 ||
313 plane == RTP_aux_float_2 ||
314 plane == RTP_aux_float_3) {
320 display_cat.error() <<
321 "add_render_texture: invalid bitplane specified.\n";
330 if (_fb_properties.is_stereo() && plane == RTP_color) {
339 if (mode == RTM_bind_or_copy) {
340 mode = RTM_copy_texture;
341 }
else if (mode == RTM_bind_layered) {
344 display_cat.error() <<
345 "add_render_texture: RTM_bind_layered was requested but "
346 "render-to-texture is not supported or has been disabled!\n";
350 if (mode == RTM_bind_layered && _gsg !=
nullptr && !_gsg->get_supports_geometry_shaders()) {
353 display_cat.warning() <<
354 "add_render_texture: RTM_bind_layered was requested but "
355 "geometry shaders are not supported!\n";
358 if (mode == RTM_bind_or_copy || mode == RTM_bind_layered) {
362 else if ((plane == RTP_depth || plane == RTP_depth_stencil) && _fb_properties.get_depth_bits() == 0) {
365 <<
"add_render_texture: can't copy depth from framebuffer without depth bits!\n";
369 CDWriter cdata(_cycler,
true);
370 RenderTexture result;
371 result._texture = tex;
372 result._plane = plane;
373 result._rtm_mode = mode;
374 cdata->_textures.push_back(result);
375 ++(cdata->_textures_seq);
377 throw_event(
"render-texture-targets-changed");
389 display_cat.warning() <<
390 "Using deprecated setup_render_texture interface.\n";
394 }
else if (allow_bind) {
407 CDLockedReader cdata(_cycler);
408 if (cdata->_active != active) {
410 cdataw->_active = active;
423 CDLockedReader cdata(_cycler);
424 if (!cdata->_active) {
428 if (cdata->_one_shot_frame != -1) {
449 if (cdata->_active_display_regions_stale) {
450 CDWriter cdataw(((GraphicsOutput *)
this)->_cycler, cdata,
false);
451 ((GraphicsOutput *)
this)->do_determine_display_regions(cdataw);
452 return !cdataw->_active_display_regions.empty();
454 return !cdata->_active_display_regions.empty();
475 CDWriter cdata(_cycler,
true);
479 cdata->_one_shot_frame = -1;
489 CDReader cdata(_cycler);
506 if (_inverted != inverted) {
507 _inverted = inverted;
512 TotalDisplayRegions::iterator dri;
513 for (dri = _total_display_regions.begin();
514 dri != _total_display_regions.end();
535 LVecBase4 left, right;
536 left.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
537 sbs_left_dimensions[2], sbs_left_dimensions[3]);
538 right.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
539 sbs_right_dimensions[2], sbs_right_dimensions[3]);
556 const LVecBase4 &sbs_left_dimensions,
557 const LVecBase4 &sbs_right_dimensions) {
558 _side_by_side_stereo = side_by_side_stereo;
559 if (_side_by_side_stereo) {
560 _sbs_left_dimensions = sbs_left_dimensions;
561 _sbs_right_dimensions = sbs_right_dimensions;
563 _sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
564 _sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
577 for (
int i = 0; i < (int)_hold_textures.size(); i++) {
578 if (_hold_textures[i].is_valid_pointer()) {
593 if (_gsg !=
nullptr &&
594 _gsg->get_engine() !=
nullptr) {
595 _gsg->get_engine()->set_window_sort(
this, sort);
611 if (
is_stereo() && default_stereo_camera) {
630 if (_side_by_side_stereo) {
637 return new DisplayRegion(
this, dimensions);
648 PT(DisplayRegion) left, right;
650 if (_side_by_side_stereo) {
653 PN_stdfloat left_l = _sbs_left_dimensions[0];
654 PN_stdfloat left_b = _sbs_left_dimensions[2];
655 PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
656 PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
657 LVecBase4 left_dimensions(dimensions[0] * left_w + left_l,
658 dimensions[1] * left_w + left_l,
659 dimensions[2] * left_h + left_b,
660 dimensions[3] * left_h + left_b);
661 left =
new DisplayRegion(
this, left_dimensions);
663 PN_stdfloat right_l = _sbs_right_dimensions[0];
664 PN_stdfloat right_b = _sbs_right_dimensions[2];
665 PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
666 PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
667 LVecBase4 right_dimensions(dimensions[0] * right_w + right_l,
668 dimensions[1] * right_w + right_l,
669 dimensions[2] * right_h + right_b,
670 dimensions[3] * right_h + right_b);
671 right =
new DisplayRegion(
this, right_dimensions);
674 DisplayRegion *t = left;
682 left =
new DisplayRegion(
this, dimensions);
683 right =
new DisplayRegion(
this, dimensions);
689 right->set_clear_depth_active(
true);
692 right->set_clear_stencil_active(
true);
713 nassertr(display_region != _overlay_display_region,
false);
717 DCAST_INTO_R(sdr, display_region,
false);
722 return do_remove_display_region(display_region);
733 TotalDisplayRegions::iterator dri;
734 for (dri = _total_display_regions.begin();
735 dri != _total_display_regions.end();
737 DisplayRegion *display_region = (*dri);
738 if (display_region != _overlay_display_region) {
741 display_region->_window =
nullptr;
744 _total_display_regions.clear();
745 _total_display_regions.push_back(_overlay_display_region);
747 OPEN_ITERATE_ALL_STAGES(_cycler) {
748 CDStageWriter cdata(_cycler, pipeline_stage);
749 cdata->_active_display_regions_stale =
true;
751 CLOSE_ITERATE_ALL_STAGES(_cycler);
769 nassertv(display_region->
get_window() ==
this);
770 _overlay_display_region = display_region;
780 return _total_display_regions.size();
791 determine_display_regions();
792 PT(DisplayRegion) result;
794 LightMutexHolder holder(_lock);
795 if (n >= 0 && n < (
int)_total_display_regions.size()) {
796 result = _total_display_regions[n];
810 determine_display_regions();
811 CDReader cdata(_cycler);
812 return cdata->_active_display_regions.size();
823 determine_display_regions();
825 CDReader cdata(_cycler);
826 if (n >= 0 && n < (
int)cdata->_active_display_regions.size()) {
827 return cdata->_active_display_regions[n];
864 props.set_rgb_color(1);
866 props.set_alpha_bits(1);
867 props.set_depth_bits(1);
869 if (fbp ==
nullptr) {
873 int flags = GraphicsPipe::BF_refuse_window;
874 if (textures_power_2 != ATS_none) {
875 flags |= GraphicsPipe::BF_size_power_2;
877 if (tex !=
nullptr &&
879 flags |= GraphicsPipe::BF_size_square;
882 GraphicsOutput *buffer =
get_gsg()->get_engine()->
888 if (buffer !=
nullptr) {
889 if (buffer->
get_gsg() ==
nullptr ||
890 buffer->
get_gsg()->get_prepared_objects() !=
get_gsg()->get_prepared_objects()) {
929 display_cat.warning()
930 <<
"Cannot make dynamic cube map; GSG does not support cube maps.\n";
933 if (max_dimension > 0) {
934 size = std::min(max_dimension, size);
946 tex->setup_cube_map();
947 tex->set_wrap_u(SamplerState::WM_clamp);
948 tex->set_wrap_v(SamplerState::WM_clamp);
949 GraphicsOutput *buffer;
961 for (
int i = 0; i < 6; i++) {
963 camera->set_lens(lens);
964 camera->set_camera_mask(camera_mask);
966 camera_np.
look_at(cube_faces[i]._look_at, cube_faces[i]._up);
992 if (_texture_card ==
nullptr) {
995 strip->set_shade_model(Geom::SM_uniform);
996 strip->add_next_vertices(4);
997 strip->close_primitive();
999 geom->add_primitive(strip);
1000 _texture_card =
new GeomNode(
"texture card");
1001 _texture_card->add_geom(geom);
1010 CDReader cdata(_cycler);
1011 RenderTextures::const_iterator ri;
1012 for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1013 Texture *texture = (*ri)._texture;
1014 if ((texture->
get_format() != Texture::F_depth_stencil)) {
1102 <<
"Resetting " << get_type() <<
"\n";
1125 _is_nonzero_size = (x > 0 && y > 0);
1130 for (DisplayRegion *dr : _total_display_regions) {
1131 dr->compute_pixels_all_stages(fb_x_size, fb_y_size);
1134 if (_texture_card !=
nullptr && _texture_card->get_num_geoms() > 0) {
1135 _texture_card->modify_geom(0)->set_vertex_data(create_texture_card_vdata(x, y));
1149 if (display_cat.is_spam()) {
1151 <<
"clear(): " << get_type() <<
" "
1152 <<
get_name() <<
" " << (
void *)
this <<
"\n";
1155 nassertv(_gsg !=
nullptr);
1158 _gsg->prepare_display_region(&dr_reader);
1192 if (new_target_tex_page != -1 && new_target_tex_page != _target_tex_page) {
1194 if (new_target_tex_page == -1) {
1195 new_target_tex_page = 0;
1197 int old_target_tex_page = _target_tex_page;
1198 DisplayRegion *old_page_dr = _prev_page_dr;
1199 _target_tex_page = new_target_tex_page;
1200 _prev_page_dr = new_dr->get_object();
1202 CDReader cdata(_cycler);
1203 RenderTextures::const_iterator ri;
1204 for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1205 RenderTextureMode rtm_mode = (*ri)._rtm_mode;
1206 RenderTexturePlane plane = (*ri)._plane;
1207 Texture *texture = (*ri)._texture;
1208 if (rtm_mode != RTM_none) {
1209 if (rtm_mode == RTM_bind_or_copy || rtm_mode == RTM_bind_layered) {
1215 }
else if (old_target_tex_page != -1) {
1219 nassertv(old_page_dr !=
nullptr);
1220 if (display_cat.is_debug()) {
1222 <<
"Copying texture for " <<
get_name() <<
" at scene change.\n";
1224 <<
"target_tex_page = " << old_target_tex_page <<
"\n";
1229 if (plane == RTP_color && _fb_properties.is_stereo()) {
1231 RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right);
1232 RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left);
1234 if (rtm_mode == RTM_copy_ram) {
1235 _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page,
1237 _gsg->framebuffer_copy_to_ram(texture, 1, old_target_tex_page,
1238 old_page_dr, right);
1240 _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page,
1242 _gsg->framebuffer_copy_to_texture(texture, 1, old_target_tex_page,
1243 old_page_dr, right);
1246 if (rtm_mode == RTM_copy_ram) {
1247 _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page,
1248 old_page_dr, buffer);
1250 _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page,
1251 old_page_dr, buffer);
1307 _flip_ready =
false;
1323void GraphicsOutput::
1324pixel_factor_changed() {
1334void GraphicsOutput::
1335prepare_for_deletion() {
1336 CDWriter cdata(_cycler,
true);
1337 cdata->_active =
false;
1341 RenderTextures::iterator ri;
1342 for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1343 if ((*ri)._rtm_mode == RTM_bind_or_copy || (*ri)._rtm_mode == RTM_bind_layered) {
1344 _hold_textures.push_back((*ri)._texture);
1347 cdata->_textures.clear();
1349 _delete_flag =
true;
1363void GraphicsOutput::
1364promote_to_copy_texture() {
1365 CDLockedReader cdata(_cycler);
1366 RenderTextures::const_iterator ri;
1368 bool any_bind =
false;
1369 for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1370 if ((*ri)._rtm_mode == RTM_bind_or_copy) {
1376 CDWriter cdataw(((GraphicsOutput *)
this)->_cycler, cdata,
true);
1377 RenderTextures::iterator ri;
1378 for (ri = cdataw->_textures.begin(); ri != cdataw->_textures.end(); ++ri) {
1379 if ((*ri)._rtm_mode == RTM_bind_or_copy) {
1380 (*ri)._rtm_mode = RTM_copy_texture;
1393bool GraphicsOutput::
1397 CDReader cdata(_cycler);
1398 RenderTextures::const_iterator ri;
1399 for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1400 RenderTextureMode rtm_mode = (*ri)._rtm_mode;
1401 if ((rtm_mode == RTM_none) || (rtm_mode == RTM_bind_or_copy)) {
1405 Texture *texture = (*ri)._texture;
1406 PStatTimer timer(_copy_texture_pcollector);
1408 if ((rtm_mode == RTM_copy_texture)||
1409 (rtm_mode == RTM_copy_ram)||
1410 ((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
1411 ((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
1412 if (display_cat.is_debug()) {
1414 <<
"Copying texture for " <<
get_name() <<
" at frame end.\n";
1416 <<
"target_tex_page = " << _target_tex_page <<
"\n";
1418 RenderTexturePlane plane = (*ri)._plane;
1420 if (plane == RTP_color) {
1425 bool copied =
false;
1426 DisplayRegion *dr = _overlay_display_region;
1427 if (_prev_page_dr !=
nullptr) {
1431 if (plane == RTP_color && _fb_properties.is_stereo()) {
1433 RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right);
1434 RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left);
1436 if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
1437 copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
1439 copied = _gsg->framebuffer_copy_to_ram(texture, 1, _target_tex_page,
1440 dr, right) && copied;
1442 copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page,
1444 copied = _gsg->framebuffer_copy_to_texture(texture, 1, _target_tex_page,
1445 dr, right) && copied;
1448 if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
1449 copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
1452 copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page,
1461 if (_trigger_copy !=
nullptr) {
1462 _trigger_copy->set_result(
nullptr);
1463 _trigger_copy =
nullptr;
1473create_texture_card_vdata(
int x,
int y) {
1474 PN_stdfloat xhi = 1.0;
1475 PN_stdfloat yhi = 1.0;
1480 xhi = (x * 1.0f) / xru;
1481 yhi = (y * 1.0f) / yru;
1486 PT(GeomVertexData) vdata =
new GeomVertexData
1487 (
"card", format, Geom::UH_static);
1489 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
1490 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
1491 GeomVertexWriter normal(vdata, InternalName::get_normal());
1493 vertex.add_data3(LVertex::rfu(-1.0f, 0.0f, 1.0f));
1494 vertex.add_data3(LVertex::rfu(-1.0f, 0.0f, -1.0f));
1495 vertex.add_data3(LVertex::rfu( 1.0f, 0.0f, 1.0f));
1496 vertex.add_data3(LVertex::rfu( 1.0f, 0.0f, -1.0f));
1498 texcoord.add_data2( 0.0f, yhi);
1499 texcoord.add_data2( 0.0f, 0.0f);
1500 texcoord.add_data2( xhi, yhi);
1501 texcoord.add_data2( xhi, 0.0f);
1503 normal.add_data3(LVector3::back());
1504 normal.add_data3(LVector3::back());
1505 normal.add_data3(LVector3::back());
1506 normal.add_data3(LVector3::back());
1517 LightMutexHolder holder(_lock);
1518 CDWriter cdata(_cycler,
true);
1519 cdata->_active_display_regions_stale =
true;
1521 _total_display_regions.push_back(display_region);
1523 return display_region;
1530bool GraphicsOutput::
1532 nassertr(display_region != _overlay_display_region,
false);
1534 PT(DisplayRegion) drp = display_region;
1535 TotalDisplayRegions::iterator dri =
1536 find(_total_display_regions.begin(), _total_display_regions.end(), drp);
1537 if (dri != _total_display_regions.end()) {
1540 display_region->_window =
nullptr;
1541 _total_display_regions.erase(dri);
1543 OPEN_ITERATE_ALL_STAGES(_cycler) {
1544 CDStageWriter cdata(_cycler, pipeline_stage);
1545 cdata->_active_display_regions_stale =
true;
1547 CLOSE_ITERATE_ALL_STAGES(_cycler);
1557void GraphicsOutput::
1558do_determine_display_regions(GraphicsOutput::CData *cdata) {
1559 cdata->_active_display_regions_stale =
false;
1561 cdata->_active_display_regions.clear();
1562 cdata->_active_display_regions.reserve(_total_display_regions.size());
1565 TotalDisplayRegions::const_iterator dri;
1566 for (dri = _total_display_regions.begin();
1567 dri != _total_display_regions.end();
1569 DisplayRegion *display_region = (*dri);
1571 cdata->_active_display_regions.push_back(display_region);
1572 display_region->set_active_index(index);
1575 display_region->set_active_index(-1);
1579 std::stable_sort(cdata->_active_display_regions.begin(),
1580 cdata->_active_display_regions.end(),
1581 IndirectLess<DisplayRegion>());
1590unsigned int GraphicsOutput::
1591parse_color_mask(
const string &word) {
1592 unsigned int result = 0;
1593 vector_string components;
1596 vector_string::const_iterator ci;
1597 for (ci = components.begin(); ci != components.end(); ++ci) {
1599 if (w ==
"red" || w ==
"r") {
1602 }
else if (w ==
"green" || w ==
"g") {
1605 }
else if (w ==
"blue" || w ==
"b") {
1608 }
else if (w ==
"yellow" || w ==
"y") {
1611 }
else if (w ==
"magenta" || w ==
"m") {
1614 }
else if (w ==
"cyan" || w ==
"c") {
1617 }
else if (w ==
"alpha" || w ==
"a") {
1620 }
else if (w ==
"off") {
1623 display_cat.warning()
1624 <<
"Invalid color in red-blue-stereo-colors: " << (*ci) <<
"\n";
1634GraphicsOutput::CData::
1640 _one_shot_frame = -1;
1641 _active_display_regions_stale =
false;
1647GraphicsOutput::CData::
1648CData(
const GraphicsOutput::CData ©) :
1649 _textures(copy._textures),
1650 _textures_seq(copy._textures_seq),
1651 _active(copy._active),
1652 _one_shot_frame(copy._one_shot_frame),
1653 _active_display_regions(copy._active_display_regions),
1654 _active_display_regions_stale(copy._active_display_regions_stale)
1663 return new CData(*
this);
1670operator << (std::ostream &out, GraphicsOutput::FrameMode fm) {
1672 case GraphicsOutput::FM_render:
1673 return out <<
"render";
1674 case GraphicsOutput::FM_parasite:
1675 return out <<
"parasite";
1676 case GraphicsOutput::FM_refresh:
1677 return out <<
"refresh";
1680 return out <<
"(**invalid GraphicsOutput::FrameMode(" << (int)fm <<
")**)";
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
static ConstPointerTo< RenderEffect > make(const NodePath &reference, int properties=P_rot)
Constructs a new CompassEffect object.
A single page of data maintained by a PipelineCycler.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
int get_target_tex_page() const
Returns the target page number associated with this particular DisplayRegion, or -1 if it is not asso...
A rectangular subregion within a window for rendering into.
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
set_camera
Sets the camera that is associated with this DisplayRegion.
set_target_tex_page
This is a special parameter that is only used when rendering the faces of a cube map or multipage and...
is_active
Returns the active flag associated with the DisplayRegion.
get_window
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
void cleanup()
Cleans up some pointers associated with the DisplayRegion to help reduce the chance of memory leaks d...
int get_draw_buffer_type() const
Returns the RenderBuffer into which the GSG should issue draw commands.
void set_clear_stencil_active(bool clear_stencil_active)
Toggles the flag that indicates whether the stencil buffer should be cleared every frame.
void set_clear_color_active(bool clear_color_active)
Toggles the flag that indicates whether the color buffer should be cleared every frame.
static int get_renderbuffer_type(int plane)
Returns the RenderBuffer::Type that corresponds to a RenderTexturePlane.
bool get_clear_depth_active() const
Returns the current setting of the flag that indicates whether the depth buffer should be cleared eve...
virtual bool is_any_clear_active() const
Returns true if any of the clear types (so far there are just color or depth) have been set active,...
void copy_clear_settings(const DrawableRegion ©)
Copies only the clear settings from the other drawable region.
bool get_clear_stencil_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
void set_clear_depth_active(bool clear_depth_active)
Toggles the flag that indicates whether the depth buffer should be cleared every frame.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
set_color_bits
Sets the number of requested color bits as a single number that represents the sum of the individual ...
A node that holds Geom objects, renderable pieces of geometry.
Defines a series of triangle strips.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
virtual void process_events()
Do whatever processing in the window thread is appropriate for this output object each frame.
void clear_render_textures()
If the GraphicsOutput is currently rendering to a texture, then all textures are dissociated from the...
int get_fb_x_size() const
Returns the internal width of the window or buffer.
set_inverted
Changes the current setting of the inverted flag.
get_num_active_display_regions
Returns the number of active DisplayRegions that have been created within the window.
get_pipe
Returns the GraphicsPipe that this window is associated with.
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
void add_render_texture(Texture *tex, RenderTextureMode mode, RenderTexturePlane bitplane=RTP_COUNT)
Creates a new Texture object, suitable for rendering the contents of this buffer into,...
set_active
Sets the active flag associated with the GraphicsOutput.
void set_side_by_side_stereo(bool side_by_side_stereo)
Enables side-by-side stereo mode on this particular window.
get_active_display_region
Returns the nth active DisplayRegion of those that have been created within the window.
is_active
Returns true if the window is ready to be rendered into, false otherwise.
get_gsg
Returns the GSG that is associated with this window.
virtual void clear_pipe()
Sets the window's _pipe pointer to NULL; this is generally called only as a precursor to deleting the...
void remove_all_display_regions()
Removes all display regions from the window, except the default one that is created with the window.
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
virtual bool share_depth_buffer(GraphicsOutput *graphics_output)
Will attempt to use the depth buffer of the input graphics_output.
set_one_shot
Changes the current setting of the one-shot flag.
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool get_delete_flag() const
Returns the current setting of the delete flag.
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram)
This is a deprecated interface that made sense back when GraphicsOutputs could only render into one t...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
StereoDisplayRegion * make_stereo_display_region()
Creates a new DisplayRegion that covers the entire window.
DisplayRegion * make_mono_display_region()
Creates a new DisplayRegion that covers the entire window.
virtual void unshare_depth_buffer()
Discontinue sharing the depth buffer.
get_supports_render_texture
Returns true if this particular GraphicsOutput can render directly into a texture,...
NodePath get_texture_card()
Returns a PandaNode containing a square polygon.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
get_num_display_regions
Returns the number of DisplayRegions that have been created within the window, active or otherwise.
get_child_sort
Returns the sort value of future offscreen buffers created by make_texture_sort().
get_one_shot
Returns the current setting of the one-shot flag.
int get_fb_y_size() const
Returns the internal height of the window or buffer.
DisplayRegion * make_display_region()
Creates a new DisplayRegion that covers the entire window.
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
void set_size_and_recalc(int x, int y)
Changes the x_size and y_size, then recalculates structures that depend on size.
bool remove_display_region(DisplayRegion *display_region)
Removes the indicated DisplayRegion from the window, and destructs it if there are no other reference...
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or,...
get_display_region
Returns the nth DisplayRegion of those that have been created within the window.
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
get_name
Returns the name that was passed to the GraphicsOutput constructor.
void set_overlay_display_region(DisplayRegion *display_region)
Replaces the special "overlay" DisplayRegion that is created for each window or buffer.
virtual void select_target_tex_page(int page)
Called internally when the window is in render-to-a-texture mode and we are in the process of renderi...
GraphicsOutput * make_cube_map(const std::string &name, int size, NodePath &camera_rig, DrawMask camera_mask=PandaNode::get_all_camera_mask(), bool to_ram=false, FrameBufferProperties *fbp=nullptr)
This is similar to make_texture_buffer() in that it allocates a separate buffer suitable for renderin...
bool is_stereo() const
Returns Returns true if this window can render stereo DisplayRegions, either through red-blue stereo ...
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or,...
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
GraphicsOutput * make_texture_buffer(const std::string &name, int x_size, int y_size, Texture *tex=nullptr, bool to_ram=false, FrameBufferProperties *fbp=nullptr)
Creates and returns an offscreen buffer for rendering into, the result of which will be a texture sui...
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
set_sort
Adjusts the sorting order of this particular GraphicsOutput, relative to other GraphicsOutputs.
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
get_max_cube_map_dimension
Returns the largest possible texture size in any one dimension for a cube map texture,...
get_supports_cube_map
Returns true if this GSG can render cube map textures.
A base class for any number of different kinds of lenses, linear and otherwise.
Similar to MutexHolder, but for a light mutex.
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void look_at(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the transform on this NodePath so that it rotates to face the indicated point in space.
void set_texture(Texture *tex, int priority=0)
Adds the indicated texture to the list of textures that will be rendered on the default texture stage...
PandaNode * node() const
Returns the referenced node of the path.
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
A lightweight class that represents a single element that may be timed and/or counted via stats.
void set_effect(const RenderEffect *effect)
Adds the indicated render effect to the scene graph on this node.
void add_child(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node.
A perspective-type lens: a normal camera.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
This is a special DisplayRegion wrapper that actually includes a pair of DisplayRegions internally: t...
get_right_eye
Returns a pointer to the right DisplayRegion managed by this stereo object.
get_left_eye
Returns a pointer to the left DisplayRegion managed by this stereo object.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
set_compression
Requests that this particular Texture be compressed when it is loaded into texture memory.
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
set_match_framebuffer_format
Sets the special flag that, if true, indicates to the GSG that the Texture's format should be chosen ...
set_wrap_u
This setting determines what happens when the texture is sampled with a U value outside the range 0....
set_num_views
Sets the number of "views" within a texture.
get_num_views
Returns the number of "views" in the texture.
get_texture_type
Returns the overall interpretation of the texture.
set_format
Changes the format value for the texture components.
set_render_to_texture
Sets a flag on the texture that indicates whether the texture is intended to be used as a direct-rend...
get_z_size
Returns the depth of the texture image in texels.
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
void clear_ram_image()
Discards the current system-RAM image.
void set_size_padded(int x=1, int y=1, int z=1)
Changes the size of the texture, padding if necessary, and setting the pad region as well.
set_wrap_v
This setting determines what happens when the texture is sampled with a V value outside the range 0....
set_component_type
Changes the data value for the texture components.
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
static WindowProperties size(const LVecBase2i &size)
Returns a WindowProperties structure with only the size specified.
has_size
Returns true if the window size has been specified, false otherwise.
get_size
Returns size in pixels of the useful part of the window, not including decorations.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.