mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
*** empty log message ***
This commit is contained in:
parent
5c29aace8d
commit
efc2a9ce26
@ -60,30 +60,36 @@ get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::count_textures
|
||||
// Access: Published
|
||||
// Description: If the GraphicsOutput is set to render into a
|
||||
// texture, returns the number of textures that are
|
||||
// being rendered into. Normally, the textures would
|
||||
// be associated with different buffers - a color
|
||||
// texture, a depth texture, and a stencil texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsOutput::
|
||||
count_textures() const {
|
||||
return _textures.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::has_texture
|
||||
// Access: Published
|
||||
// Description: Returns true if the GraphicsOutput is set to render
|
||||
// into a texture, or false otherwise.
|
||||
//
|
||||
// Normally, this will only be true for a GraphicsBuffer
|
||||
// object, and only when want_texture is passed in as
|
||||
// true to the GraphicsBuffer constructor. If
|
||||
// show-buffers is true, this may also be set for a
|
||||
// GraphicsWindow, which is in this case serving in the
|
||||
// place of a GraphicsBuffer.
|
||||
// Description: Returns true if the GraphicsOutput is rendering
|
||||
// into any textures at all.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsOutput::
|
||||
has_texture() const {
|
||||
return !(_texture.is_null());
|
||||
return (_textures.size() > 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_texture
|
||||
// Access: Published
|
||||
// Description: Returns the texture into which the GraphicsOutput
|
||||
// renders, if has_texture() is true, or NULL if
|
||||
// has_texture() is false.
|
||||
// Description: Returns the nth texture into which the GraphicsOutput
|
||||
// renders. Returns NULL if there is no such texture.
|
||||
//
|
||||
// If the texture is non-NULL, it may be applied to
|
||||
// geometry to be rendered for any other windows or
|
||||
@ -93,8 +99,26 @@ has_texture() const {
|
||||
// the texture will be invalid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Texture *GraphicsOutput::
|
||||
get_texture() const {
|
||||
return _texture;
|
||||
get_texture(int i) const {
|
||||
if ((i < 0) || (i >= ((int)_textures.size()))) {
|
||||
return (Texture *)NULL;
|
||||
}
|
||||
return _textures[i]._texture;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_rtm_mode
|
||||
// Access: Published
|
||||
// Description: Returns the RenderTextureMode associated with the
|
||||
// nth texture. Returns RTM_none if there is no such
|
||||
// texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsOutput::RenderTextureMode GraphicsOutput::
|
||||
get_rtm_mode(int i) const {
|
||||
if ((i < 0) || (i >= ((int)_textures.size()))) {
|
||||
return RTM_none;
|
||||
}
|
||||
return _textures[i]._rtm_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -225,7 +249,12 @@ INLINE bool GraphicsOutput::
|
||||
get_delete_flag() const {
|
||||
// We only delete the window or buffer automatically when it is
|
||||
// no longer associated with a texture.
|
||||
return _delete_flag && !_hold_texture.is_valid_pointer();
|
||||
for (int i=0; i<(int)_hold_textures.size(); i++) {
|
||||
if (_hold_textures[i].is_valid_pointer()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return _delete_flag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -80,7 +80,6 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
||||
_y_size = 0;
|
||||
_has_size = false;
|
||||
_is_valid = false;
|
||||
_rtm_mode = RTM_none;
|
||||
_flip_ready = false;
|
||||
_needs_context = true;
|
||||
_cube_map_index = -1;
|
||||
@ -187,12 +186,24 @@ GraphicsOutput::
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::setup_render_texture
|
||||
// Function: GraphicsOutput::clear_render_textures
|
||||
// Access: Published
|
||||
// Description: If the GraphicsOutput is currently rendering to
|
||||
// a texture, then all textures are dissociated from
|
||||
// the GraphicsOuput.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
clear_render_textures() {
|
||||
MutexHolder holder(_lock);
|
||||
_textures.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::add_render_texture
|
||||
// Access: Published
|
||||
// Description: Creates a new Texture object, suitable for rendering
|
||||
// the contents of this buffer into, and stores it in
|
||||
// _texture. This also disassociates the previous
|
||||
// texture (if any).
|
||||
// the contents of this buffer into, and appends it to
|
||||
// the list of render textures.
|
||||
//
|
||||
// If tex is not NULL, it is the texture that will be
|
||||
// set up for rendering into; otherwise, a new Texture
|
||||
@ -200,66 +211,84 @@ GraphicsOutput::
|
||||
// get_texture() to retrieve the new texture pointer
|
||||
// later).
|
||||
//
|
||||
// If allow_bind is true, and this GraphicsOutput is an
|
||||
// offscreen graphics buffer that has not yet been
|
||||
// rendered into, it will attempt to set up the buffer
|
||||
// for rendering directly into the texture, avoiding the
|
||||
// cost of the copy-to-texture-memory each frame. This
|
||||
// is not supported by all graphics hardware, but if it
|
||||
// is not supported, this option is quietly ignored.
|
||||
//
|
||||
// If to_ram is true, the texture image will be
|
||||
// downloaded from the framebuffer memory into system
|
||||
// RAM each frame, which is more expensive but allows
|
||||
// the texture to subsequently be applied to any GSG.
|
||||
// Otherwise, the texture image remains in texture
|
||||
// memory only.
|
||||
//
|
||||
// Also see make_texture_buffer(), which is a
|
||||
// higher-level interface for preparing
|
||||
// render-to-a-texture mode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
setup_render_texture(Texture *tex, RenderTextureMode mode) {
|
||||
add_render_texture(Texture *tex, RenderTextureMode mode) {
|
||||
if (mode == RTM_none) {
|
||||
return;
|
||||
}
|
||||
MutexHolder holder(_lock);
|
||||
_rtm_mode = mode;
|
||||
|
||||
if (tex == (Texture *)NULL) {
|
||||
_texture = new Texture(get_name());
|
||||
_texture->set_wrap_u(Texture::WM_clamp);
|
||||
_texture->set_wrap_v(Texture::WM_clamp);
|
||||
tex = new Texture(get_name());
|
||||
tex->set_wrap_u(Texture::WM_clamp);
|
||||
tex->set_wrap_v(Texture::WM_clamp);
|
||||
} else {
|
||||
_texture = tex;
|
||||
_texture->clear_ram_image();
|
||||
tex->clear_ram_image();
|
||||
}
|
||||
_texture->set_match_framebuffer_format(true);
|
||||
tex->set_match_framebuffer_format(true);
|
||||
|
||||
// Go ahead and tell the texture our anticipated size, even if it
|
||||
// might be inaccurate (particularly if this is a GraphicsWindow,
|
||||
// which has system-imposed restrictions on size).
|
||||
_texture->set_x_size(get_x_size());
|
||||
_texture->set_y_size(get_y_size());
|
||||
|
||||
tex->set_x_size(get_x_size());
|
||||
tex->set_y_size(get_y_size());
|
||||
|
||||
RenderTexture result;
|
||||
result._texture = tex;
|
||||
result._rtm_mode = mode;
|
||||
_textures.push_back(result);
|
||||
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
set_inverted(_gsg->get_copy_texture_inverted());
|
||||
|
||||
// Sanity check that we don't have two textures of the same type.
|
||||
int count_stencil_textures = 0;
|
||||
int count_depth_textures = 0;
|
||||
int count_color_textures = 0;
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
Texture::Format fmt = get_texture(i)->get_format();
|
||||
if (fmt == Texture::F_depth_component) {
|
||||
count_depth_textures += 1;
|
||||
} else if (fmt == Texture::F_stencil_index) {
|
||||
count_stencil_textures += 1;
|
||||
} else {
|
||||
count_color_textures += 1;
|
||||
}
|
||||
}
|
||||
if ((count_color_textures > 1)||
|
||||
(count_depth_textures > 1)||
|
||||
(count_stencil_textures > 1)) {
|
||||
display_cat.error() <<
|
||||
"Currently, each GraphicsOutput can only render to one color texture, "
|
||||
"one depth texture, and one stencil texture at a time. RTM aborted.\n";
|
||||
clear_render_textures();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::setup_render_texture
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description: This is a deprecated interface that made sense back
|
||||
// when GraphicsOutputs could only render into one
|
||||
// texture at a time. From now on, use
|
||||
// clear_render_textures and add_render_texture
|
||||
// instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
setup_render_texture(Texture *tex, bool allow_bind, bool to_ram) {
|
||||
display_cat.warning() <<
|
||||
"Using deprecated setup_render_texture interface.\n";
|
||||
clear_render_textures();
|
||||
if (to_ram) {
|
||||
setup_render_texture(tex, RTM_copy_ram);
|
||||
add_render_texture(tex, RTM_copy_ram);
|
||||
} else if (allow_bind) {
|
||||
setup_render_texture(tex, RTM_bind_or_copy);
|
||||
add_render_texture(tex, RTM_bind_or_copy);
|
||||
} else {
|
||||
setup_render_texture(tex, RTM_copy_texture);
|
||||
add_render_texture(tex, RTM_copy_texture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,7 +606,20 @@ get_texture_card() {
|
||||
PT(GeomNode) gnode = new GeomNode("texture card");
|
||||
gnode->add_geom(_texture_card);
|
||||
NodePath path(gnode);
|
||||
path.set_texture(get_texture(), 0);
|
||||
|
||||
// The texture card, by default, is textured with the first
|
||||
// render-to-texture output texture. Depth and stencil
|
||||
// textures are ignored. The user can freely alter the
|
||||
// card's texture attrib.
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
Texture *texture = get_texture(i);
|
||||
if ((texture->get_format() != Texture::F_depth_component) &&
|
||||
(texture->get_format() != Texture::F_stencil_index)) {
|
||||
path.set_texture(texture, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -635,7 +677,7 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
// host window size. If the user requests this, we have to use a
|
||||
// parasite buffer.
|
||||
buffer = engine->make_parasite(host, name, sort, x_size, y_size);
|
||||
buffer->setup_render_texture(tex, false, to_ram);
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -644,7 +686,7 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
// since it all amounts to the same thing anyway--this will
|
||||
// actually create a new GraphicsWindow.
|
||||
buffer = engine->make_buffer(gsg, name, sort, x_size, y_size);
|
||||
buffer->setup_render_texture(tex, false, to_ram);
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -661,7 +703,7 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
(x_size <= host->get_x_size() && y_size <= host->get_y_size())) {
|
||||
buffer = engine->make_parasite(host, name, sort, x_size, y_size);
|
||||
if (buffer != (GraphicsOutput *)NULL) {
|
||||
buffer->setup_render_texture(tex, false, to_ram);
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
@ -680,7 +722,11 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
buffer = engine->make_buffer(sb_gsg, name, sort, x_size, y_size);
|
||||
if (buffer != (GraphicsOutput *)NULL) {
|
||||
// Check the buffer for goodness.
|
||||
buffer->setup_render_texture(tex, allow_bind, to_ram);
|
||||
if (allow_bind) {
|
||||
buffer->add_render_texture(tex, RTM_bind_or_copy);
|
||||
} else {
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
}
|
||||
engine->open_windows();
|
||||
if (buffer->is_valid()) {
|
||||
return buffer;
|
||||
@ -700,7 +746,11 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
// source window is double-buffered.
|
||||
buffer = engine->make_buffer(gsg, name, sort, x_size, y_size);
|
||||
if (buffer != (GraphicsOutput *)NULL) {
|
||||
buffer->setup_render_texture(tex, allow_bind, to_ram);
|
||||
if (allow_bind) {
|
||||
buffer->add_render_texture(tex, RTM_bind_or_copy);
|
||||
} else {
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
}
|
||||
engine->open_windows();
|
||||
if (buffer->is_valid()) {
|
||||
return buffer;
|
||||
@ -714,7 +764,7 @@ make_texture_buffer(const string &name, int x_size, int y_size,
|
||||
// Looks like we have to settle for a parasite buffer.
|
||||
if (x_size <= host->get_x_size() && y_size <= host->get_y_size()) {
|
||||
buffer = engine->make_parasite(host, name, sort, x_size, y_size);
|
||||
buffer->setup_render_texture(tex, false, to_ram);
|
||||
buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -926,10 +976,7 @@ begin_frame() {
|
||||
// Okay, we already have a GSG, so activate it.
|
||||
make_current();
|
||||
|
||||
if (_rtm_mode == RTM_bind_or_copy) {
|
||||
// Release the texture so we can render into the frame buffer.
|
||||
_gsg->framebuffer_release_texture(this, get_texture());
|
||||
}
|
||||
begin_render_texture();
|
||||
|
||||
_cube_map_index = -1;
|
||||
_cube_map_dr = NULL;
|
||||
@ -982,33 +1029,24 @@ end_frame() {
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
_gsg->end_frame();
|
||||
|
||||
// If _rtm_mode isn't RTM_none, it means we should copy or lock the
|
||||
// framebuffer to the GraphicsOutput's associated texture after the
|
||||
// frame has rendered.
|
||||
if (_rtm_mode != RTM_none) {
|
||||
// Handle all render-to-texture operations that use bind-to-texture
|
||||
end_render_texture();
|
||||
|
||||
// Handle all render-to-texture operations that use copy-to-texture
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
RenderTextureMode rtm_mode = get_rtm_mode(i);
|
||||
if ((rtm_mode == RTM_none)||(rtm_mode == RTM_bind_or_copy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Texture *texture = get_texture(i);
|
||||
PStatTimer timer(_copy_texture_pcollector);
|
||||
nassertv(has_texture());
|
||||
|
||||
// If _rtm_mode is one of the bind-modes, it means we should attempt
|
||||
// to lock the framebuffer directly to the texture memory, avoiding
|
||||
// the copy.
|
||||
if (_rtm_mode == RTM_bind_or_copy) {
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
<< "Locking texture for " << get_name() << " at frame end.\n";
|
||||
}
|
||||
if (!_gsg->framebuffer_bind_to_texture(this, get_texture())) {
|
||||
display_cat.warning()
|
||||
<< "Lock-to-texture failed, resorting to copy.\n";
|
||||
_rtm_mode = RTM_copy_texture;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_rtm_mode == RTM_copy_texture)||
|
||||
(_rtm_mode == RTM_copy_ram)||
|
||||
((_rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
|
||||
((_rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
|
||||
_trigger_copy = false;
|
||||
if ((rtm_mode == RTM_copy_texture)||
|
||||
(rtm_mode == RTM_copy_ram)||
|
||||
((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
|
||||
((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
<< "Copying texture for " << get_name() << " at frame end.\n";
|
||||
@ -1017,30 +1055,31 @@ end_frame() {
|
||||
}
|
||||
RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
|
||||
if (_cube_map_dr != (DisplayRegion *)NULL) {
|
||||
if ((_rtm_mode == RTM_copy_ram)||(_rtm_mode == RTM_triggered_copy_ram)) {
|
||||
_gsg->framebuffer_copy_to_ram(get_texture(), _cube_map_index,
|
||||
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
|
||||
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
|
||||
_cube_map_dr, buffer);
|
||||
} else {
|
||||
_gsg->framebuffer_copy_to_texture(get_texture(), _cube_map_index,
|
||||
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
|
||||
_cube_map_dr, buffer);
|
||||
}
|
||||
} else {
|
||||
if ((_rtm_mode == RTM_copy_ram)||(_rtm_mode == RTM_triggered_copy_ram)) {
|
||||
_gsg->framebuffer_copy_to_ram(get_texture(), _cube_map_index,
|
||||
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
|
||||
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
|
||||
_default_display_region, buffer);
|
||||
} else {
|
||||
_gsg->framebuffer_copy_to_texture(get_texture(), _cube_map_index,
|
||||
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
|
||||
_default_display_region, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_trigger_copy = false;
|
||||
|
||||
// If we're not single-buffered, we're now ready to flip.
|
||||
if (!_gsg->get_properties().is_single_buffered()) {
|
||||
_flip_ready = true;
|
||||
}
|
||||
|
||||
|
||||
// In one-shot mode, we request the GraphicsEngine to delete the
|
||||
// window after we have rendered a frame.
|
||||
if (_one_shot) {
|
||||
@ -1059,23 +1098,53 @@ end_frame() {
|
||||
|
||||
// If we were rendering directly to texture, we can't delete the
|
||||
// buffer until the texture is gone too.
|
||||
if (_rtm_mode == RTM_bind_or_copy) {
|
||||
_hold_texture = _texture;
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if (get_rtm_mode(i) == RTM_bind_or_copy) {
|
||||
_hold_textures.push_back(get_texture(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have to be sure to clear the _texture pointer, though, or
|
||||
// we'll end up holding a reference to it forever.
|
||||
_texture = NULL;
|
||||
|
||||
// And we need to stop trying to copy to the texture.
|
||||
_rtm_mode = RTM_none;
|
||||
// We have to be sure to clear the _textures pointers, though, or
|
||||
// we'll end up holding a reference to the textures forever.
|
||||
clear_render_textures();
|
||||
}
|
||||
|
||||
|
||||
_cube_map_index = -1;
|
||||
_cube_map_dr = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::begin_render_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: If the GraphicsOutput supports direct render-to-texture,
|
||||
// and if any setup needs to be done during begin_frame,
|
||||
// then the setup code should go here. Any textures that
|
||||
// can not be rendered to directly should be reflagged
|
||||
// as RTM_copy_texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
begin_render_texture() {
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if (get_rtm_mode(i) == RTM_bind_or_copy) {
|
||||
_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::end_render_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: If the GraphicsOutput supports direct render-to-texture,
|
||||
// and if any setup needs to be done during end_frame,
|
||||
// then the setup code should go here. Any textures that
|
||||
// could not be rendered to directly should be reflagged
|
||||
// as RTM_copy_texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
end_render_texture() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::change_scenes
|
||||
// Access: Public
|
||||
@ -1095,31 +1164,35 @@ change_scenes(DisplayRegion *new_dr) {
|
||||
_cube_map_index = new_cube_map_index;
|
||||
_cube_map_dr = new_dr;
|
||||
|
||||
if (_rtm_mode != RTM_none) {
|
||||
if (_rtm_mode == RTM_bind_or_copy) {
|
||||
// In render-to-texture mode, switch the rendering backend to
|
||||
// the new cube map face, so that the subsequent frame will be
|
||||
// rendered to the new face.
|
||||
|
||||
select_cube_map(new_cube_map_index);
|
||||
|
||||
} else if (old_cube_map_index != -1) {
|
||||
// In copy-to-texture mode, copy the just-rendered framebuffer
|
||||
// to the old cube map face.
|
||||
nassertv(old_cube_map_dr != (DisplayRegion *)NULL);
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
<< "Copying texture for " << get_name() << " at scene change.\n";
|
||||
display_cat.debug()
|
||||
<< "cube_map_index = " << old_cube_map_index << "\n";
|
||||
}
|
||||
RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
|
||||
if (_rtm_mode == RTM_copy_ram) {
|
||||
_gsg->framebuffer_copy_to_ram(get_texture(), old_cube_map_index,
|
||||
old_cube_map_dr, buffer);
|
||||
} else {
|
||||
_gsg->framebuffer_copy_to_texture(get_texture(), old_cube_map_index,
|
||||
old_cube_map_dr, buffer);
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
Texture *texture = get_texture(i);
|
||||
RenderTextureMode rtm_mode = get_rtm_mode(i);
|
||||
if (rtm_mode != RTM_none) {
|
||||
if (rtm_mode == RTM_bind_or_copy) {
|
||||
// In render-to-texture mode, switch the rendering backend to
|
||||
// the new cube map face, so that the subsequent frame will be
|
||||
// rendered to the new face.
|
||||
|
||||
select_cube_map(new_cube_map_index);
|
||||
|
||||
} else if (old_cube_map_index != -1) {
|
||||
// In copy-to-texture mode, copy the just-rendered framebuffer
|
||||
// to the old cube map face.
|
||||
nassertv(old_cube_map_dr != (DisplayRegion *)NULL);
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
<< "Copying texture for " << get_name() << " at scene change.\n";
|
||||
display_cat.debug()
|
||||
<< "cube_map_index = " << old_cube_map_index << "\n";
|
||||
}
|
||||
RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
|
||||
if (rtm_mode == RTM_copy_ram) {
|
||||
_gsg->framebuffer_copy_to_ram(texture, old_cube_map_index,
|
||||
old_cube_map_dr, buffer);
|
||||
} else {
|
||||
_gsg->framebuffer_copy_to_texture(texture, old_cube_map_index,
|
||||
old_cube_map_dr, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,11 +84,14 @@ PUBLISHED:
|
||||
INLINE GraphicsPipe *get_pipe() const;
|
||||
INLINE const string &get_name() const;
|
||||
|
||||
INLINE bool has_texture() const;
|
||||
INLINE Texture *get_texture() const;
|
||||
void setup_render_texture(Texture *tex, RenderTextureMode mode);
|
||||
INLINE int count_textures() const;
|
||||
INLINE bool has_texture() const;
|
||||
INLINE Texture *get_texture(int i=0) const;
|
||||
INLINE RenderTextureMode get_rtm_mode(int i=0) const;
|
||||
void clear_render_textures();
|
||||
void add_render_texture(Texture *tex, RenderTextureMode mode);
|
||||
void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram);
|
||||
|
||||
|
||||
INLINE int get_x_size() const;
|
||||
INLINE int get_y_size() const;
|
||||
INLINE bool has_size() const;
|
||||
@ -157,10 +160,13 @@ public:
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the draw thread. These methods are normally
|
||||
// called by the GraphicsEngine.
|
||||
virtual bool begin_frame();
|
||||
void clear();
|
||||
virtual bool begin_frame();
|
||||
virtual void end_frame();
|
||||
|
||||
virtual void begin_render_texture();
|
||||
virtual void end_render_texture();
|
||||
|
||||
void change_scenes(DisplayRegion *new_dr);
|
||||
virtual void select_cube_map(int cube_map_index);
|
||||
|
||||
@ -182,11 +188,15 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
class RenderTexture {
|
||||
public:
|
||||
PT(Texture) _texture;
|
||||
RenderTextureMode _rtm_mode;
|
||||
};
|
||||
PT(GraphicsStateGuardian) _gsg;
|
||||
PT(GraphicsPipe) _pipe;
|
||||
string _name;
|
||||
PT(Texture) _texture;
|
||||
RenderTextureMode _rtm_mode;
|
||||
pvector<RenderTexture> _textures;
|
||||
bool _flip_ready;
|
||||
bool _needs_context;
|
||||
int _cube_map_index;
|
||||
@ -211,12 +221,12 @@ protected:
|
||||
bool _inverted;
|
||||
bool _delete_flag;
|
||||
|
||||
// This weak pointer is used to keep track of whether the buffer's
|
||||
// bound Texture has been deleted or not. Until it has, we don't
|
||||
// auto-close the buffer (since that would deallocate the memory
|
||||
// associated with the texture).
|
||||
WPT(Texture) _hold_texture;
|
||||
|
||||
// These weak pointers are used to keep track of whether the
|
||||
// buffer's bound Texture has been deleted or not. Until they have,
|
||||
// we don't auto-close the buffer (since that would deallocate the
|
||||
// memory associated with the texture).
|
||||
pvector<WPT(Texture)> _hold_textures;
|
||||
|
||||
protected:
|
||||
Mutex _lock;
|
||||
// protects _display_regions.
|
||||
|
@ -971,39 +971,6 @@ end_draw_primitives() {
|
||||
_vertex_data = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::framebuffer_bind_to_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: Works in lieu of copy_texture() to bind the primary
|
||||
// render buffer of the framebuffer to the indicated
|
||||
// texture (which must have been created via
|
||||
// GraphicsOutput::setup_render_texture()).
|
||||
//
|
||||
// If supported by the graphics backend, this will make
|
||||
// the framebuffer memory directly accessible within the
|
||||
// texture, but the frame cannot be rendered again until
|
||||
// framebuffer_release_texture() is called.
|
||||
//
|
||||
// The return value is true if successful, false on
|
||||
// failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
framebuffer_bind_to_texture(GraphicsOutput *, Texture *) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::framebuffer_release_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: Undoes a previous call to
|
||||
// framebuffer_bind_to_texture(). The framebuffer may
|
||||
// again be rendered into, and the contents of the
|
||||
// texture is undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
framebuffer_release_texture(GraphicsOutput *, Texture *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::do_issue_color_scale
|
||||
// Access: Public, Virtual
|
||||
|
@ -191,9 +191,6 @@ public:
|
||||
virtual void draw_points(const GeomPoints *primitive);
|
||||
virtual void end_draw_primitives();
|
||||
|
||||
virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex);
|
||||
virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex);
|
||||
|
||||
INLINE bool reset_if_new();
|
||||
INLINE void mark_new();
|
||||
virtual void reset();
|
||||
|
@ -202,10 +202,7 @@ public:
|
||||
(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0;
|
||||
virtual bool framebuffer_copy_to_ram
|
||||
(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0;
|
||||
|
||||
virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex)=0;
|
||||
virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex)=0;
|
||||
|
||||
|
||||
virtual CoordinateSystem get_internal_coordinate_system() const=0;
|
||||
|
||||
virtual void bind_light(PointLight *light_obj, const NodePath &light,
|
||||
|
@ -89,6 +89,75 @@ begin_frame() {
|
||||
return GraphicsBuffer::begin_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::begin_render_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: If the GraphicsOutput supports direct render-to-texture,
|
||||
// and if any setup needs to be done during begin_frame,
|
||||
// then the setup code should go here. Any textures that
|
||||
// can not be rendered to directly should be reflagged
|
||||
// as RTM_copy_texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsBuffer::
|
||||
begin_render_texture() {
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_V(wglgsg, _gsg);
|
||||
|
||||
if (_gsg->get_properties().is_single_buffered()) {
|
||||
wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
|
||||
} else {
|
||||
wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::end_render_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: If the GraphicsOutput supports direct render-to-texture,
|
||||
// and if any setup needs to be done during end_frame,
|
||||
// then the setup code should go here. Any textures that
|
||||
// could not be rendered to directly should be reflagged
|
||||
// as RTM_copy_texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsBuffer::
|
||||
end_render_texture() {
|
||||
wglGraphicsStateGuardian *wglgsg;
|
||||
DCAST_INTO_V(wglgsg, _gsg);
|
||||
|
||||
// Find the color texture, if there is one. That one can be bound to
|
||||
// the framebuffer. All others must be marked RTM_copy_to_texture.
|
||||
int tex_index = -1;
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if (get_rtm_mode(i) == RTM_bind_or_copy) {
|
||||
if ((get_texture(i)->get_format() != Texture::F_depth_component)&&
|
||||
(get_texture(i)->get_format() != Texture::F_stencil_index)&&
|
||||
(tex_index < 0)) {
|
||||
tex_index = i;
|
||||
} else {
|
||||
_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tex_index >= 0) {
|
||||
Texture *tex = get_texture(tex_index);
|
||||
TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
|
||||
nassertv(tc != (TextureContext *)NULL);
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
GLenum target = wglgsg->get_texture_target(tex->get_texture_type());
|
||||
if (target == GL_NONE) {
|
||||
_textures[tex_index]._rtm_mode = RTM_copy_texture;
|
||||
return;
|
||||
}
|
||||
GLP(BindTexture)(target, gtc->_index);
|
||||
if (_gsg->get_properties().is_single_buffered()) {
|
||||
wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
|
||||
} else {
|
||||
wglgsg->_wglBindTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsBuffer::select_cube_map
|
||||
// Access: Public, Virtual
|
||||
@ -231,29 +300,6 @@ open_buffer() {
|
||||
}
|
||||
|
||||
_pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
|
||||
if (wgldisplay_cat.is_debug()) {
|
||||
wgldisplay_cat.debug()
|
||||
<< "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n";
|
||||
switch (_rtm_mode) {
|
||||
case RTM_bind_or_copy:
|
||||
wgldisplay_cat.debug()
|
||||
<< "pbuffer renders directly to texture.\n";
|
||||
break;
|
||||
|
||||
case RTM_copy_texture:
|
||||
wgldisplay_cat.debug()
|
||||
<< "pbuffer copies indirectly into texture.\n";
|
||||
break;
|
||||
|
||||
case RTM_copy_ram:
|
||||
wgldisplay_cat.debug()
|
||||
<< "pbuffer copies indirectly into system RAM.\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc));
|
||||
wglgsg->report_my_gl_errors();
|
||||
@ -286,9 +332,15 @@ make_pbuffer(HDC twindow_dc) {
|
||||
|
||||
if (wglgsg->_supports_pixel_format) {
|
||||
bool got_pbuffer_format = false;
|
||||
bool any_binds = false;
|
||||
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if (get_rtm_mode(i) == RTM_bind_or_copy) {
|
||||
any_binds = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_rtm_mode == RTM_bind_or_copy) &&
|
||||
wglgsg->_supports_render_texture) {
|
||||
if (any_binds && wglgsg->_supports_render_texture) {
|
||||
// First, try to get a pbuffer format that supports
|
||||
// render-to-texture.
|
||||
int new_pbformat = choose_pbuffer_format(twindow_dc, true);
|
||||
@ -299,8 +351,13 @@ make_pbuffer(HDC twindow_dc) {
|
||||
}
|
||||
|
||||
if (!got_pbuffer_format) {
|
||||
// Failing that, just get a matching pbuffer format.
|
||||
_rtm_mode = RTM_copy_texture;
|
||||
// Failing that, just get a matching pbuffer format,
|
||||
// and disable RTM_bind_or_copy.
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if (get_rtm_mode(i) == RTM_bind_or_copy) {
|
||||
_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
}
|
||||
}
|
||||
int new_pbformat = choose_pbuffer_format(twindow_dc, false);
|
||||
if (new_pbformat != 0) {
|
||||
pbformat = new_pbformat;
|
||||
@ -322,8 +379,18 @@ make_pbuffer(HDC twindow_dc) {
|
||||
int iattrib_list[max_attrib_list];
|
||||
int ni = 0;
|
||||
|
||||
if (_rtm_mode == RTM_bind_or_copy) {
|
||||
nassertr(_texture != (Texture *)NULL, false);
|
||||
// Find the texture to bind to the color buffer.
|
||||
Texture *bindtexture = NULL;
|
||||
for (int i=0; i<count_textures(); i++) {
|
||||
if ((get_rtm_mode(i) == RTM_bind_or_copy)&&
|
||||
(get_texture(i)->get_format() != Texture::F_depth_component)&&
|
||||
(get_texture(i)->get_format() != Texture::F_stencil_index)) {
|
||||
bindtexture = get_texture(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bindtexture != 0) {
|
||||
|
||||
if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) {
|
||||
iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
|
||||
@ -333,12 +400,12 @@ make_pbuffer(HDC twindow_dc) {
|
||||
iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
|
||||
}
|
||||
|
||||
if (_texture->uses_mipmaps()) {
|
||||
if (bindtexture->uses_mipmaps()) {
|
||||
iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB;
|
||||
iattrib_list[ni++] = 1;
|
||||
}
|
||||
|
||||
switch (_texture->get_texture_type()) {
|
||||
switch (bindtexture->get_texture_type()) {
|
||||
case Texture::TT_cube_map:
|
||||
iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
|
||||
iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB;
|
||||
@ -353,7 +420,7 @@ make_pbuffer(HDC twindow_dc) {
|
||||
iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
|
||||
iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the list.
|
||||
nassertr(ni <= max_attrib_list, false);
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
virtual void make_current();
|
||||
virtual void release_gsg();
|
||||
|
||||
virtual void begin_render_texture();
|
||||
virtual void end_render_texture();
|
||||
|
||||
virtual void process_events();
|
||||
|
||||
protected:
|
||||
|
@ -63,66 +63,6 @@ wglGraphicsStateGuardian::
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::framebuffer_bind_to_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: Works in lieu of copy_texture() to bind the primary
|
||||
// render buffer of the framebuffer to the indicated
|
||||
// texture (which must have been created via
|
||||
// GraphicsOutput::setup_render_texture()).
|
||||
//
|
||||
// If supported by the graphics backend, this will make
|
||||
// the framebuffer memory directly accessible within the
|
||||
// texture, but the frame cannot be rendered again until
|
||||
// framebuffer_release_texture() is called.
|
||||
//
|
||||
// The return value is true if successful, false on
|
||||
// failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool wglGraphicsStateGuardian::
|
||||
framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex) {
|
||||
wglGraphicsBuffer *buffer;
|
||||
DCAST_INTO_R(buffer, win, false);
|
||||
|
||||
TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
|
||||
nassertr(tc != (TextureContext *)NULL, false);
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
GLenum target = get_texture_target(tex->get_texture_type());
|
||||
if (target == GL_NONE) {
|
||||
// Invalid texture, can't bind it.
|
||||
return false;
|
||||
}
|
||||
GLP(BindTexture)(target, gtc->_index);
|
||||
|
||||
if (get_properties().is_single_buffered()) {
|
||||
_wglBindTexImageARB(buffer->_pbuffer, WGL_FRONT_LEFT_ARB);
|
||||
} else {
|
||||
_wglBindTexImageARB(buffer->_pbuffer, WGL_BACK_LEFT_ARB);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::framebuffer_release_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: Undoes a previous call to
|
||||
// framebuffer_bind_to_texture(). The framebuffer may
|
||||
// again be rendered into, and the contents of the
|
||||
// texture is undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void wglGraphicsStateGuardian::
|
||||
framebuffer_release_texture(GraphicsOutput *win, Texture *) {
|
||||
wglGraphicsBuffer *buffer;
|
||||
DCAST_INTO_V(buffer, win);
|
||||
|
||||
if (get_properties().is_single_buffered()) {
|
||||
_wglReleaseTexImageARB(buffer->_pbuffer, WGL_FRONT_LEFT_ARB);
|
||||
} else {
|
||||
_wglReleaseTexImageARB(buffer->_pbuffer, WGL_BACK_LEFT_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: wglGraphicsStateGuardian::reset
|
||||
// Access: Public, Virtual
|
||||
|
@ -43,9 +43,6 @@ public:
|
||||
INLINE bool made_context() const;
|
||||
INLINE HGLRC get_context(HDC hdc);
|
||||
|
||||
virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex);
|
||||
virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
INLINE HDC get_twindow_dc();
|
||||
|
Loading…
x
Reference in New Issue
Block a user