split out PreparedGraphicsObjects from GraphicsStateGuardians

This commit is contained in:
David Rose 2004-02-25 19:34:30 +00:00
parent 0e81017698
commit 232f9395bf
28 changed files with 589 additions and 377 deletions

View File

@ -551,7 +551,7 @@ get_screenshot(PNMImage &image) {
PixelBuffer::F_rgb);
RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type());
if (!p.copy(gsg, this, buffer)) {
if (!gsg->copy_pixel_buffer(&p, this, buffer)) {
return false;
}

View File

@ -1,5 +1,5 @@
// Filename: graphicsBuffer.h
// Created by: mike (09Jan97)
// Created by: drose (06Feb04)
//
////////////////////////////////////////////////////////////////////
//

View File

@ -437,7 +437,8 @@ end_frame() {
nassertv(has_texture());
DisplayRegion dr(this, _x_size, _y_size);
RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
get_texture()->copy(_gsg, &dr, buffer);
TextureContext *tc = get_texture()->prepare_now(_gsg->get_prepared_objects(), _gsg);
_gsg->copy_texture(tc, &dr, buffer);
}
}

View File

@ -40,6 +40,17 @@ ClipPlaneInfo() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::release_all_textures
// Access: Public
// Description: Frees the resources for all textures associated with
// this GSG.
////////////////////////////////////////////////////////////////////
INLINE int GraphicsStateGuardian::
release_all_textures() {
return _prepared_objects->release_all_textures();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::set_active
// Access: Published

View File

@ -79,6 +79,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties) {
_needs_reset = true;
_closing_gsg = false;
_active = true;
_prepared_objects = new PreparedGraphicsObjects;
}
////////////////////////////////////////////////////////////////////
@ -146,58 +147,15 @@ get_render_buffer(int buffer_type) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::release_all_textures
// Access: Public
// Description: Frees the resources for all textures associated with
// this GSG.
// Function: GraphicsStateGuardian::get_prepared_objects
// Access: Public, Virtual
// Description: Returns the set of texture and geom objects that have
// been prepared with this GSG (and possibly other GSG's
// that share objects).
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
release_all_textures() {
// We must get a copy of the _prepared_textures list first, because
// each call to release_texture() will remove that texture from the
// list, and we don't want to traverse a list while we're modifying
// it!
Textures temp = _prepared_textures;
for (Textures::const_iterator ti = temp.begin();
ti != temp.end();
++ti) {
release_texture(*ti);
}
// Now that we've released all of the textures, the
// _prepared_textures list should have completely emptied itself.
nassertv(_prepared_textures.empty());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::release_all_geoms
// Access: Public
// Description: Frees the resources for all Geoms and GeomNodes
// associated with this GSG. Warning! This may make
// the Geoms unrenderable, if the Panda-level
// information has been deleted.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
release_all_geoms() {
// As above, for both Geoms and GeomNodes.
Geoms temp_geoms = _prepared_geoms;
for (Geoms::const_iterator gi = temp_geoms.begin();
gi != temp_geoms.end();
++gi) {
release_geom(*gi);
}
GeomNodes temp_geom_nodes = _prepared_geom_nodes;
for (GeomNodes::const_iterator gni = temp_geom_nodes.begin();
gni != temp_geom_nodes.end();
++gni) {
release_geom_node(*gni);
}
nassertv(_prepared_geoms.empty());
nassertv(_prepared_geom_nodes.empty());
PreparedGraphicsObjects *GraphicsStateGuardian::
get_prepared_objects() {
return _prepared_objects;
}
////////////////////////////////////////////////////////////////////
@ -397,6 +355,12 @@ prepare_lens() {
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
begin_frame() {
// Now we know the GSG is the currently active context, so this is a
// good time to release any textures or geoms that had been queued
// up to release in the past frame, and load up any newly requested
// textures.
_prepared_objects->update(this);
// Undo any lighting we had enabled last frame, to force the lights
// to be reissued, in case their parameters or positions have
// changed between frames.
@ -1229,126 +1193,6 @@ set_blend_mode(ColorWriteAttrib::Mode, ColorBlendAttrib::Mode,
TransparencyAttrib::Mode) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::mark_prepared_texture
// Access: Protected
// Description: This is intended to be called from within
// prepare_texture(). It adds the indicated
// TextureContext pointer to the _prepared_textures set,
// and returns true if it was successfully added
// (i.e. it was not already in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
mark_prepared_texture(TextureContext *tc) {
bool prepared = _prepared_textures.insert(tc).second;
#ifdef DO_PSTATS
if (prepared) {
_total_texusage_pcollector.add_level(tc->estimate_texture_memory());
}
#endif
return prepared;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::unmark_prepared_texture
// Access: Protected
// Description: This is intended to be called from within
// release_texture(). It removes the indicated
// TextureContext pointer from the _prepared_textures
// set, and returns true if it was successfully removed
// (i.e. it had been in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
unmark_prepared_texture(TextureContext *tc) {
bool removed = (_prepared_textures.erase(tc) != 0);
#ifdef DO_PSTATS
if (removed) {
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
}
#endif
return removed;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::mark_prepared_geom
// Access: Protected
// Description: This is intended to be called from within
// prepare_geom(). It adds the indicated GeomContext
// pointer to the _prepared_geoms set, and returns true
// if it was successfully added (i.e. it was not already
// in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
mark_prepared_geom(GeomContext *gc) {
bool prepared = _prepared_geoms.insert(gc).second;
#ifdef DO_PSTATS
if (prepared) {
_total_geom_pcollector.add_level(1);
}
#endif
return prepared;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::unmark_prepared_geom
// Access: Protected
// Description: This is intended to be called from within
// release_geom(). It removes the indicated GeomContext
// pointer from the _prepared_geoms set, and returns
// true if it was successfully removed (i.e. it had been
// in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
unmark_prepared_geom(GeomContext *gc) {
bool removed = (_prepared_geoms.erase(gc) != 0);
#ifdef DO_PSTATS
if (removed) {
_total_geom_pcollector.sub_level(1);
}
#endif
return removed;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::mark_prepared_geom_node
// Access: Protected
// Description: This is intended to be called from within
// prepare_geom_node(). It adds the indicated
// GeomNodeContext pointer to the _prepared_geom_nodes
// set, and returns true if it was successfully added
// (i.e. it was not already in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
mark_prepared_geom_node(GeomNodeContext *gnc) {
bool prepared = _prepared_geom_nodes.insert(gnc).second;
#ifdef DO_PSTATS
if (prepared) {
_total_geom_node_pcollector.add_level(1);
}
#endif
return prepared;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::unmark_prepared_geom_node
// Access: Protected
// Description: This is intended to be called from within
// release_geom_node(). It removes the indicated
// GeomNodeContext pointer from the _prepared_geom_nodes
// set, and returns true if it was successfully removed
// (i.e. it had been in the set).
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
unmark_prepared_geom_node(GeomNodeContext *gnc) {
bool removed = (_prepared_geom_nodes.erase(gnc) != 0);
#ifdef DO_PSTATS
if (removed) {
_total_geom_node_pcollector.sub_level(1);
}
#endif
return removed;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::free_pointers
// Access: Protected, Virtual
@ -1371,8 +1215,18 @@ void GraphicsStateGuardian::
close_gsg() {
_closing_gsg = true;
free_pointers();
release_all_textures();
release_all_geoms();
// If we're not sharing the prepared objects list with any other
// GSG, go ahread and release all the textures and geoms now. This
// isn't really a reliable test of whether we are sharing this list,
// but it's not too important if we get this wrong since this ought
// to be an optional cleanup anyway. (Presumably, the underlying
// graphics API will properly clean up outstanding textures and
// geoms when the last context using them is released.)
if (_prepared_objects->get_ref_count() == 1) {
release_all_textures();
//release_all_geoms();
}
}
////////////////////////////////////////////////////////////////////
@ -1522,7 +1376,9 @@ get_untextured_state() {
void GraphicsStateGuardian::
traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
for (Textures::const_iterator ti = _prepared_textures.begin(); ti != _prepared_textures.end();
PreparedGraphicsObjects::Textures::const_iterator ti;
for (ti = _prepared_objects->_prepared_textures.begin();
ti != _prepared_objects->_prepared_textures.end();
++ti) {
bool bResult=(*pertex_callbackfn)(*ti,callback_arg);
if(!bResult)

View File

@ -26,6 +26,7 @@
#include "frameBufferProperties.h"
#include "displayRegionStack.h"
#include "lensStack.h"
#include "preparedGraphicsObjects.h"
#include "graphicsStateGuardianBase.h"
#include "graphicsThreadingModel.h"
@ -69,8 +70,8 @@ public:
virtual ~GraphicsStateGuardian();
PUBLISHED:
void release_all_textures();
void release_all_geoms();
INLINE int release_all_textures();
// int release_all_geoms();
INLINE void set_active(bool active);
INLINE bool is_active() const;
@ -84,6 +85,8 @@ public:
INLINE void set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
virtual PreparedGraphicsObjects *get_prepared_objects();
virtual TextureContext *prepare_texture(Texture *tex);
virtual void apply_texture(TextureContext *tc);
virtual void release_texture(TextureContext *tc);
@ -193,13 +196,6 @@ protected:
CPT(DisplayRegion) dr)=0;
virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer)=0;
bool mark_prepared_texture(TextureContext *tc);
bool unmark_prepared_texture(TextureContext *tc);
bool mark_prepared_geom(GeomContext *gc);
bool unmark_prepared_geom(GeomContext *gc);
bool mark_prepared_geom_node(GeomNodeContext *gnc);
bool unmark_prepared_geom_node(GeomNodeContext *gnc);
virtual void free_pointers();
virtual void close_gsg();
void panic_deactivate();
@ -276,6 +272,8 @@ protected:
bool _closing_gsg;
bool _active;
PT(PreparedGraphicsObjects) _prepared_objects;
public:
// Statistics
static PStatCollector _total_texusage_pcollector;
@ -321,15 +319,6 @@ private:
pvector<ClipPlaneInfo> _clip_plane_info;
bool _clip_planes_enabled_this_frame;
// NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access
// these sets directly due to exported template issue
typedef pset<TextureContext *> Textures;
Textures _prepared_textures;
typedef pset<GeomContext *> Geoms;
Geoms _prepared_geoms;
typedef pset<GeomNodeContext *> GeomNodes;
GeomNodes _prepared_geom_nodes;
FrameBufferProperties _properties;
PT(GraphicsPipe) _pipe;
GraphicsEngine *_engine;

View File

@ -608,8 +608,9 @@ render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) {
// Copy the results of the render from the frame buffer into the
// screen's texture.
screen._texture->copy(_gsg, scratch_region,
_gsg->get_render_buffer(RenderBuffer::T_back));
TextureContext *tc = screen._texture->prepare_now(_gsg->get_prepared_objects(), _gsg);
_gsg->copy_texture(tc, scratch_region,
_gsg->get_render_buffer(RenderBuffer::T_back));
// It might be nice if we didn't throw away the scratch region every
// time, which prevents us from preserving cull state from one frame

View File

@ -1643,6 +1643,9 @@ draw_sphere(GeomSphere *geom, GeomContext *) {
// responsibility of the calling function to later
// call release_texture() with this same pointer (which
// will also delete the pointer).
//
// This function should not be called directly to
// prepare a texture. Instead, call Texture::prepare().
////////////////////////////////////////////////////////////////////
TextureContext *CLP(GraphicsStateGuardian)::
prepare_texture(Texture *tex) {
@ -1654,13 +1657,6 @@ prepare_texture(Texture *tex) {
specify_texture(tex);
apply_texture_immediate(tex);
bool inserted = mark_prepared_texture(gtc);
// If this assertion fails, the same texture was prepared twice,
// which shouldn't be possible, since the texture itself should
// detect this.
nassertr(inserted, gtc);
report_my_gl_errors();
return gtc;
}
@ -1695,32 +1691,19 @@ apply_texture(TextureContext *tc) {
// Function: CLP(GraphicsStateGuardian)::release_texture
// Access: Public, Virtual
// Description: Frees the GL resources previously allocated for the
// texture.
// texture. This function should never be called
// directly; instead, call Texture::release() (or simply
// let the Texture destruct).
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
release_texture(TextureContext *tc) {
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
Texture *tex = tc->_texture;
if (!_closing_gsg) {
// Don't bother to delete the GL texture if we're about to destroy
// the context anyway.
GLP(DeleteTextures)(1, &gtc->_index);
}
GLP(DeleteTextures)(1, &gtc->_index);
report_my_gl_errors();
gtc->_index = 0;
bool erased = unmark_prepared_texture(gtc);
// If this assertion fails, a texture was released that hadn't been
// prepared (or a texture was released twice).
nassertv(erased);
tex->clear_gsg(this);
delete gtc;
if (!_closing_gsg) {
report_my_gl_errors();
}
}
////////////////////////////////////////////////////////////////////
@ -1811,7 +1794,7 @@ prepare_geom_node(GeomNode *node) {
_texturing_enabled = old_texturing_enabled;
_vertex_colors_enabled = old_vertex_colors_enabled;
bool inserted = mark_prepared_geom_node(ggnc);
bool inserted = _prepared_objects->mark_prepared_geom_node(ggnc);
// If this assertion fails, the same GeomNode was prepared twice,
// which shouldn't be possible, since the GeomNode itself should
@ -1875,7 +1858,7 @@ release_geom_node(GeomNodeContext *gnc) {
CLP(GeomNodeContext) *ggnc = DCAST(CLP(GeomNodeContext), gnc);
GLP(DeleteLists)(ggnc->_index, 1);
bool erased = unmark_prepared_geom_node(ggnc);
bool erased = _prepared_objects->unmark_prepared_geom_node(ggnc);
// If this assertion fails, a GeomNode was released that hadn't
// been prepared (or a GeomNode was released twice).
@ -2220,7 +2203,9 @@ issue_texture(const TextureAttrib *attrib) {
enable_texturing(true);
Texture *tex = attrib->get_texture();
nassertv(tex != (Texture *)NULL);
tex->apply(this);
TextureContext *tc = tex->prepare_now(_prepared_objects, this);
apply_texture(tc);
}
report_my_gl_errors();
}
@ -3916,7 +3901,8 @@ save_frame_buffer(const RenderBuffer &buffer,
if (buffer._buffer_type & RenderBuffer::T_back) {
// Save the color buffer.
sfb->_back_rgba = new Texture;
copy_texture(sfb->_back_rgba->prepare(this), dr, buffer);
TextureContext *tc = sfb->_back_rgba->prepare_now(_prepared_objects, this);
copy_texture(tc, dr, buffer);
}
return sfb;
@ -3934,8 +3920,8 @@ restore_frame_buffer(SavedFrameBuffer *frame_buffer) {
if (sfb->_back_rgba != (Texture *)NULL &&
(sfb->_buffer._buffer_type & RenderBuffer::T_back) != 0) {
// Restore the color buffer.
draw_texture(sfb->_back_rgba->prepare(this),
sfb->_display_region, sfb->_buffer);
TextureContext *tc = sfb->_back_rgba->prepare_now(_prepared_objects, this);
draw_texture(tc, sfb->_display_region, sfb->_buffer);
}
if (sfb->_depth != (PixelBuffer *)NULL &&

View File

@ -183,7 +183,7 @@ make_gsg(const FrameBufferProperties &properties) {
// Now we can make a GSG.
PT(glxGraphicsStateGuardian) gsg =
new glxGraphicsStateGuardian(new_properties, context, fbconfig,
new glxGraphicsStateGuardian(new_properties, NULL, context, fbconfig,
_display, _screen);
return gsg.p();
}

View File

@ -28,6 +28,7 @@ TypeHandle glxGraphicsStateGuardian::_type_handle;
////////////////////////////////////////////////////////////////////
glxGraphicsStateGuardian::
glxGraphicsStateGuardian(const FrameBufferProperties &properties,
glxGraphicsStateGuardian *share_with,
GLXContext context, GLXFBConfig fbconfig,
Display *display, int screen) :
GLGraphicsStateGuardian(properties),
@ -36,6 +37,9 @@ glxGraphicsStateGuardian(const FrameBufferProperties &properties,
_display(display),
_screen(screen)
{
if (share_with != (glxGraphicsStateGuardian *)NULL) {
_prepared_objects = share_with->get_prepared_objects();
}
}
////////////////////////////////////////////////////////////////////

View File

@ -32,6 +32,7 @@
class glxGraphicsStateGuardian : public GLGraphicsStateGuardian {
public:
glxGraphicsStateGuardian(const FrameBufferProperties &properties,
glxGraphicsStateGuardian *share_with,
GLXContext context, GLXFBConfig fbconfig,
Display *display, int screen);
virtual ~glxGraphicsStateGuardian();

View File

@ -4,7 +4,7 @@
#begin lib_target
#define TARGET gobj
#define LOCAL_LIBS \
event linmath mathutil pnmimage gsgbase putil
pstatclient event linmath mathutil pnmimage gsgbase putil
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
@ -19,7 +19,9 @@
matrixLens.I matrixLens.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
perspectiveLens.h pixelBuffer.I pixelBuffer.N \
pixelBuffer.h lens.h lens.I \
pixelBuffer.h \
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
savedContext.I savedContext.h \
texture.I texture.N texture.h \
textureContext.I textureContext.h \
@ -33,7 +35,9 @@
geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \
geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx \
materialPool.cxx matrixLens.cxx orthographicLens.cxx \
perspectiveLens.cxx pixelBuffer.cxx lens.cxx \
perspectiveLens.cxx pixelBuffer.cxx \
preparedGraphicsObjects.cxx \
lens.cxx \
savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx
#define INSTALL_HEADERS \
@ -47,6 +51,7 @@
materialPool.I materialPool.h matrixLens.I matrixLens.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
perspectiveLens.h pixelBuffer.I pixelBuffer.h \
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
savedContext.I savedContext.h \
texture.I texture.h \

View File

@ -138,8 +138,10 @@ ostream &operator << (ostream &out, GeomAttrType t) {
////////////////////////////////////////////////////////////////////
Geom::
Geom(void) : dDrawable() {
/*
_prepared_gsg = (GraphicsStateGuardianBase *)NULL;
_prepared_context = (GeomContext *)NULL;
*/
init();
}
@ -150,8 +152,10 @@ Geom(void) : dDrawable() {
////////////////////////////////////////////////////////////////////
Geom::
Geom(const Geom& copy) : dDrawable() {
/*
_prepared_gsg = (GraphicsStateGuardianBase *)NULL;
_prepared_context = (GeomContext *)NULL;
*/
*this = copy;
}
@ -162,7 +166,7 @@ Geom(const Geom& copy) : dDrawable() {
////////////////////////////////////////////////////////////////////
Geom::
~Geom() {
unprepare();
// unprepare();
}
////////////////////////////////////////////////////////////////////
@ -463,9 +467,10 @@ draw(GraphicsStateGuardianBase *gsg) {
if (is_dirty()) {
config();
}
/*
if (_prepared_gsg == gsg) {
draw_immediate(gsg, _prepared_context);
} else {
} else */ {
draw_immediate(gsg, (GeomContext *)NULL);
}
}
@ -513,7 +518,7 @@ config() {
}
// Mark the Geom as needing to be prepared again.
unprepare();
// unprepare();
}
////////////////////////////////////////////////////////////////////
@ -547,6 +552,7 @@ output(ostream &out) const {
*/
}
/*
////////////////////////////////////////////////////////////////////
// Function: Geom::prepare
// Access: Public
@ -620,6 +626,7 @@ clear_gsg(GraphicsStateGuardianBase *gsg) {
_prepared_context = (GeomContext *)NULL;
}
}
*/
////////////////////////////////////////////////////////////////////
// Function: Geom::init

View File

@ -224,10 +224,12 @@ public:
INLINE ColorIterator make_color_iterator() const;
INLINE const Colorf &get_next_color(ColorIterator &citerator) const;
/*
GeomContext *prepare(GraphicsStateGuardianBase *gsg);
void unprepare();
void unprepare(GraphicsStateGuardianBase *gsg);
void clear_gsg(GraphicsStateGuardianBase *gsg);
*/
protected:
void init();
@ -261,8 +263,10 @@ protected:
// intended to reduce memory overhead that would otherwise be
// required to support a little-used feature (having two
// simultaneous GSG's).
/*
GraphicsStateGuardianBase *_prepared_gsg;
GeomContext *_prepared_context;
*/
public:
//static void register_with_read_factory(void);

View File

@ -9,6 +9,7 @@
#include "matrixLens.cxx"
#include "perspectiveLens.cxx"
#include "pixelBuffer.cxx"
#include "preparedGraphicsObjects.cxx"
#include "lens.cxx"
#include "savedContext.cxx"
#include "texture.cxx"

View File

@ -43,10 +43,6 @@ PUBLISHED:
public:
virtual void config( void ) { WritableConfigurable::config(); }
virtual bool copy(GraphicsStateGuardianBase *, const DisplayRegion *)=0;
virtual bool copy(GraphicsStateGuardianBase *, const DisplayRegion *,
const RenderBuffer &rb)=0;
PUBLISHED:
INLINE bool has_filename() const;
INLINE const Filename &get_filename() const;

View File

@ -421,13 +421,3 @@ copy(const PixelBuffer *pb) {
if (!pb->_image.empty())
_image.v() = pb->_image.v();
}
bool PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
return gsg->copy_pixel_buffer(this, dr);
}
bool PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
const RenderBuffer &rb) {
return gsg->copy_pixel_buffer(this, dr, rb);
}

View File

@ -105,10 +105,6 @@ public:
bool store( PNMImage& pnmimage ) const;
void copy(const PixelBuffer *pb);
virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
const RenderBuffer &rb);
INLINE void set_xsize(int size);
INLINE void set_ysize(int size);

View File

@ -0,0 +1,18 @@
// Filename: preparedGraphicsObjects.I
// Created by: drose (23Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,243 @@
// Filename: preparedGraphicsObjects.cxx
// Created by: drose (19Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "preparedGraphicsObjects.h"
#include "textureContext.h"
#include "mutexHolder.h"
#ifndef CPPPARSER
PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
#endif // CPPPARSER
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PreparedGraphicsObjects::
PreparedGraphicsObjects() {
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PreparedGraphicsObjects::
~PreparedGraphicsObjects() {
// There may be texture objects that are still prepared when we
// destruct. If this is so, then all of the GSG's that own them
// have already destructed, so we can assume their resources were
// internally cleaned up. Quietly erase these remaining textures.
MutexHolder holder(_lock);
Textures::iterator tci;
for (tci = _prepared_textures.begin();
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
tc->_texture->clear_prepared(this);
}
_prepared_textures.clear();
_released_textures.clear();
_enqueued_textures.clear();
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::enqueue_texture
// Access: Public
// Description: Indicates that a texture would like to be put on the
// list to be prepared when the GSG is next ready to
// do this (presumably at the next frame).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
enqueue_texture(Texture *tex) {
MutexHolder holder(_lock);
_enqueued_textures.insert(tex);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::dequeue_texture
// Access: Public
// Description: Removes a texture from the queued list of textures to
// be prepared. Normally it is not necessary to call
// this, unless you change your mind about preparing it
// at the last minute, since the texture will
// automatically be dequeued and prepared at the next
// frame.
//
// The return value is true if the texture is
// successfully dequeued, false if it had not been
// queued.
////////////////////////////////////////////////////////////////////
bool PreparedGraphicsObjects::
dequeue_texture(Texture *tex) {
MutexHolder holder(_lock);
EnqueuedTextures::iterator qi = _enqueued_textures.find(tex);
if (qi != _enqueued_textures.end()) {
_enqueued_textures.erase(qi);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_texture
// Access: Public
// Description: Indicates that a texture context, created by a
// previous call to prepare_texture(), is no longer
// needed. The driver resources will not be freed until
// some GSG calls update(), indicating it is at a
// stage where it is ready to release textures--this
// prevents conflicts from threading or multiple GSG's
// sharing textures (we have no way of knowing which
// graphics context is currently active, or what state
// it's in, at the time release_texture is called).
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
release_texture(TextureContext *tc) {
MutexHolder holder(_lock);
tc->_texture->clear_prepared(this);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
// We have to set the Texture pointer to NULL at this point, since
// the Texture itself might destruct at any time after it has been
// released.
tc->_texture = (Texture *)NULL;
bool removed = (_prepared_textures.erase(tc) != 0);
nassertv(removed);
_released_textures.insert(tc);
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_all_textures
// Access: Public
// Description: Releases all textures at once. This will force them
// to be reloaded into texture memory for all GSG's that
// share this object. Returns the number of textures
// released.
////////////////////////////////////////////////////////////////////
int PreparedGraphicsObjects::
release_all_textures() {
MutexHolder holder(_lock);
int num_textures = (int)_prepared_textures.size();
Textures::iterator tci;
for (tci = _prepared_textures.begin();
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
tc->_texture->clear_prepared(this);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
tc->_texture = (Texture *)NULL;
_released_textures.insert(tc);
}
_prepared_textures.clear();
return num_textures;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::prepare_texture_now
// Access: Public
// Description: Immediately creates a new TextureContext for the
// indicated texture and returns it. This assumes that
// the GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// textures. If this is not necessarily the case, you
// should use enqueue_texture() instead.
//
// Normally, this function is not called directly. Call
// Texture::prepare_now() instead.
//
// The TextureContext contains all of the pertinent
// information needed by the GSG to keep track of this
// one particular texture, and will exist as long as the
// texture is ready to be rendered.
//
// When either the Texture or the
// PreparedGraphicsObjects object destructs, the
// TextureContext will be deleted.
////////////////////////////////////////////////////////////////////
TextureContext *PreparedGraphicsObjects::
prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// Ask the GSG to create a brand new TextureContext. There might
// be several GSG's sharing the same set of textures; if so, it
// doesn't matter which of them creates the context (since they're
// all shared anyway).
TextureContext *tc = gsg->prepare_texture(tex);
bool prepared = _prepared_textures.insert(tc).second;
nassertr(prepared, tc);
_total_texusage_pcollector.add_level(tc->estimate_texture_memory());
return tc;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::update
// Access: Public
// Description: This is called by the GraphicsStateGuardian to
// indicate that it is in a state to load or release
// textures.
//
// Any texture contexts that were previously passed to
// release_texture() are actually passed to the GSG to
// be freed at this point; textures that were previously
// passed to prepare_texture are actually loaded.
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
update(GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
// First, release all the textures awaiting release.
Textures::iterator tci;
for (tci = _released_textures.begin();
tci != _released_textures.end();
++tci) {
TextureContext *tc = (*tci);
gsg->release_texture(tc);
}
_released_textures.clear();
// Now prepare all the textures awaiting preparation.
EnqueuedTextures::iterator qi;
for (qi = _enqueued_textures.begin();
qi != _enqueued_textures.end();
++qi) {
Texture *tex = (*qi);
tex->prepare_now(this, gsg);
}
_enqueued_textures.clear();
}

View File

@ -0,0 +1,80 @@
// Filename: preparedGraphicsObjects.h
// Created by: drose (19Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef PREPAREDGRAPHICSOBJECTS_H
#define PREPAREDGRAPHICSOBJECTS_H
#include "pandabase.h"
#include "referenceCount.h"
#include "texture.h"
#include "pStatCollector.h"
#include "pset.h"
#include "pmutex.h"
class TextureContext;
class GeomContext;
class GeomNodeContext;
class GraphicsStateGuardianBase;
////////////////////////////////////////////////////////////////////
// Class : PreparedGraphicsObjects
// Description : A table of objects that are saved within the graphics
// context for reference by handle later. Generally,
// this represents things like OpenGL texture objects or
// display lists.
//
// This object simply records the pointers to the
// context objects created by the individual GSG's;
// these context objects will contain enough information
// to reference or release the actual object stored
// within the graphics context.
//
// These tables may potentially be shared between
// related graphics contexts, hence their storage here
// in a separate object rather than as a part of the
// GraphicsStateGuardian.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PreparedGraphicsObjects : public ReferenceCount {
public:
PreparedGraphicsObjects();
~PreparedGraphicsObjects();
void enqueue_texture(Texture *tex);
bool dequeue_texture(Texture *tex);
void release_texture(TextureContext *tc);
int release_all_textures();
TextureContext *prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg);
void update(GraphicsStateGuardianBase *gsg);
private:
typedef pset<TextureContext *> Textures;
typedef pset< PT(Texture) > EnqueuedTextures;
Mutex _lock;
Textures _prepared_textures, _released_textures;
EnqueuedTextures _enqueued_textures;
static PStatCollector _total_texusage_pcollector;
friend class GraphicsStateGuardian;
};
#include "preparedGraphicsObjects.I"
#endif

View File

@ -150,14 +150,4 @@ get_keep_ram_image() const {
return _keep_ram_image;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::apply
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Texture::
apply(GraphicsStateGuardianBase *gsg) {
gsg->apply_texture(prepare(gsg));
}

View File

@ -26,6 +26,7 @@
#include "bamReader.h"
#include "bamWriter.h"
#include "string_utils.h"
#include "preparedGraphicsObjects.h"
#include <stddef.h>
@ -126,7 +127,7 @@ consider_downgrade(PNMImage &pnmimage, int num_channels,
}
////////////////////////////////////////////////////////////////////
// Function: Constructor
// Function: Texture::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -146,7 +147,7 @@ Texture() : ImageBuffer() {
////////////////////////////////////////////////////////////////////
// Function: Constructor
// Function: Texture::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -166,17 +167,17 @@ Texture(int xsize, int ysize, int components, int component_width, PixelBuffer::
}
////////////////////////////////////////////////////////////////////
// Function: Destructor
// Function: Texture::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
Texture::
~Texture() {
unprepare();
release_all();
}
////////////////////////////////////////////////////////////////////
// Function: read
// Function: Texture::read
// Access: Published
// Description: Reads the texture from the indicated filename. If
// num_channels is not 0, it specifies the number of
@ -215,7 +216,7 @@ read(const Filename &fullpath, int primary_file_num_channels) {
}
////////////////////////////////////////////////////////////////////
// Function: read
// Function: Texture::read
// Access: Published
// Description: Combine a 3-component image with a grayscale image
// to get a 4-component image
@ -309,7 +310,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
}
////////////////////////////////////////////////////////////////////
// Function: write
// Function: Texture::write
// Access: Published
// Description: Writes the texture to the indicated filename.
////////////////////////////////////////////////////////////////////
@ -330,7 +331,7 @@ write(const Filename &name) const {
}
////////////////////////////////////////////////////////////////////
// Function: set_wrapu
// Function: Texture::set_wrapu
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -343,7 +344,7 @@ set_wrapu(Texture::WrapMode wrap) {
}
////////////////////////////////////////////////////////////////////
// Function: set_wrapv
// Function: Texture::set_wrapv
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -356,7 +357,7 @@ set_wrapv(Texture::WrapMode wrap) {
}
////////////////////////////////////////////////////////////////////
// Function: set_minfilter
// Function: Texture::set_minfilter
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -373,7 +374,7 @@ set_minfilter(Texture::FilterType filter) {
}
////////////////////////////////////////////////////////////////////
// Function: set_magfilter
// Function: Texture::set_magfilter
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -386,7 +387,7 @@ set_magfilter(Texture::FilterType filter) {
}
////////////////////////////////////////////////////////////////////
// Function: set_anisotropic_degree
// Function: Texture::set_anisotropic_degree
// Access: Published
// Description: Specifies the level of anisotropic filtering to apply
// to the texture. Normally, this is 1, to indicate
@ -403,7 +404,7 @@ set_anisotropic_degree(int anisotropic_degree) {
}
////////////////////////////////////////////////////////////////////
// Function: set_border_color
// Function: Texture::set_border_color
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
@ -413,7 +414,24 @@ set_border_color(const Colorf &color) {
}
////////////////////////////////////////////////////////////////////
// Function: load
// Function: Texture::prepare
// Access: Published
// Description: Indicates that the texture should be enqueued to be
// prepared in the indicated prepared_objects at the
// beginning of the next frame. This will ensure the
// texture is already loaded into texture memory if it
// is expected to be rendered soon.
//
// Use this function instead of prepare_now() to preload
// textures from a user interface standpoint.
////////////////////////////////////////////////////////////////////
void Texture::
prepare(PreparedGraphicsObjects *prepared_objects) {
prepared_objects->enqueue_texture(this);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::load
// Access: Public
// Description: Creates the texture from the already-read PNMImage.
////////////////////////////////////////////////////////////////////
@ -428,7 +446,7 @@ load(const PNMImage &pnmimage) {
}
////////////////////////////////////////////////////////////////////
// Function: store
// Function: Texture::store
// Access: Public
// Description: Saves the texture to the indicated PNMImage, but does
// not write it to disk.
@ -459,22 +477,32 @@ is_mipmap(FilterType type) {
}
////////////////////////////////////////////////////////////////////
// Function: prepare
// Function: Texture::prepare_now
// Access: Public
// Description: Creates a context for the texture on the particular
// GSG, if it does not already exist. Returns the new
// (or old) TextureContext.
// (or old) TextureContext. This assumes that the
// GraphicsStateGuardian is the currently active
// rendering context and that it is ready to accept new
// textures. If this is not necessarily the case, you
// should use prepare_later() instead.
//
// Normally, this is not called directly except by the
// GraphicsStateGuardian; a texture does not need to be
// explicitly prepared by the user before it may be
// rendered.
////////////////////////////////////////////////////////////////////
TextureContext *Texture::
prepare(GraphicsStateGuardianBase *gsg) {
prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg) {
Contexts::const_iterator ci;
ci = _contexts.find(gsg);
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
return (*ci).second;
}
TextureContext *tc = gsg->prepare_texture(this);
_contexts[gsg] = tc;
TextureContext *tc = prepared_objects->prepare_texture_now(this, gsg);
_contexts[prepared_objects] = tc;
// Now that we have a new TextureContext with zero dirty flags, our
// intersection of all dirty flags must be zero. This doesn't mean
@ -498,67 +526,54 @@ prepare(GraphicsStateGuardianBase *gsg) {
}
////////////////////////////////////////////////////////////////////
// Function: Texture::unprepare
// Function: Texture::release
// Access: Public
// Description: Frees the context allocated on all GSG's for which
// the texture has been declared.
// Description: Frees the texture context only on the indicated object,
// if it exists there. Returns true if it was released,
// false if it had not been prepared.
////////////////////////////////////////////////////////////////////
void Texture::
unprepare() {
// We have to traverse a copy of the _contexts list, because the GSG
// will call clear_gsg() in response to each release_texture(), and
// we don't want to be modifying the _contexts list while we're
// traversing it.
bool Texture::
release(PreparedGraphicsObjects *prepared_objects) {
Contexts::iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
TextureContext *tc = (*ci).second;
prepared_objects->release_texture(tc);
return true;
}
// Maybe it wasn't prepared yet, but it's about to be.
return prepared_objects->dequeue_texture(this);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::release_all
// Access: Public
// Description: Frees the context allocated on all objects for which
// the texture has been declared. Returns the number of
// contexts which have been freed.
////////////////////////////////////////////////////////////////////
int Texture::
release_all() {
// We have to traverse a copy of the _contexts list, because the
// PreparedGraphicsObjects object will call clear_prepared() in response
// to each release_texture(), and we don't want to be modifying the
// _contexts list while we're traversing it.
Contexts temp = _contexts;
int num_freed = (int)_contexts.size();
Contexts::const_iterator ci;
for (ci = temp.begin(); ci != temp.end(); ++ci) {
GraphicsStateGuardianBase *gsg = (*ci).first;
PreparedGraphicsObjects *prepared_objects = (*ci).first;
TextureContext *tc = (*ci).second;
gsg->release_texture(tc);
prepared_objects->release_texture(tc);
}
// Now that we've called release_texture() on every known GSG, the
// _contexts list should have completely emptied itself.
nassertv(_contexts.empty());
}
// Now that we've called release_texture() on every known context,
// the _contexts list should have completely emptied itself.
nassertr(_contexts.empty(), num_freed);
////////////////////////////////////////////////////////////////////
// Function: Texture::unprepare
// Access: Public
// Description: Frees the texture context only on the indicated GSG,
// if it exists there.
////////////////////////////////////////////////////////////////////
void Texture::
unprepare(GraphicsStateGuardianBase *gsg) {
Contexts::iterator ci;
ci = _contexts.find(gsg);
if (ci != _contexts.end()) {
TextureContext *tc = (*ci).second;
gsg->release_texture(tc);
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::clear_gsg
// Access: Public
// Description: Removes the indicated GSG from the Texture's known
// GSG's, without actually releasing the texture on that
// GSG. This is intended to be called only from
// GSG::release_texture(); it should never be called by
// user code.
////////////////////////////////////////////////////////////////////
void Texture::
clear_gsg(GraphicsStateGuardianBase *gsg) {
Contexts::iterator ci;
ci = _contexts.find(gsg);
if (ci != _contexts.end()) {
_contexts.erase(ci);
} else {
// If this assertion fails, clear_gsg() was called on a GSG which
// the texture didn't know about.
nassertv(false);
}
return num_freed;
}
////////////////////////////////////////////////////////////////////
@ -606,17 +621,6 @@ get_ram_image() {
}
}
bool Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
gsg->copy_texture(prepare(gsg), dr);
return true;
}
bool Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
const RenderBuffer &rb) {
gsg->copy_texture(prepare(gsg), dr, rb);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::mark_dirty
// Access: Public
@ -650,6 +654,28 @@ mark_dirty(int flags_to_set) {
_all_dirty_flags |= flags_to_set;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::clear_prepared
// Access: Private
// Description: Removes the indicated PreparedGraphicsObjects table
// from the Texture's table, without actually releasing
// the texture. This is intended to be called only from
// PreparedGraphicsObjects::release_texture(); it should
// never be called by user code.
////////////////////////////////////////////////////////////////////
void Texture::
clear_prepared(PreparedGraphicsObjects *prepared_objects) {
Contexts::iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
_contexts.erase(ci);
} else {
// If this assertion fails, clear_prepared() was given a
// prepared_objects which the texture didn't know about.
nassertv(false);
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::string_wrap_mode
// Access: Public

View File

@ -28,6 +28,7 @@
class PNMImage;
class TextureContext;
class FactoryParams;
class PreparedGraphicsObjects;
////////////////////////////////////////////////////////////////////
// Class : Texture
@ -98,28 +99,24 @@ PUBLISHED:
INLINE int get_anisotropic_degree() const;
INLINE bool uses_mipmaps() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
public:
bool load(const PNMImage &pnmimage);
bool store(PNMImage &pnmimage) const;
static bool is_mipmap(FilterType type);
TextureContext *prepare(GraphicsStateGuardianBase *gsg);
void unprepare();
void unprepare(GraphicsStateGuardianBase *gsg);
void clear_gsg(GraphicsStateGuardianBase *gsg);
TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
INLINE bool has_ram_image() const;
PixelBuffer *get_ram_image();
INLINE void set_keep_ram_image(bool keep_ram_image);
INLINE bool get_keep_ram_image() const;
INLINE void apply(GraphicsStateGuardianBase *gsg);
virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
const RenderBuffer &rb);
// These bits are used as parameters to Texture::mark_dirty() and
// also TextureContext::mark_dirty() (and related functions in
// TextureContext).
@ -136,6 +133,8 @@ public:
static FilterType string_filter_type(const string &string);
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
WrapMode _wrapu;
WrapMode _wrapv;
FilterType _minfilter;
@ -144,11 +143,12 @@ private:
bool _keep_ram_image;
Colorf _border_color;
// A Texture keeps a list (actually, a map) of all the GSG's that it
// has been prepared into. Each GSG conversely keeps a list (a set)
// of all the Textures that have been prepared there. When either
// destructs, it removes itself from the other's list.
typedef pmap<GraphicsStateGuardianBase *, TextureContext *> Contexts;
// A Texture keeps a list (actually, a map) of all the
// PreparedGraphicsObjects tables that it has been prepared into.
// Each PGO conversely keeps a list (a set) of all the Textures that
// have been prepared there. When either destructs, it removes
// itself from the other's list.
typedef pmap<PreparedGraphicsObjects *, TextureContext *> Contexts;
Contexts _contexts;
// This value represents the intersection of all the dirty flags of
@ -201,6 +201,7 @@ private:
static TypeHandle _type_handle;
friend class TextureContext;
friend class PreparedGraphicsObjects;
};
#include "texture.I"

View File

@ -44,6 +44,7 @@ class GeomTristrip;
class GeomTrifan;
class GeomSphere;
class PreparedGraphicsObjects;
class TextureContext;
class Texture;
class PixelBuffer;
@ -111,6 +112,8 @@ public:
// These are some general interface functions; they're defined here
// mainly to make it easy to call these from code in some directory
// that display depends on.
virtual PreparedGraphicsObjects *get_prepared_objects()=0;
virtual TextureContext *prepare_texture(Texture *tex)=0;
virtual void apply_texture(TextureContext *tc)=0;
virtual void release_texture(TextureContext *tc)=0;

View File

@ -47,6 +47,7 @@
#include "globPattern.h"
#include "config_gobj.h"
#include "bamFile.h"
#include "preparedGraphicsObjects.h"
#include "dcast.h"
// stack seems to overflow on Intel C++ at 7000. If we need more than
@ -3246,19 +3247,18 @@ verify_complete() const {
// but this may take some of the overhead away from that
// process.
//
// If force_retained_mode is true, retained mode is set
// on the geometry encountered, regardless of the
// setting of the retained-mode Config variable.
// Otherwise, retained mode is set only if the
// retained-mode Config variable is true.
// 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 NodePath::
prepare_scene(GraphicsStateGuardianBase *gsg, bool force_retained_mode) {
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, gsg,
retained_mode || force_retained_mode);
r_prepare_scene(node(), net_state, prepared_objects);
}
////////////////////////////////////////////////////////////////////
@ -3895,14 +3895,14 @@ r_find_all_textures(PandaNode *node, const RenderState *state,
////////////////////////////////////////////////////////////////////
void NodePath::
r_prepare_scene(PandaNode *node, const RenderState *state,
GraphicsStateGuardianBase *gsg, bool do_retained_mode) {
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 (do_retained_mode) {
if (retained_mode) {
gnode->prepare(gsg);
}
*/
@ -3917,7 +3917,7 @@ r_prepare_scene(PandaNode *node, const RenderState *state,
DCAST_INTO_V(ta, attrib);
Texture *texture = ta->get_texture();
if (texture != (Texture *)NULL) {
texture->prepare(gsg);
texture->prepare(prepared_objects);
}
}
}
@ -3927,6 +3927,6 @@ r_prepare_scene(PandaNode *node, const RenderState *state,
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, gsg, do_retained_mode);
r_prepare_scene(child, child_state, prepared_objects);
}
}

View File

@ -39,6 +39,7 @@ class Texture;
class Material;
class Fog;
class GlobPattern;
class PreparedGraphicsObjects;
//
// A NodePath is the fundamental unit of high-level interaction with
@ -577,7 +578,7 @@ PUBLISHED:
// Miscellaneous
bool verify_complete() const;
void prepare_scene(GraphicsStateGuardianBase *gsg, bool force_retained_mode = false);
void prepare_scene(GraphicsStateGuardianBase *gsg);
void show_bounds();
void hide_bounds();
@ -635,7 +636,7 @@ private:
void r_find_all_textures(PandaNode *node, const RenderState *state,
Textures &textures) const;
void r_prepare_scene(PandaNode *node, const RenderState *state,
GraphicsStateGuardianBase *gsg, bool do_retained_mode);
PreparedGraphicsObjects *prepared_objects);
PT(NodePathComponent) _head;
int _backup_key;

View File

@ -227,7 +227,9 @@ make_image(Texture *texture, float radius) {
pb->set_uchar_rgb_texel(C, size - tx2 - 1, size - ty2 - 1, size);
}
}
texture->unprepare();
// Force the texture to be reloaded into texture memory.
texture->mark_dirty(Texture::DF_image);
return true;
}