From 8c2e657f15bb8a175d8a26508c354ceeac7c3289 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 25 Aug 2008 22:58:58 +0000 Subject: [PATCH] Add gsg::update_texture() --- panda/src/display/graphicsStateGuardian.cxx | 21 ++++ panda/src/display/graphicsStateGuardian.h | 1 + .../glstuff/glGraphicsStateGuardian_src.cxx | 119 +++++++++++++----- .../src/glstuff/glGraphicsStateGuardian_src.h | 3 +- panda/src/gobj/preparedGraphicsObjects.cxx | 3 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 1 + panda/src/pgraph/geomNode.cxx | 29 +++++ panda/src/pgraph/geomNode.h | 3 + panda/src/pgraph/nodePath.cxx | 47 +------ panda/src/pgraph/nodePath.h | 3 - panda/src/pgraph/pandaNode.cxx | 41 ++++++ panda/src/pgraph/pandaNode.h | 7 ++ panda/src/pgui/pgItem.cxx | 24 ++++ panda/src/pgui/pgItem.h | 3 + panda/src/text/textNode.cxx | 22 ++++ panda/src/text/textNode.h | 3 + .../tinydisplay/tinyGraphicsStateGuardian.cxx | 59 ++++++--- .../tinydisplay/tinyGraphicsStateGuardian.h | 1 + 18 files changed, 292 insertions(+), 98 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index e1897af468..ccdb5eca8f 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -414,6 +414,27 @@ prepare_texture(Texture *) { return (TextureContext *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::update_texture +// Access: Public, Virtual +// Description: Ensures that the current Texture data is refreshed +// onto the GSG. This means updating the texture +// properties and/or re-uploading the texture image, if +// necessary. This should only be called within the +// draw thread. +// +// If force is true, this function will not return until +// the texture has been fully uploaded. If force is +// false, the function may choose to upload a simple +// version of the texture instead, if the texture is not +// fully resident (and if get_incomplete_render() is +// true). +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +update_texture(TextureContext *, bool) { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::release_texture // Access: Public, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 9f6e7cb2fd..2d8a401e18 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -170,6 +170,7 @@ public: virtual SceneSetup *get_scene() const; virtual TextureContext *prepare_texture(Texture *tex); + virtual bool update_texture(TextureContext *tc, bool force); virtual void release_texture(TextureContext *tc); virtual bool extract_texture_data(Texture *tex); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 9f36438cc5..71aeda2e53 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2637,6 +2637,50 @@ prepare_texture(Texture *tex) { return gtc; } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::update_texture +// Access: Public, Virtual +// Description: Ensures that the current Texture data is refreshed +// onto the GSG. This means updating the texture +// properties and/or re-uploading the texture image, if +// necessary. This should only be called within the +// draw thread. +// +// If force is true, this function will not return until +// the texture has been fully uploaded. If force is +// false, the function may choose to upload a simple +// version of the texture instead, if the texture is not +// fully resident (and if get_incomplete_render() is +// true). +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsStateGuardian):: +update_texture(TextureContext *tc, bool force) { + apply_texture(tc); + + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + + if (gtc->was_image_modified()) { + // If the texture image was modified, reload the texture. This + // means we also re-specify the properties for good measure. + specify_texture(gtc->get_texture()); + bool okflag = upload_texture(gtc, force); + if (!okflag) { + GLCAT.error() + << "Could not load " << *gtc->get_texture() << "\n"; + return false; + } + + } else if (gtc->was_properties_modified()) { + // If only the properties have been modified, we don't necessarily + // need to reload the texture. + specify_texture(gtc->get_texture()); + gtc->mark_loaded(); + } + + report_my_gl_errors(); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::release_texture // Access: Public, Virtual @@ -3275,18 +3319,44 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertr(tc != (TextureContext *)NULL, false); - apply_texture(tc); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - if (z >= 0) { - // Copy to a cube map face. This doesn't seem to work too well - // with CopyTexSubImage2D, so we always use CopyTexImage2D. - GLP(CopyTexImage2D)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + z, 0, - get_internal_image_format(tex), - xo, yo, w, h, 0); - } else { - GLP(CopyTexSubImage2D)(GL_TEXTURE_2D, 0, 0, 0, xo, yo, w, h); + apply_texture(gtc); + specify_texture(tex); + + GLenum target = get_texture_target(tex->get_texture_type()); + GLint internal_format = get_internal_image_format(tex); + bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps); + if (uses_mipmaps) { + if (_supports_generate_mipmap) { + GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, true); + } else { + // If we can't auto-generate mipmaps, do without mipmaps. + GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + uses_mipmaps = false; + } } + bool new_image = gtc->was_image_modified(); + if (z >= 0) { + // Copy to a cube map face. + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z; + + // Cube map faces seem to have trouble with CopyTexSubImage, so we + // always reload the image. + new_image = true; + } + + if (new_image) { + // We have to create a new image. + GLP(CopyTexImage2D)(target, 0, internal_format, xo, yo, w, h, 0); + } else { + // We can overlay the existing image. + GLP(CopyTexSubImage2D)(target, 0, 0, 0, xo, yo, w, h); + } + + gtc->mark_loaded(); + report_my_gl_errors(); // Force reload of texture state, since we've just monkeyed with it. @@ -6186,7 +6256,7 @@ update_standard_texture_bindings() { } GLP(Enable)(target); - if (!apply_texture(tc)) { + if (!update_texture(tc, false)) { GLP(Disable)(target); break; } @@ -6755,24 +6825,6 @@ apply_texture(TextureContext *tc) { } GLP(BindTexture)(target, gtc->_index); - if (gtc->was_image_modified()) { - // If the texture image was modified, reload the texture. This - // means we also re-specify the properties for good measure. - specify_texture(gtc->get_texture()); - bool okflag = upload_texture(gtc); - if (!okflag) { - GLCAT.error() - << "Could not load " << *gtc->get_texture() << "\n"; - return false; - } - - } else if (gtc->was_properties_modified()) { - // If only the properties have been modified, we don't necessarily - // need to reload the texture. - specify_texture(gtc->get_texture()); - gtc->mark_loaded(); - } - report_my_gl_errors(); return true; } @@ -6787,10 +6839,10 @@ apply_texture(TextureContext *tc) { // the texture has no image. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -upload_texture(CLP(TextureContext) *gtc) { +upload_texture(CLP(TextureContext) *gtc, bool force) { Texture *tex = gtc->get_texture(); - if (_incomplete_render) { + if (_incomplete_render && !force) { bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image(); if (!has_image && tex->might_have_ram_image() && tex->has_simple_ram_image() && @@ -6827,6 +6879,13 @@ upload_texture(CLP(TextureContext) *gtc) { image_compression = Texture::CM_off; } + /* + if (image.is_null()) { + // If we don't have an image, we can't upload. + return false; + } + */ + int mipmap_bias = 0; int width = tex->get_x_size(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 0807ed7887..9a56ab7650 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -143,6 +143,7 @@ public: INLINE bool draw_display_list(GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); + virtual bool update_texture(TextureContext *tc, bool force); virtual void release_texture(TextureContext *tc); virtual bool extract_texture_data(Texture *tex); @@ -324,7 +325,7 @@ protected: void do_auto_rescale_normal(); void specify_texture(Texture *tex); bool apply_texture(TextureContext *tc); - bool upload_texture(CLP(TextureContext) *gtc); + bool upload_texture(CLP(TextureContext) *gtc, bool force); bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, int mipmap_bias, GLenum texture_target, GLenum page_target, diff --git a/panda/src/gobj/preparedGraphicsObjects.cxx b/panda/src/gobj/preparedGraphicsObjects.cxx index aa28fc44da..7cd8a4a9e2 100644 --- a/panda/src/gobj/preparedGraphicsObjects.cxx +++ b/panda/src/gobj/preparedGraphicsObjects.cxx @@ -1214,7 +1214,8 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) { qti != _enqueued_textures.end(); ++qti) { Texture *tex = (*qti); - tex->prepare_now(this, gsg); + TextureContext *tc = tex->prepare_now(this, gsg); + gsg->update_texture(tc, true); } _enqueued_textures.clear(); diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 9d05741061..58b97a11d3 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -133,6 +133,7 @@ public: #endif virtual TextureContext *prepare_texture(Texture *tex)=0; + virtual bool update_texture(TextureContext *tc, bool force)=0; virtual void release_texture(TextureContext *tc)=0; virtual bool extract_texture_data(Texture *tex)=0; diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index de181c6bca..afbfbfb44d 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -352,6 +352,35 @@ safe_to_combine() const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::r_prepare_scene +// Access: Protected, Virtual +// Description: The recursive implementation of prepare_scene(). +// Don't call this directly; call +// PandaNode::prepare_scene() or +// NodePath::prepare_scene() instead. +//////////////////////////////////////////////////////////////////// +void GeomNode:: +r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects) { + int num_geoms = get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + CPT(RenderState) geom_state = state->compose(get_geom_state(i)); + const RenderAttrib *attrib = + geom_state->get_attrib(TextureAttrib::get_class_type()); + if (attrib != (const RenderAttrib *)NULL) { + const TextureAttrib *ta; + DCAST_INTO_V(ta, attrib); + Texture *texture = ta->get_texture(); + if (texture != (Texture *)NULL) { + texture->prepare(prepared_objects); + } + } + } + + PandaNode::r_prepare_scene(state, prepared_objects); +} + //////////////////////////////////////////////////////////////////// // Function: GeomNode::combine_with diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index 0d62571e8b..feb919e758 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -59,6 +59,9 @@ public: virtual bool safe_to_flatten() const; virtual bool safe_to_combine() const; + virtual void r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects); + PUBLISHED: INLINE void set_preserved(bool value); INLINE bool get_preserved() const; diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 73a246bfb4..3cac987c7a 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -5752,10 +5752,8 @@ void NodePath:: prepare_scene(GraphicsStateGuardianBase *gsg) { nassertv_always(!is_empty()); - PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects(); - CPT(RenderState) net_state = get_net_state(); - r_prepare_scene(node(), net_state, prepared_objects); + node()->prepare_scene(gsg, net_state); } //////////////////////////////////////////////////////////////////// @@ -7009,46 +7007,3 @@ r_find_all_materials(PandaNode *node, const RenderState *state, r_find_all_materials(child, next_state, materials); } } - -//////////////////////////////////////////////////////////////////// -// Function: NodePath::r_prepare_scene -// Access: Private -// Description: The recursive implementation of prepare_scene. -//////////////////////////////////////////////////////////////////// -void NodePath:: -r_prepare_scene(PandaNode *node, const RenderState *state, - PreparedGraphicsObjects *prepared_objects) { - if (node->is_geom_node()) { - GeomNode *gnode; - DCAST_INTO_V(gnode, node); - - /* - Not implemented yet in pgraph. Maybe we don't need this anyway. - if (retained_mode) { - gnode->prepare(gsg); - } - */ - - int num_geoms = gnode->get_num_geoms(); - for (int i = 0; i < num_geoms; i++) { - CPT(RenderState) geom_state = state->compose(gnode->get_geom_state(i)); - const RenderAttrib *attrib = - geom_state->get_attrib(TextureAttrib::get_class_type()); - if (attrib != (const RenderAttrib *)NULL) { - const TextureAttrib *ta; - DCAST_INTO_V(ta, attrib); - Texture *texture = ta->get_texture(); - if (texture != (Texture *)NULL) { - texture->prepare(prepared_objects); - } - } - } - } - - int num_children = node->get_num_children(); - for (int i = 0; i < num_children; i++) { - PandaNode *child = node->get_child(i); - CPT(RenderState) child_state = state->compose(child->get_state()); - r_prepare_scene(child, child_state, prepared_objects); - } -} diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 4e529f2bd4..71c1df07ef 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -913,9 +913,6 @@ private: void r_find_all_materials(PandaNode *node, const RenderState *state, Materials &materials) const; - void r_prepare_scene(PandaNode *node, const RenderState *state, - PreparedGraphicsObjects *prepared_objects); - PT(NodePathComponent) _head; int _backup_key; ErrorType _error_type; diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 33c731f3dd..0902023fc8 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -27,6 +27,7 @@ #include "pStatTimer.h" #include "config_mathutil.h" #include "reMutexHolder.h" +#include "graphicsStateGuardianBase.h" // This category is just temporary for debugging convenience. NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH); @@ -2105,6 +2106,27 @@ get_off_clip_planes(Thread *current_thread) const { return cdata->_off_clip_planes; } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::prepare_scene +// Access: Published +// Description: Walks through the scene graph beginning at this node, +// and does whatever initialization is required to +// render the scene properly with the indicated GSG. It +// is not strictly necessary to call this, since the GSG +// will initialize itself when the scene is rendered, +// but this may take some of the overhead away from that +// process. +// +// In particular, this will ensure that textures within +// the scene are loaded in texture memory, and display +// lists are built up from static geometry. +//////////////////////////////////////////////////////////////////// +void PandaNode:: +prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *net_state) { + PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects(); + r_prepare_scene(net_state, prepared_objects); +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::output // Access: Published, Virtual @@ -2661,6 +2683,25 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map, } } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::r_prepare_scene +// Access: Public, Virtual +// Description: The recursive implementation of prepare_scene(). +// Don't call this directly; call +// PandaNode::prepare_scene() or +// NodePath::prepare_scene() instead. +//////////////////////////////////////////////////////////////////// +void PandaNode:: +r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects) { + int num_children = get_num_children(); + for (int i = 0; i < num_children; i++) { + PandaNode *child = get_child(i); + CPT(RenderState) child_state = state->compose(child->get_state()); + child->r_prepare_scene(child_state, prepared_objects); + } +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::set_cull_callback // Access: Protected diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index d6cc49e256..577c155d60 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -60,6 +60,7 @@ class Light; class FactoryParams; class AccumulatedAttribs; class GeomTransformer; +class GraphicsStateGuardianBase; //////////////////////////////////////////////////////////////////// // Class : PandaNode @@ -239,6 +240,8 @@ PUBLISHED: CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const; CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const; + void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *net_state); + virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; @@ -314,6 +317,10 @@ protected: void set_cull_callback(); +public: + virtual void r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects); + protected: // This is a base class of CData, defined below. It contains just // the protected (not private) part of CData that will be needed by diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index 9e68a60f53..ac2efabfb4 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -335,6 +335,30 @@ compute_internal_bounds(PandaNode::BoundsData *bdata, int pipeline_stage, bdata->_internal_bounds_stale = false; } +//////////////////////////////////////////////////////////////////// +// Function: PGItem::r_prepare_scene +// Access: Protected, Virtual +// Description: The recursive implementation of prepare_scene(). +// Don't call this directly; call +// PandaNode::prepare_scene() or +// NodePath::prepare_scene() instead. +//////////////////////////////////////////////////////////////////// +void PGItem:: +r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects) { + StateDefs::iterator di; + for (di = _state_defs.begin(); di != _state_defs.end(); ++di) { + NodePath &root = (*di)._root; + if (!root.is_empty()) { + PandaNode *child = root.node(); + CPT(RenderState) child_state = state->compose(child->get_state()); + child->r_prepare_scene(child_state, prepared_objects); + } + } + + PandaNode::r_prepare_scene(state, prepared_objects); +} + //////////////////////////////////////////////////////////////////// // Function: PGItem::xform // Access: Public, Virtual diff --git a/panda/src/pgui/pgItem.h b/panda/src/pgui/pgItem.h index 7119b3881a..1c2daed7af 100644 --- a/panda/src/pgui/pgItem.h +++ b/panda/src/pgui/pgItem.h @@ -68,6 +68,9 @@ protected: virtual void compute_internal_bounds(BoundsData *bdata, int pipeline_stage, Thread *current_thread) const; + virtual void r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects); + public: virtual void xform(const LMatrix4f &mat); bool activate_region(const LMatrix4f &transform, int sort, diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 2cfc616cd5..e6072767f1 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -649,6 +649,28 @@ compute_internal_bounds(PandaNode::BoundsData *bdata, int pipeline_stage, bdata->_internal_bounds_stale = false; } +//////////////////////////////////////////////////////////////////// +// Function: TextNode::r_prepare_scene +// Access: Protected, Virtual +// Description: The recursive implementation of prepare_scene(). +// Don't call this directly; call +// PandaNode::prepare_scene() or +// NodePath::prepare_scene() instead. +//////////////////////////////////////////////////////////////////// +void TextNode:: +r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects) { + check_rebuild(); + + PandaNode *child = _internal_geom; + if (child != (PandaNode *)NULL) { + CPT(RenderState) child_state = state->compose(child->get_state()); + child->r_prepare_scene(child_state, prepared_objects); + } + + PandaNode::r_prepare_scene(state, prepared_objects); +} + //////////////////////////////////////////////////////////////////// // Function: TextNode::do_rebuild // Access: Private diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 12b81286eb..5678d35d12 100644 --- a/panda/src/text/textNode.h +++ b/panda/src/text/textNode.h @@ -242,6 +242,9 @@ public: virtual void compute_internal_bounds(BoundsData *bdata, int pipeline_stage, Thread *current_thread) const; + virtual void r_prepare_scene(const RenderState *state, + PreparedGraphicsObjects *prepared_objects); + private: INLINE void invalidate_no_measure(); INLINE void invalidate_with_measure(); diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index 950337528f..dbbaa61dda 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -1468,6 +1468,47 @@ prepare_texture(Texture *tex) { return gtc; } +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::update_texture +// Access: Public, Virtual +// Description: Ensures that the current Texture data is refreshed +// onto the GSG. This means updating the texture +// properties and/or re-uploading the texture image, if +// necessary. This should only be called within the +// draw thread. +// +// If force is true, this function will not return until +// the texture has been fully uploaded. If force is +// false, the function may choose to upload a simple +// version of the texture instead, if the texture is not +// fully resident (and if get_incomplete_render() is +// true). +//////////////////////////////////////////////////////////////////// +bool TinyGraphicsStateGuardian:: +update_texture(TextureContext *tc, bool force) { + apply_texture(tc); + + TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); + + GLTexture *gltex = >c->_gltex; + + if (gtc->was_image_modified() || gltex->num_levels == 0) { + // If the texture image was modified, reload the texture. + bool okflag = upload_texture(gtc); + if (!okflag) { + tinydisplay_cat.error() + << "Could not load " << *gtc->get_texture() << "\n"; + return false; + } + } + gtc->enqueue_lru(&_textures_lru); + + _c->current_texture = gltex; + _c->zb->current_texture = gltex->levels; + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::release_texture // Access: Public, Virtual @@ -1874,7 +1915,7 @@ do_issue_texture() { } // Then, turn on the current texture mode. - if (!apply_texture(tc)) { + if (!update_texture(tc, false)) { return; } @@ -1981,22 +2022,6 @@ apply_texture(TextureContext *tc) { TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); gtc->set_active(true); - - GLTexture *gltex = >c->_gltex; - - if (gtc->was_image_modified() || gltex->num_levels == 0) { - // If the texture image was modified, reload the texture. - bool okflag = upload_texture(gtc); - if (!okflag) { - tinydisplay_cat.error() - << "Could not load " << *gtc->get_texture() << "\n"; - return false; - } - } - gtc->enqueue_lru(&_textures_lru); - - _c->current_texture = gltex; - _c->zb->current_texture = gltex->levels; return true; } diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h index 04c7fb0464..8ba9244233 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h @@ -85,6 +85,7 @@ public: const TransformState *transform); virtual TextureContext *prepare_texture(Texture *tex); + virtual bool update_texture(TextureContext *tc, bool force); virtual void release_texture(TextureContext *tc); virtual void do_issue_light();