mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -04:00
Add gsg::update_texture()
This commit is contained in:
parent
189626a483
commit
8c2e657f15
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,17 +3319,43 @@ 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);
|
||||
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 {
|
||||
GLP(CopyTexSubImage2D)(GL_TEXTURE_2D, 0, 0, 0, xo, yo, w, h);
|
||||
// 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();
|
||||
|
||||
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user