better pstats tracking of texture/vbuffer memory

This commit is contained in:
David Rose 2006-03-16 21:26:56 +00:00
parent c83ac68e90
commit 83a6c42496
56 changed files with 1370 additions and 724 deletions

View File

@ -39,10 +39,6 @@
#include <algorithm>
#include <limits.h>
PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage");
PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
PStatCollector GraphicsStateGuardian::_texture_count_pcollector("Prepared Textures");
PStatCollector GraphicsStateGuardian::_active_texture_count_pcollector("Prepared Textures:Active");
PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
@ -51,15 +47,6 @@ PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Tra
PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer");
PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffer size");
PStatCollector GraphicsStateGuardian::_active_vertex_buffers_pcollector("Vertex buffer size:Active vertex");
PStatCollector GraphicsStateGuardian::_active_index_buffers_pcollector("Vertex buffer size:Active index");
PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes");
PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active");
PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory");
PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use");
PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches");
@ -964,11 +951,7 @@ 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);
_prepared_objects->begin_frame(this);
#ifdef DO_PSTATS
// For Pstats to track our current texture memory usage, we have to
@ -1005,6 +988,7 @@ begin_frame() {
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
begin_scene() {
_prepared_objects->end_frame();
return true;
}
@ -1879,7 +1863,6 @@ determine_light_color_scale() {
}
#ifdef DO_PSTATS
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::init_frame_pstats
// Access: Protected
@ -1889,16 +1872,7 @@ determine_light_color_scale() {
void GraphicsStateGuardian::
init_frame_pstats() {
if (PStatClient::is_connected()) {
_current_textures.clear();
_current_geoms.clear();
_current_vertex_buffers.clear();
_current_index_buffers.clear();
_active_texusage_pcollector.clear_level();
_data_transferred_pcollector.clear_level();
_active_geom_pcollector.clear_level();
_active_geom_node_pcollector.clear_level();
_active_vertex_buffers_pcollector.clear_level();
_active_index_buffers_pcollector.clear_level();
_vertex_buffer_switch_pcollector.clear_level();
_index_buffer_switch_pcollector.clear_level();
@ -1918,114 +1892,6 @@ init_frame_pstats() {
_texture_state_pcollector.clear_level();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_texture_record
// Access: Protected
// Description: Records that the indicated texture has been applied
// this frame, and thus must be present in current
// texture memory. This function is only used to update
// the PStats current_texmem collector; it gets compiled
// out if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_texture_record(TextureContext *tc) {
if (PStatClient::is_connected()) {
if (_current_textures.insert(tc).second) {
_active_texusage_pcollector.add_level(tc->estimate_texture_memory());
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_geom_record
// Access: Protected
// Description: Records that the indicated Geom has been drawn this
// frame. This function is only used to update the
// PStats active_geom collector; it gets compiled out
// if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_geom_record(GeomContext *gc) {
if (PStatClient::is_connected()) {
if (gc != (GeomContext *)NULL && _current_geoms.insert(gc).second) {
_active_geom_pcollector.add_level(1);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_vertex_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been drawn
// this frame. This function is only used to update the
// PStats active_vertex_buffers collector; it gets
// compiled out if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_vertex_buffer_record(VertexBufferContext *vbc) {
if (vbc != (VertexBufferContext *)NULL) {
if (PStatClient::is_connected()) {
_vertex_buffer_switch_pcollector.add_level(1);
if (_current_vertex_buffers.insert(vbc).second) {
_active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes());
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_index_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been drawn
// this frame. This function is only used to update the
// PStats active_index_buffers collector; it gets compiled out
// if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_index_buffer_record(IndexBufferContext *ibc) {
if (ibc != (IndexBufferContext *)NULL) {
if (PStatClient::is_connected()) {
_index_buffer_switch_pcollector.add_level(1);
if (_current_index_buffers.insert(ibc).second) {
_active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes());
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_total_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been loaded
// this frame. This function is only used to update the
// PStats total_buffers collector; it gets
// compiled out if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_total_buffer_record(VertexBufferContext *vbc) {
if (vbc != (VertexBufferContext *)NULL) {
int delta = vbc->get_data()->get_data_size_bytes() - vbc->get_data_size_bytes();
_total_buffers_pcollector.add_level(delta);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::add_to_total_buffer_record
// Access: Protected
// Description: Records that the indicated data array has been loaded
// this frame. This function is only used to update the
// PStats total_buffers collector; it gets
// compiled out if we aren't using PStats.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
add_to_total_buffer_record(IndexBufferContext *ibc) {
if (ibc != (IndexBufferContext *)NULL) {
int delta = ibc->get_data()->get_data_size_bytes() - ibc->get_data_size_bytes();
_total_buffers_pcollector.add_level(delta);
}
}
#endif // DO_PSTATS
////////////////////////////////////////////////////////////////////

View File

@ -247,29 +247,7 @@ protected:
INLINE void set_properties(const FrameBufferProperties &properties);
#ifdef DO_PSTATS
// These functions are used to update the active texture memory
// usage record (and other frame-based measurements) in Pstats.
void init_frame_pstats();
void add_to_texture_record(TextureContext *tc);
void add_to_geom_record(GeomContext *gc);
void add_to_vertex_buffer_record(VertexBufferContext *vbc);
void add_to_index_buffer_record(IndexBufferContext *ibc);
void add_to_total_buffer_record(VertexBufferContext *vbc);
void add_to_total_buffer_record(IndexBufferContext *ibc);
pset<TextureContext *> _current_textures;
pset<GeomContext *> _current_geoms;
pset<VertexBufferContext *> _current_vertex_buffers;
pset<IndexBufferContext *> _current_index_buffers;
#else
INLINE void init_frame_pstats() { }
INLINE void add_to_texture_record(TextureContext *) { }
INLINE void add_to_geom_record(GeomContext *) { }
INLINE void record_state_change(TypeHandle) { }
INLINE void add_to_vertex_buffer_record(VertexBufferContext *) { }
INLINE void add_to_index_buffer_record(IndexBufferContext *) { }
INLINE void add_to_total_buffer_record(VertexBufferContext *) { };
INLINE void add_to_total_buffer_record(IndexBufferContext *) { };
#endif
static CPT(RenderState) get_unlit_state();
@ -374,10 +352,6 @@ protected:
public:
// Statistics
static PStatCollector _total_texusage_pcollector;
static PStatCollector _active_texusage_pcollector;
static PStatCollector _texture_count_pcollector;
static PStatCollector _active_texture_count_pcollector;
static PStatCollector _vertex_buffer_switch_pcollector;
static PStatCollector _index_buffer_switch_pcollector;
static PStatCollector _load_vertex_buffer_pcollector;
@ -386,15 +360,6 @@ public:
static PStatCollector _create_index_buffer_pcollector;
static PStatCollector _load_texture_pcollector;
static PStatCollector _data_transferred_pcollector;
static PStatCollector _total_geom_pcollector;
static PStatCollector _active_geom_pcollector;
static PStatCollector _total_buffers_pcollector;
static PStatCollector _active_vertex_buffers_pcollector;
static PStatCollector _active_index_buffers_pcollector;
static PStatCollector _total_geom_node_pcollector;
static PStatCollector _active_geom_node_pcollector;
static PStatCollector _total_texmem_pcollector;
static PStatCollector _used_texmem_pcollector;
static PStatCollector _texmgrmem_total_pcollector;
static PStatCollector _texmgrmem_resident_pcollector;
static PStatCollector _primitive_batches_pcollector;

View File

@ -147,11 +147,11 @@ DXGraphicsStateGuardian8::
////////////////////////////////////////////////////////////////////
TextureContext *DXGraphicsStateGuardian8::
prepare_texture(Texture *tex) {
DXTextureContext8 *dtc = new DXTextureContext8(tex);
DXTextureContext8 *dtc = new DXTextureContext8(_prepared_objects, tex);
if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
dxgsg8_cat.error()
<< *dtc->_texture << " is stored in an unsupported compressed format.\n";
<< *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
return NULL;
}
@ -178,30 +178,17 @@ apply_texture(int i, TextureContext *tc) {
return;
}
#ifdef DO_PSTATS
add_to_texture_record(tc);
#endif
tc->set_active(true);
DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
int dirty = dtc->get_dirty_flags();
// If the texture image has changed, or if its use of mipmaps has
// changed, we need to re-create the image. Ignore other types of
// changes, which aren't significant for DX.
// changed, we need to re-create the image.
if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
// If this is *only* because of a mipmap change, issue a
// warning--it is likely that this change is the result of an
// error or oversight.
if ((dirty & Texture::DF_image) == 0) {
dxgsg8_cat.warning()
<< *dtc->_texture << " has changed mipmap state.\n";
}
if (!get_supports_compressed_texture_format(tc->_texture->get_ram_image_compression())) {
if (dtc->was_modified()) {
if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) {
dxgsg8_cat.error()
<< *dtc->_texture << " is stored in an unsupported compressed format.\n";
<< *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
_d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
return;
}
@ -209,13 +196,13 @@ apply_texture(int i, TextureContext *tc) {
if (!dtc->create_texture(*_screen)) {
// Oops, we can't re-create the texture for some reason.
dxgsg8_cat.error()
<< "Unable to re-create texture " << *dtc->_texture << endl;
<< "Unable to re-create texture " << *dtc->get_texture() << endl;
_d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
return;
}
}
Texture *tex = tc->_texture;
Texture *tex = tc->get_texture();
Texture::WrapMode wrap_u, wrap_v, wrap_w;
wrap_u = tex->get_wrap_u();
wrap_v = tex->get_wrap_v();
@ -303,7 +290,7 @@ release_texture(TextureContext *tc) {
////////////////////////////////////////////////////////////////////
VertexBufferContext *DXGraphicsStateGuardian8::
prepare_vertex_buffer(GeomVertexArrayData *data) {
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(_prepared_objects, data);
return dvbc;
}
@ -327,14 +314,13 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
if (dvbc->_vbuffer != NULL) {
dvbc->upload_data();
add_to_total_buffer_record(dvbc);
dvbc->mark_loaded();
_d3d_device->SetStreamSource
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
_active_vbuffer = dvbc;
_active_ibuffer = NULL;
add_to_vertex_buffer_record(dvbc);
dvbc->set_active(true);
} else {
_active_vbuffer = NULL;
@ -349,8 +335,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
}
dvbc->upload_data();
add_to_total_buffer_record(dvbc);
dvbc->mark_loaded();
_active_vbuffer = NULL;
}
@ -360,7 +344,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
(0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
_active_vbuffer = dvbc;
_active_ibuffer = NULL;
add_to_vertex_buffer_record(dvbc);
dvbc->set_active(true);
}
}
@ -403,7 +387,7 @@ release_vertex_buffer(VertexBufferContext *vbc) {
////////////////////////////////////////////////////////////////////
IndexBufferContext *DXGraphicsStateGuardian8::
prepare_index_buffer(GeomPrimitive *data) {
DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data);
DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(_prepared_objects, data);
return dibc;
}
@ -423,12 +407,11 @@ apply_index_buffer(IndexBufferContext *ibc) {
if (dibc->_ibuffer != NULL) {
dibc->upload_data();
add_to_total_buffer_record(dibc);
dibc->mark_loaded();
_d3d_device->SetIndices(dibc->_ibuffer, 0);
_active_ibuffer = dibc;
add_to_index_buffer_record(dibc);
dibc->set_active(true);
} else {
_d3d_device->SetIndices(NULL, 0);
@ -445,7 +428,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
dibc->upload_data();
add_to_total_buffer_record(dibc);
dibc->mark_loaded();
_active_ibuffer = NULL;
}
@ -453,7 +435,7 @@ apply_index_buffer(IndexBufferContext *ibc) {
if (_active_ibuffer != dibc) {
_d3d_device->SetIndices(dibc->_ibuffer, 0);
_active_ibuffer = dibc;
add_to_index_buffer_record(dibc);
dibc->set_active(true);
}
}
}
@ -1396,7 +1378,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
if (!dtc->create_texture(*_screen)) {
// Oops, we can't re-create the texture for some reason.
dxgsg8_cat.error()
<< "Unable to re-create texture " << *dtc->_texture << endl;
<< "Unable to re-create texture " << *dtc->get_texture() << endl;
return;
}
hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
@ -1415,7 +1397,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
// If it's still the wrong size, it's because driver can't create size
// that we want. In that case, there's no helping it, we have to give up.
dxgsg8_cat.error()
<< "Unable to copy to texture, texture is wrong size: " << *dtc->_texture << endl;
<< "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl;
SAFE_RELEASE(tex_level_0);
return;
}
@ -3435,7 +3417,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
release_all_vertex_buffers();
release_all_index_buffers();
_prepared_objects->update(this);
_prepared_objects->begin_frame(this);
hr = _d3d_device->Reset(&_presentation_reset);
if (FAILED(hr)) {
@ -3493,7 +3475,7 @@ check_cooperative_level() {
_dx_is_ready = false;
// call this just in case
_prepared_objects->update (this);
_prepared_objects->begin_frame(this);
hr = reset_d3d_device(&_screen->_presentation_params);
if (FAILED(hr)) {

View File

@ -31,8 +31,8 @@ TypeHandle DXIndexBufferContext8::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
DXIndexBufferContext8::
DXIndexBufferContext8(GeomPrimitive *data) :
IndexBufferContext(data),
DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
IndexBufferContext(pgo, data),
_ibuffer(NULL)
{
}

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXIndexBufferContext8 : public IndexBufferContext {
public:
DXIndexBufferContext8(GeomPrimitive *data);
DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
virtual ~DXIndexBufferContext8();
void create_ibuffer(DXScreenData &scrn);

View File

@ -35,8 +35,8 @@ static const DWORD g_LowByteMask = 0x000000FF;
// Description:
////////////////////////////////////////////////////////////////////
DXTextureContext8::
DXTextureContext8(Texture *tex) :
TextureContext(tex) {
DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex) :
TextureContext(pgo, tex) {
if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam()
@ -59,7 +59,7 @@ DXTextureContext8::
~DXTextureContext8() {
if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam()
<< "Deleting texture context for " << _texture->get_name() << "\n";
<< "Deleting texture context for " << get_texture()->get_name() << "\n";
}
delete_texture();
TextureContext::~TextureContext();
@ -82,32 +82,31 @@ create_texture(DXScreenData &scrn) {
D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
bool needs_luminance = false;
nassertr(IS_VALID_PTR(_texture), false);
nassertr(IS_VALID_PTR(get_texture()), false);
delete_texture();
clear_dirty_flags(Texture::DF_image | Texture::DF_mipmap);
mark_loaded();
// bpp indicates requested fmt, not texture fmt
DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &num_alpha_bits);
DWORD num_color_channels = _texture->get_num_components();
DWORD target_bpp = get_bits_per_pixel(get_texture()->get_format(), &num_alpha_bits);
DWORD num_color_channels = get_texture()->get_num_components();
//PRINT_REFCNT(dxgsg8, scrn._d3d8);
DWORD orig_width = (DWORD)_texture->get_x_size();
DWORD orig_height = (DWORD)_texture->get_y_size();
DWORD orig_depth = (DWORD)_texture->get_z_size();
DWORD orig_width = (DWORD)get_texture()->get_x_size();
DWORD orig_height = (DWORD)get_texture()->get_y_size();
DWORD orig_depth = (DWORD)get_texture()->get_z_size();
if ((_texture->get_format() == Texture::F_luminance_alpha)||
(_texture->get_format() == Texture::F_luminance_alphamask) ||
(_texture->get_format() == Texture::F_luminance)) {
if ((get_texture()->get_format() == Texture::F_luminance_alpha)||
(get_texture()->get_format() == Texture::F_luminance_alphamask) ||
(get_texture()->get_format() == Texture::F_luminance)) {
needs_luminance = true;
}
if (num_alpha_bits > 0) {
if (num_color_channels == 3) {
dxgsg8_cat.error()
<< "texture " << _texture->get_name()
<< "texture " << get_texture()->get_name()
<< " has no inherent alpha channel, but alpha format is requested!\n";
}
}
@ -145,7 +144,7 @@ create_texture(DXScreenData &scrn) {
DWORD filter_caps;
switch (_texture->get_texture_type()) {
switch (get_texture()->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
filter_caps = scrn._d3dcaps.TextureFilterCaps;
@ -239,15 +238,15 @@ create_texture(DXScreenData &scrn) {
if (orig_width != target_width || orig_height != target_height ||
orig_depth != target_depth) {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
if (get_texture()->get_texture_type() == Texture::TT_3d_texture) {
dxgsg8_cat.info()
<< "Reducing size of " << _texture->get_name()
<< "Reducing size of " << get_texture()->get_name()
<< " from " << orig_width << "x" << orig_height << "x" << orig_depth
<< " to " << target_width << "x" << target_height
<< "x" << target_depth << "\n";
} else {
dxgsg8_cat.info()
<< "Reducing size of " << _texture->get_name()
<< "Reducing size of " << get_texture()->get_name()
<< " from " << orig_width << "x" << orig_height
<< " to " << target_width << "x" << target_height << "\n";
}
@ -457,7 +456,7 @@ create_texture(DXScreenData &scrn) {
// if we've gotten here, haven't found a match
dxgsg8_cat.error()
<< error_message << ": " << _texture->get_name() << endl
<< error_message << ": " << get_texture()->get_name() << endl
<< "NumColorChannels: " << num_color_channels << "; NumAlphaBits: "
<< num_alpha_bits << "; targetbpp: " <<target_bpp
<< "; _supported_tex_formats_mask: 0x"
@ -470,7 +469,7 @@ create_texture(DXScreenData &scrn) {
found_matching_format:
// We found a suitable format that matches the texture's format.
if (_texture->get_match_framebuffer_format()) {
if (get_texture()->get_match_framebuffer_format()) {
// Instead of creating a texture with the found format, we will
// need to make one that exactly matches the framebuffer's
// format. Look up what that format is.
@ -505,7 +504,7 @@ create_texture(DXScreenData &scrn) {
Texture::FilterType ft;
ft = _texture->get_magfilter();
ft = get_texture()->get_magfilter();
if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) {
// mipmap settings make no sense for magfilter
if (ft == Texture::FT_nearest_mipmap_nearest) {
@ -519,10 +518,10 @@ create_texture(DXScreenData &scrn) {
(filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) {
ft = Texture::FT_nearest;
}
_texture->set_magfilter(ft);
get_texture()->set_magfilter(ft);
// figure out if we are mipmapping this texture
ft = _texture->get_minfilter();
ft = get_texture()->get_minfilter();
_has_mipmaps = false;
if (!dx_ignore_mipmaps) { // set if no HW mipmap capable
@ -540,11 +539,11 @@ create_texture(DXScreenData &scrn) {
if (ft != Texture::FT_linear_mipmap_linear) {
dxgsg8_cat.spam()
<< "Forcing trilinear mipmapping on DX texture ["
<< _texture->get_name() << "]\n";
<< get_texture()->get_name() << "]\n";
}
}
ft = Texture::FT_linear_mipmap_linear;
_texture->set_minfilter(ft);
get_texture()->set_minfilter(ft);
}
} else if ((ft == Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types
@ -596,23 +595,23 @@ create_texture(DXScreenData &scrn) {
break;
}
_texture->set_minfilter(ft);
get_texture()->set_minfilter(ft);
uint aniso_degree;
aniso_degree = 1;
if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
aniso_degree = _texture->get_anisotropic_degree();
aniso_degree = get_texture()->get_anisotropic_degree();
if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) ||
dx_force_anisotropic_filtering) {
aniso_degree = scrn._d3dcaps.MaxAnisotropy;
}
}
_texture->set_anisotropic_degree(aniso_degree);
get_texture()->set_anisotropic_degree(aniso_degree);
#ifdef _DEBUG
dxgsg8_cat.spam()
<< "create_texture: setting aniso degree for " << _texture->get_name()
<< "create_texture: setting aniso degree for " << get_texture()->get_name()
<< " to: " << aniso_degree << endl;
#endif
@ -624,7 +623,7 @@ create_texture(DXScreenData &scrn) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "create_texture: generating mipmaps for " << _texture->get_name()
<< "create_texture: generating mipmaps for " << get_texture()->get_name()
<< endl;
}
} else {
@ -634,7 +633,7 @@ create_texture(DXScreenData &scrn) {
DWORD usage;
D3DPOOL pool;
if (_texture->get_render_to_texture ()) {
if (get_texture()->get_render_to_texture ()) {
// REQUIRED
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_RENDERTARGET;
@ -646,7 +645,7 @@ create_texture(DXScreenData &scrn) {
usage = 0;
}
switch (_texture->get_texture_type()) {
switch (get_texture()->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
hr = scrn._d3d_device->CreateTexture
@ -678,7 +677,7 @@ create_texture(DXScreenData &scrn) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "create_texture: " << _texture->get_name()
<< "create_texture: " << get_texture()->get_name()
<< " converting panda equivalent of " << D3DFormatStr(_d3d_format)
<< " => " << D3DFormatStr(target_pixel_format) << endl;
}
@ -984,14 +983,14 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface,
////////////////////////////////////////////////////////////////////
HRESULT DXTextureContext8::
fill_d3d_texture_pixels() {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
if (get_texture()->get_texture_type() == Texture::TT_3d_texture) {
return fill_d3d_volume_texture_pixels();
}
HRESULT hr = E_FAIL;
nassertr(IS_VALID_PTR(_texture), E_FAIL);
nassertr(IS_VALID_PTR(get_texture()), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
CPTA_uchar image = get_texture()->get_ram_image();
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
@ -1003,13 +1002,13 @@ fill_d3d_texture_pixels() {
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
DWORD orig_width = (DWORD) get_texture()->get_x_size();
DWORD orig_height = (DWORD) get_texture()->get_y_size();
DWORD orig_depth = (DWORD) get_texture()->get_z_size();
DWORD num_color_channels = get_texture()->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
int component_width = get_texture()->get_component_width();
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
@ -1018,10 +1017,10 @@ fill_d3d_texture_pixels() {
BYTE *pixels = NULL;
for (unsigned int di = 0; di < orig_depth; di++) {
pixels = image_pixels + di * _texture->get_expected_ram_page_size();
pixels = image_pixels + di * get_texture()->get_expected_ram_page_size();
mip_level_0 = NULL;
if (_texture->get_texture_type() == Texture::TT_cube_map) {
if (get_texture()->get_texture_type() == Texture::TT_cube_map) {
nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)di, 0, &mip_level_0);
} else {
@ -1031,7 +1030,7 @@ fill_d3d_texture_pixels() {
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
@ -1085,7 +1084,7 @@ fill_d3d_texture_pixels() {
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_components = get_texture()->get_num_components();
int num_pixels = orig_width * orig_height * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
@ -1113,7 +1112,7 @@ fill_d3d_texture_pixels() {
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1131,7 +1130,7 @@ fill_d3d_texture_pixels() {
mip_filter_flags);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1159,9 +1158,9 @@ fill_d3d_texture_pixels() {
HRESULT DXTextureContext8::
fill_d3d_volume_texture_pixels() {
HRESULT hr = E_FAIL;
nassertr(IS_VALID_PTR(_texture), E_FAIL);
nassertr(IS_VALID_PTR(get_texture()), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
CPTA_uchar image = get_texture()->get_ram_image();
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
@ -1172,15 +1171,15 @@ fill_d3d_volume_texture_pixels() {
PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
nassertr(_texture->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
nassertr(get_texture()->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
DWORD orig_width = (DWORD) get_texture()->get_x_size();
DWORD orig_height = (DWORD) get_texture()->get_y_size();
DWORD orig_depth = (DWORD) get_texture()->get_z_size();
DWORD num_color_channels = get_texture()->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
int component_width = get_texture()->get_component_width();
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
@ -1193,7 +1192,7 @@ fill_d3d_volume_texture_pixels() {
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
@ -1252,7 +1251,7 @@ fill_d3d_volume_texture_pixels() {
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_components = get_texture()->get_num_components();
int num_pixels = orig_width * orig_height * orig_depth * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
@ -1281,7 +1280,7 @@ fill_d3d_volume_texture_pixels() {
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1299,7 +1298,7 @@ fill_d3d_volume_texture_pixels() {
mip_filter_flags);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}

View File

@ -29,7 +29,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXTextureContext8 : public TextureContext {
public:
DXTextureContext8(Texture *tex);
DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex);
virtual ~DXTextureContext8();
bool create_texture(DXScreenData &scrn);

View File

@ -33,8 +33,8 @@ TypeHandle DXVertexBufferContext8::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
DXVertexBufferContext8::
DXVertexBufferContext8(GeomVertexArrayData *data) :
VertexBufferContext(data),
DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
VertexBufferContext(pgo, data),
_vbuffer(NULL)
{
// Now fill in the FVF code.

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXVertexBufferContext8 : public VertexBufferContext {
public:
DXVertexBufferContext8(GeomVertexArrayData *data);
DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data);
virtual ~DXVertexBufferContext8();
void create_vbuffer(DXScreenData &scrn);

View File

@ -190,11 +190,11 @@ DXGraphicsStateGuardian9::
////////////////////////////////////////////////////////////////////
TextureContext *DXGraphicsStateGuardian9::
prepare_texture(Texture *tex) {
DXTextureContext9 *dtc = new DXTextureContext9(tex);
DXTextureContext9 *dtc = new DXTextureContext9(_prepared_objects, tex);
if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
dxgsg9_cat.error()
<< *dtc->_texture << " is stored in an unsupported compressed format.\n";
<< *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
return NULL;
}
@ -221,9 +221,7 @@ apply_texture(int i, TextureContext *tc) {
return;
}
#ifdef DO_PSTATS
add_to_texture_record(tc);
#endif
tc->set_active(true);
DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
@ -232,24 +230,13 @@ apply_texture(int i, TextureContext *tc) {
_lru -> access_page (dtc -> _lru_page);
}
int dirty = dtc->get_dirty_flags();
// If the texture image has changed, or if its use of mipmaps has
// changed, we need to re-create the image. Ignore other types of
// changes, which aren't significant for DX.
// changed, we need to re-create the image.
if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
// If this is *only* because of a mipmap change, issue a
// warning--it is likely that this change is the result of an
// error or oversight.
if ((dirty & Texture::DF_image) == 0) {
dxgsg9_cat.warning()
<< *dtc->_texture << " has changed mipmap state.\n";
}
if (!get_supports_compressed_texture_format(tc->_texture->get_ram_image_compression())) {
if (dtc->was_modified()) {
if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) {
dxgsg9_cat.error()
<< *dtc->_texture << " is stored in an unsupported compressed format.\n";
<< *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
_d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
return;
}
@ -257,13 +244,13 @@ apply_texture(int i, TextureContext *tc) {
if (!dtc->create_texture(*_screen)) {
// Oops, we can't re-create the texture for some reason.
dxgsg9_cat.error()
<< "Unable to re-create texture " << *dtc->_texture << endl;
<< "Unable to re-create texture " << *dtc->get_texture() << endl;
set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
return;
}
}
Texture *tex = tc->_texture;
Texture *tex = tc->get_texture();
Texture::WrapMode wrap_u, wrap_v, wrap_w;
DWORD address_u;
@ -388,7 +375,7 @@ release_shader(ShaderContext *sc) {
////////////////////////////////////////////////////////////////////
VertexBufferContext *DXGraphicsStateGuardian9::
prepare_vertex_buffer(GeomVertexArrayData *data) {
DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(data, *(this -> _screen));
DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(_prepared_objects, data, *(this -> _screen));
return dvbc;
}
@ -427,7 +414,6 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context
if (dvbc->_vbuffer != NULL) {
dvbc->upload_data();
add_to_total_buffer_record(dvbc);
dvbc->mark_loaded();
set_stream_source = true;
@ -446,7 +432,6 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context
dvbc->upload_data();
add_to_total_buffer_record(dvbc);
dvbc->mark_loaded();
_active_vbuffer = NULL;
}
@ -467,7 +452,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context
}
_active_vbuffer = dvbc;
_active_ibuffer = NULL;
add_to_vertex_buffer_record(dvbc);
dvbc->set_active(true);
}
if ((dvbc->_fvf != _last_fvf)) {
@ -558,7 +543,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context
}
_active_vbuffer = dvbc;
_active_ibuffer = NULL;
add_to_vertex_buffer_record(dvbc);
dvbc->set_active(true);
}
if (dvbc -> _direct_3d_vertex_declaration) {
@ -603,7 +588,7 @@ release_vertex_buffer(VertexBufferContext *vbc) {
////////////////////////////////////////////////////////////////////
IndexBufferContext *DXGraphicsStateGuardian9::
prepare_index_buffer(GeomPrimitive *data) {
DXIndexBufferContext9 *dibc = new DXIndexBufferContext9(data);
DXIndexBufferContext9 *dibc = new DXIndexBufferContext9(_prepared_objects, data);
return dibc;
}
@ -627,12 +612,11 @@ apply_index_buffer(IndexBufferContext *ibc) {
if (dibc->_ibuffer != NULL) {
dibc->upload_data();
add_to_total_buffer_record(dibc);
dibc->mark_loaded();
_d3d_device->SetIndices(dibc->_ibuffer);
_active_ibuffer = dibc;
add_to_index_buffer_record(dibc);
dibc->set_active(true);
} else {
_d3d_device->SetIndices(NULL);
@ -649,7 +633,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
dibc->upload_data();
add_to_total_buffer_record(dibc);
dibc->mark_loaded();
_active_ibuffer = NULL;
}
@ -657,7 +640,7 @@ apply_index_buffer(IndexBufferContext *ibc) {
if (_active_ibuffer != dibc) {
_d3d_device->SetIndices(dibc->_ibuffer);
_active_ibuffer = dibc;
add_to_index_buffer_record(dibc);
dibc->set_active(true);
}
}
}
@ -1902,7 +1885,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
if (!dtc->create_texture(*_screen)) {
// Oops, we can't re-create the texture for some reason.
dxgsg9_cat.error()
<< "Unable to re-create texture " << *dtc->_texture << endl;
<< "Unable to re-create texture " << *dtc->get_texture() << endl;
return;
}
hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
@ -1921,7 +1904,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
// If it's still the wrong size, it's because driver can't create size
// that we want. In that case, there's no helping it, we have to give up.
dxgsg9_cat.error()
<< "Unable to copy to texture, texture is wrong size: " << *dtc->_texture << endl;
<< "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl;
SAFE_RELEASE(tex_level_0);
return;
}
@ -4460,7 +4443,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
release_all_index_buffers();
// must be called before reset
_prepared_objects->update(this);
_prepared_objects->begin_frame(this);
hr = _d3d_device->Reset(&_presentation_reset);
if (FAILED(hr)) {
@ -4518,7 +4501,7 @@ check_cooperative_level() {
_dx_is_ready = false;
// call this just in case
_prepared_objects->update (this);
_prepared_objects->begin_frame(this);
hr = reset_d3d_device(&_screen->_presentation_params);
if (FAILED(hr)) {

View File

@ -32,8 +32,8 @@ TypeHandle DXIndexBufferContext9::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
DXIndexBufferContext9::
DXIndexBufferContext9(GeomPrimitive *data) :
IndexBufferContext(data),
DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
IndexBufferContext(pgo, data),
_ibuffer(NULL)
{
_managed = -1;

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXIndexBufferContext9 : public IndexBufferContext {
public:
DXIndexBufferContext9(GeomPrimitive *data);
DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
virtual ~DXIndexBufferContext9();
void free_ibuffer(void);

View File

@ -37,8 +37,8 @@ static const DWORD g_LowByteMask = 0x000000FF;
// Description:
////////////////////////////////////////////////////////////////////
DXTextureContext9::
DXTextureContext9(Texture *tex) :
TextureContext(tex) {
DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex) :
TextureContext(pgo, tex) {
if (dxgsg9_cat.is_spam()) {
dxgsg9_cat.spam()
@ -63,7 +63,7 @@ DXTextureContext9::
~DXTextureContext9() {
if (dxgsg9_cat.is_spam()) {
dxgsg9_cat.spam()
<< "Deleting texture context for " << _texture->get_name() << "\n";
<< "Deleting texture context for " << get_texture()->get_name() << "\n";
}
if (_lru_page)
@ -94,32 +94,31 @@ create_texture(DXScreenData &scrn) {
D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
bool needs_luminance = false;
nassertr(IS_VALID_PTR(_texture), false);
nassertr(IS_VALID_PTR(get_texture()), false);
delete_texture();
clear_dirty_flags(Texture::DF_image | Texture::DF_mipmap);
mark_loaded();
// bpp indicates requested fmt, not texture fmt
DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &num_alpha_bits);
DWORD num_color_channels = _texture->get_num_components();
DWORD target_bpp = get_bits_per_pixel(get_texture()->get_format(), &num_alpha_bits);
DWORD num_color_channels = get_texture()->get_num_components();
//PRINT_REFCNT(dxgsg9, scrn._d3d9);
DWORD orig_width = (DWORD)_texture->get_x_size();
DWORD orig_height = (DWORD)_texture->get_y_size();
DWORD orig_depth = (DWORD)_texture->get_z_size();
DWORD orig_width = (DWORD)get_texture()->get_x_size();
DWORD orig_height = (DWORD)get_texture()->get_y_size();
DWORD orig_depth = (DWORD)get_texture()->get_z_size();
if ((_texture->get_format() == Texture::F_luminance_alpha)||
(_texture->get_format() == Texture::F_luminance_alphamask) ||
(_texture->get_format() == Texture::F_luminance)) {
if ((get_texture()->get_format() == Texture::F_luminance_alpha)||
(get_texture()->get_format() == Texture::F_luminance_alphamask) ||
(get_texture()->get_format() == Texture::F_luminance)) {
needs_luminance = true;
}
if (num_alpha_bits > 0) {
if (num_color_channels == 3) {
dxgsg9_cat.error()
<< "texture " << _texture->get_name()
<< "texture " << get_texture()->get_name()
<< " has no inherent alpha channel, but alpha format is requested!\n";
}
}
@ -157,7 +156,7 @@ create_texture(DXScreenData &scrn) {
DWORD filter_caps;
switch (_texture->get_texture_type()) {
switch (get_texture()->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
filter_caps = scrn._d3dcaps.TextureFilterCaps;
@ -251,15 +250,15 @@ create_texture(DXScreenData &scrn) {
if (orig_width != target_width || orig_height != target_height ||
orig_depth != target_depth) {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
if (get_texture()->get_texture_type() == Texture::TT_3d_texture) {
dxgsg9_cat.info()
<< "Reducing size of " << _texture->get_name()
<< "Reducing size of " << get_texture()->get_name()
<< " from " << orig_width << "x" << orig_height << "x" << orig_depth
<< " to " << target_width << "x" << target_height
<< "x" << target_depth << "\n";
} else {
dxgsg9_cat.info()
<< "Reducing size of " << _texture->get_name()
<< "Reducing size of " << get_texture()->get_name()
<< " from " << orig_width << "x" << orig_height
<< " to " << target_width << "x" << target_height << "\n";
}
@ -469,7 +468,7 @@ create_texture(DXScreenData &scrn) {
// if we've gotten here, haven't found a match
dxgsg9_cat.error()
<< error_message << ": " << _texture->get_name() << endl
<< error_message << ": " << get_texture()->get_name() << endl
<< "NumColorChannels: " << num_color_channels << "; NumAlphaBits: "
<< num_alpha_bits << "; targetbpp: " <<target_bpp
<< "; _supported_tex_formats_mask: 0x"
@ -482,7 +481,7 @@ create_texture(DXScreenData &scrn) {
found_matching_format:
// We found a suitable format that matches the texture's format.
if (_texture->get_match_framebuffer_format()) {
if (get_texture()->get_match_framebuffer_format()) {
// Instead of creating a texture with the found format, we will
// need to make one that exactly matches the framebuffer's
// format. Look up what that format is.
@ -520,7 +519,7 @@ create_texture(DXScreenData &scrn) {
Texture::FilterType ft;
ft = _texture->get_magfilter();
ft = get_texture()->get_magfilter();
if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) {
// mipmap settings make no sense for magfilter
if (ft == Texture::FT_nearest_mipmap_nearest) {
@ -534,10 +533,10 @@ create_texture(DXScreenData &scrn) {
(filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) {
ft = Texture::FT_nearest;
}
_texture->set_magfilter(ft);
get_texture()->set_magfilter(ft);
// figure out if we are mipmapping this texture
ft = _texture->get_minfilter();
ft = get_texture()->get_minfilter();
_has_mipmaps = false;
if (!dx_ignore_mipmaps) { // set if no HW mipmap capable
@ -555,11 +554,11 @@ create_texture(DXScreenData &scrn) {
if (ft != Texture::FT_linear_mipmap_linear) {
dxgsg9_cat.spam()
<< "Forcing trilinear mipmapping on DX texture ["
<< _texture->get_name() << "]\n";
<< get_texture()->get_name() << "]\n";
}
}
ft = Texture::FT_linear_mipmap_linear;
_texture->set_minfilter(ft);
get_texture()->set_minfilter(ft);
}
} else if ((ft == Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types
@ -611,23 +610,23 @@ create_texture(DXScreenData &scrn) {
break;
}
_texture->set_minfilter(ft);
get_texture()->set_minfilter(ft);
uint aniso_degree;
aniso_degree = 1;
if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
aniso_degree = _texture->get_anisotropic_degree();
aniso_degree = get_texture()->get_anisotropic_degree();
if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) ||
dx_force_anisotropic_filtering) {
aniso_degree = scrn._d3dcaps.MaxAnisotropy;
}
}
_texture->set_anisotropic_degree(aniso_degree);
get_texture()->set_anisotropic_degree(aniso_degree);
#ifdef _DEBUG
dxgsg9_cat.spam()
<< "create_texture: setting aniso degree for " << _texture->get_name()
<< "create_texture: setting aniso degree for " << get_texture()->get_name()
<< " to: " << aniso_degree << endl;
#endif
@ -639,7 +638,7 @@ create_texture(DXScreenData &scrn) {
if (dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug()
<< "create_texture: generating mipmaps for " << _texture->get_name()
<< "create_texture: generating mipmaps for " << get_texture()->get_name()
<< endl;
}
} else {
@ -649,7 +648,7 @@ create_texture(DXScreenData &scrn) {
DWORD usage;
D3DPOOL pool;
if (_texture->get_render_to_texture ( )) {
if (get_texture()->get_render_to_texture ( )) {
// REQUIRED PARAMETERS
_managed = false;
pool = D3DPOOL_DEFAULT;
@ -752,7 +751,7 @@ create_texture(DXScreenData &scrn) {
{
data_size = (int) ((float) data_size * 1.3f);
}
if (_texture->get_texture_type() == Texture::TT_cube_map)
if (get_texture()->get_texture_type() == Texture::TT_cube_map)
{
data_size *= 6;
}
@ -762,7 +761,7 @@ create_texture(DXScreenData &scrn) {
attempts = 0;
do
{
switch (_texture->get_texture_type()) {
switch (get_texture()->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
hr = scrn._d3d_device->CreateTexture
@ -800,7 +799,7 @@ create_texture(DXScreenData &scrn) {
if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug()
<< "create_texture: " << _texture->get_name()
<< "create_texture: " << get_texture()->get_name()
<< " converting panda equivalent of " << D3DFormatStr(_d3d_format)
<< " => " << D3DFormatStr(target_pixel_format) << endl;
}
@ -814,7 +813,7 @@ create_texture(DXScreenData &scrn) {
// must not put render to texture into LRU
if (_lru_page == 0 && _managed == false && _texture->get_render_to_texture ( ) == false)
if (_lru_page == 0 && _managed == false && get_texture()->get_render_to_texture ( ) == false)
{
Lru *lru;
@ -1130,14 +1129,14 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface,
////////////////////////////////////////////////////////////////////
HRESULT DXTextureContext9::
fill_d3d_texture_pixels() {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
if (get_texture()->get_texture_type() == Texture::TT_3d_texture) {
return fill_d3d_volume_texture_pixels();
}
HRESULT hr = E_FAIL;
nassertr(IS_VALID_PTR(_texture), E_FAIL);
nassertr(IS_VALID_PTR(get_texture()), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
CPTA_uchar image = get_texture()->get_ram_image();
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
@ -1149,13 +1148,13 @@ fill_d3d_texture_pixels() {
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
DWORD orig_width = (DWORD) get_texture()->get_x_size();
DWORD orig_height = (DWORD) get_texture()->get_y_size();
DWORD orig_depth = (DWORD) get_texture()->get_z_size();
DWORD num_color_channels = get_texture()->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
int component_width = get_texture()->get_component_width();
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
@ -1164,10 +1163,10 @@ fill_d3d_texture_pixels() {
BYTE *pixels = NULL;
for (unsigned int di = 0; di < orig_depth; di++) {
pixels = image_pixels + di * _texture->get_expected_ram_page_size();
pixels = image_pixels + di * get_texture()->get_expected_ram_page_size();
mip_level_0 = NULL;
if (_texture->get_texture_type() == Texture::TT_cube_map) {
if (get_texture()->get_texture_type() == Texture::TT_cube_map) {
nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)di, 0, &mip_level_0);
} else {
@ -1177,7 +1176,7 @@ fill_d3d_texture_pixels() {
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
@ -1231,7 +1230,7 @@ fill_d3d_texture_pixels() {
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_components = get_texture()->get_num_components();
int num_pixels = orig_width * orig_height * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
@ -1259,7 +1258,7 @@ fill_d3d_texture_pixels() {
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1277,7 +1276,7 @@ fill_d3d_texture_pixels() {
mip_filter_flags);
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1308,9 +1307,9 @@ fill_d3d_texture_pixels() {
HRESULT DXTextureContext9::
fill_d3d_volume_texture_pixels() {
HRESULT hr = E_FAIL;
nassertr(IS_VALID_PTR(_texture), E_FAIL);
nassertr(IS_VALID_PTR(get_texture()), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
CPTA_uchar image = get_texture()->get_ram_image();
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
@ -1321,15 +1320,15 @@ fill_d3d_volume_texture_pixels() {
PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
nassertr(_texture->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
nassertr(get_texture()->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
DWORD orig_width = (DWORD) get_texture()->get_x_size();
DWORD orig_height = (DWORD) get_texture()->get_y_size();
DWORD orig_depth = (DWORD) get_texture()->get_z_size();
DWORD num_color_channels = get_texture()->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
int component_width = get_texture()->get_component_width();
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
@ -1342,7 +1341,7 @@ fill_d3d_volume_texture_pixels() {
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
@ -1401,7 +1400,7 @@ fill_d3d_volume_texture_pixels() {
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_components = get_texture()->get_num_components();
int num_pixels = orig_width * orig_height * orig_depth * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
@ -1430,7 +1429,7 @@ fill_d3d_volume_texture_pixels() {
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
@ -1448,7 +1447,7 @@ fill_d3d_volume_texture_pixels() {
mip_filter_flags);
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}

View File

@ -31,7 +31,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXTextureContext9 : public TextureContext {
public:
DXTextureContext9(Texture *tex);
DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex);
virtual ~DXTextureContext9();
bool create_texture(DXScreenData &scrn);

View File

@ -34,8 +34,8 @@ TypeHandle DXVertexBufferContext9::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
DXVertexBufferContext9::
DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn) :
VertexBufferContext(data),
DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn) :
VertexBufferContext(pgo, data),
_vbuffer(NULL)
{
// Now fill in the FVF code.

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX DXVertexBufferContext9 : public VertexBufferContext {
public:
DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn);
DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn);
virtual ~DXVertexBufferContext9();
void free_vbuffer(void);

View File

@ -20,7 +20,7 @@
#ifdef THREADED_PIPELINE
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerLinks::Constructor
// Access: Public
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerLinks::
@ -35,7 +35,7 @@ PipelineCyclerLinks() {
#ifdef THREADED_PIPELINE
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerLinks::Destructor
// Access: Public
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerLinks::
@ -47,7 +47,7 @@ INLINE PipelineCyclerLinks::
#ifdef THREADED_PIPELINE
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerLinks::remove_from_list
// Access: Private
// Access: Protected
// Description: Removes a PipelineCyclerLinks record from the
// doubly-linked list.
////////////////////////////////////////////////////////////////////
@ -66,7 +66,7 @@ remove_from_list() {
#ifdef THREADED_PIPELINE
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerLinks::insert_before
// Access: Private
// Access: Protected
// Description: Adds a PipelineCyclerLinks record before the indicated
// node in the doubly-linked list.
////////////////////////////////////////////////////////////////////

View File

@ -1236,8 +1236,20 @@ end_frame() {
GLP(Flush)();
}
#ifdef DO_PSTATS
// Check for textures, etc., that are no longer resident.
check_nonresident_texture(_prepared_objects->_texture_residency.get_inactive_resident());
check_nonresident_texture(_prepared_objects->_texture_residency.get_active_resident());
// OpenGL provides no methods for querying whether a buffer object
// (vertex buffer) is resident. In fact, the API appears geared
// towards the assumption that such buffers are always resident.
// OK.
#endif
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::begin_draw_primitives
@ -2117,7 +2129,7 @@ prepare_texture(Texture *tex) {
break;
}
CLP(TextureContext) *gtc = new CLP(TextureContext)(tex);
CLP(TextureContext) *gtc = new CLP(TextureContext)(_prepared_objects, tex);
GLP(GenTextures)(1, &gtc->_index);
report_my_gl_errors();
@ -2529,7 +2541,7 @@ record_deleted_display_list(GLuint index) {
VertexBufferContext *CLP(GraphicsStateGuardian)::
prepare_vertex_buffer(GeomVertexArrayData *data) {
if (_supports_buffers) {
CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(data);
CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(_prepared_objects, data);
_glGenBuffers(1, &gvbc->_index);
if (GLCAT.is_debug()) {
@ -2566,7 +2578,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
}
_glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
_current_vbuffer_index = gvbc->_index;
add_to_vertex_buffer_record(gvbc);
gvbc->set_active(true);
}
if (gvbc->was_modified()) {
@ -2589,7 +2601,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
}
_data_transferred_pcollector.add_level(num_bytes);
}
add_to_total_buffer_record(gvbc);
gvbc->mark_loaded();
}
@ -2696,7 +2708,7 @@ setup_array_data(const GeomVertexArrayData *data) {
IndexBufferContext *CLP(GraphicsStateGuardian)::
prepare_index_buffer(GeomPrimitive *data) {
if (_supports_buffers) {
CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(data);
CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(_prepared_objects, data);
_glGenBuffers(1, &gibc->_index);
if (GLCAT.is_debug()) {
@ -2734,7 +2746,7 @@ apply_index_buffer(IndexBufferContext *ibc) {
}
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index);
_current_ibuffer_index = gibc->_index;
add_to_index_buffer_record(gibc);
gibc->set_active(true);
}
if (gibc->was_modified()) {
@ -2757,7 +2769,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
}
_data_transferred_pcollector.add_level(num_bytes);
}
add_to_total_buffer_record(gibc);
gibc->mark_loaded();
}
@ -6239,25 +6250,19 @@ void CLP(GraphicsStateGuardian)::
apply_texture(TextureContext *tc) {
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
add_to_texture_record(gtc);
GLenum target = get_texture_target(gtc->_texture->get_texture_type());
gtc->set_active(true);
GLenum target = get_texture_target(gtc->get_texture()->get_texture_type());
if (target == GL_NONE) {
return;
}
GLP(BindTexture)(target, gtc->_index);
int dirty = gtc->get_dirty_flags();
if ((dirty & (Texture::DF_wrap | Texture::DF_filter | Texture::DF_border)) != 0) {
// We need to re-specify the texture properties.
specify_texture(gtc->_texture);
}
if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
// We need to re-upload the image.
if (gtc->was_modified()) {
specify_texture(gtc->get_texture());
upload_texture(gtc);
gtc->mark_loaded();
}
gtc->clear_dirty_flags();
report_my_gl_errors();
}
@ -6272,7 +6277,7 @@ apply_texture(TextureContext *tc) {
////////////////////////////////////////////////////////////////////
bool CLP(GraphicsStateGuardian)::
upload_texture(CLP(TextureContext) *gtc) {
Texture *tex = gtc->_texture;
Texture *tex = gtc->get_texture();
CPTA_uchar image = tex->get_ram_image();
if (image.is_null()) {
return false;
@ -6451,7 +6456,7 @@ upload_texture(CLP(TextureContext) *gtc) {
gtc->_depth = depth;
#ifdef DO_PSTATS
gtc->_texture_memory_size = get_texture_memory_size(tex);
gtc->update_data_size_bytes(get_texture_memory_size(tex));
#endif
#ifndef NDEBUG
@ -6502,7 +6507,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
#endif
#ifndef NDEBUG
if (CLP(show_mipmaps) && target == GL_TEXTURE_2D) {
build_phony_mipmaps(gtc->_texture);
build_phony_mipmaps(gtc->get_texture());
report_my_gl_errors();
return true;
@ -6552,10 +6557,10 @@ upload_texture_image(CLP(TextureContext) *gtc,
if (GLCAT.is_debug()) {
if (image_compression != Texture::CM_off) {
GLCAT.debug()
<< "loading pre-compressed texture " << gtc->_texture->get_name() << "\n";
<< "loading pre-compressed texture " << gtc->get_texture()->get_name() << "\n";
} else if (is_compressed_format(internal_format)) {
GLCAT.debug()
<< "compressing texture " << gtc->_texture->get_name() << "\n";
<< "compressing texture " << gtc->get_texture()->get_name() << "\n";
}
}
@ -6640,7 +6645,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
if (error_code != GL_NO_ERROR) {
const GLubyte *error_string = GLUP(ErrorString)(error_code);
GLCAT.error()
<< "GL texture creation failed for " << gtc->_texture->get_name();
<< "GL texture creation failed for " << gtc->get_texture()->get_name();
if (error_string != (const GLubyte *)NULL) {
GLCAT.error(false)
<< " : " << error_string;
@ -6737,6 +6742,42 @@ get_texture_memory_size(Texture *tex) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::check_nonresident_texture
// Access: Private
// Description: Checks the list of resident texture objects to see if
// any have recently been evicted.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
check_nonresident_texture(BufferContextChain &chain) {
size_t num_textures = chain.get_count();
CLP(TextureContext) **gtc_list = (CLP(TextureContext) **)alloca(num_textures * sizeof(CLP(TextureContext) *));
GLuint *texture_list = (GLuint *)alloca(num_textures * sizeof(GLuint));
size_t ti = 0;
BufferContext *node = chain.get_first();
while (node != (BufferContext *)NULL) {
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), node);
gtc_list[ti] = gtc;
texture_list[ti] = gtc->_index;
node = node->get_next();
++ti;
}
nassertv(ti == num_textures);
GLboolean *results = (GLboolean *)alloca(num_textures * sizeof(GLboolean));
bool all_resident = (glAreTexturesResident(num_textures, texture_list, results) != 0);
report_my_gl_errors();
if (!all_resident) {
// Some are now nonresident.
for (ti = 0; ti < num_textures; ++ti) {
if (!results[ti]) {
gtc_list[ti]->set_resident(false);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::do_point_size
// Access: Protected

View File

@ -278,6 +278,7 @@ protected:
Texture::CompressionMode image_compression);
size_t get_texture_memory_size(Texture *tex) const;
void check_nonresident_texture(BufferContextChain &chain);
void do_point_size();

View File

@ -23,8 +23,8 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(IndexBufferContext)::
CLP(IndexBufferContext)(GeomPrimitive *data) :
IndexBufferContext(data)
CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
IndexBufferContext(pgo, data)
{
_index = 0;
}

View File

@ -26,7 +26,8 @@
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(IndexBufferContext) : public IndexBufferContext {
public:
INLINE CLP(IndexBufferContext)(GeomPrimitive *data);
INLINE CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo,
GeomPrimitive *data);
// This is the GL "name" of the data object.
GLuint _index;

View File

@ -23,10 +23,9 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(TextureContext)::
CLP(TextureContext)(Texture *tex) :
TextureContext(tex)
CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex) :
TextureContext(pgo, tex)
{
_index = 0;
_already_applied = false;
_texture_memory_size = 0;
}

View File

@ -19,20 +19,3 @@
#include "notify.h"
TypeHandle CLP(TextureContext)::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: GLTextureContext::estimate_texture_memory
// Access: Public, Virtual
// Description: Estimates the amount of texture memory that will be
// consumed by loading this texture. This is mainly
// useful for debugging and reporting purposes.
//
// Returns a value in bytes.
////////////////////////////////////////////////////////////////////
size_t CLP(TextureContext)::
estimate_texture_memory() {
if (_texture_memory_size == 0) {
return TextureContext::estimate_texture_memory();
}
return _texture_memory_size;
}

View File

@ -25,9 +25,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(TextureContext) : public TextureContext {
public:
INLINE CLP(TextureContext)(Texture *tex);
virtual size_t estimate_texture_memory();
INLINE CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex);
// This is the GL "name" of the texture object.
GLuint _index;
@ -41,8 +39,6 @@ public:
GLsizei _height;
GLsizei _depth;
size_t _texture_memory_size;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -23,8 +23,8 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(VertexBufferContext)::
CLP(VertexBufferContext)(GeomVertexArrayData *data) :
VertexBufferContext(data)
CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
VertexBufferContext(pgo, data)
{
_index = 0;
}

View File

@ -26,7 +26,8 @@
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(VertexBufferContext) : public VertexBufferContext {
public:
INLINE CLP(VertexBufferContext)(GeomVertexArrayData *data);
INLINE CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo,
GeomVertexArrayData *data);
// This is the GL "name" of the data object.
GLuint _index;

View File

@ -11,6 +11,9 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
bufferContext.I bufferContext.h \
bufferContextChain.I bufferContextChain.h \
bufferResidencyTracker.I bufferResidencyTracker.h \
config_gobj.h \
geom.h geom.I \
geomContext.I geomContext.h \
@ -61,6 +64,9 @@
videoTexture.I videoTexture.h
#define INCLUDED_SOURCES \
bufferContext.cxx \
bufferContextChain.cxx \
bufferResidencyTracker.cxx \
config_gobj.cxx \
geomContext.cxx \
geom.cxx \
@ -108,6 +114,9 @@
videoTexture.cxx
#define INSTALL_HEADERS \
bufferContext.I bufferContext.h \
bufferContextChain.I bufferContextChain.h \
bufferResidencyTracker.I bufferResidencyTracker.h \
config_gobj.h \
geom.I geom.h \
textureContext.I textureContext.h \

View File

@ -0,0 +1,158 @@
// Filename: bufferContext.I
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: BufferContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContext::
BufferContext(BufferResidencyTracker *residency) :
_residency(residency),
_residency_state(0),
_data_size_bytes(0),
_owning_chain(&residency->_chains[0])
{
#ifdef DO_PSTATS
++(_owning_chain->_count);
insert_before(_owning_chain);
#endif // DO_PSTATS
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::get_data_size_bytes
// Access: Public
// Description: Returns the number of bytes previously reported for
// the data object. This is used to track changes in
// the data object's allocated size; if it changes from
// this, we need to create a new buffer. This is also
// used to track memory utilization in PStats.
////////////////////////////////////////////////////////////////////
INLINE size_t BufferContext::
get_data_size_bytes() const {
return _data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::get_modified
// Access: Public
// Description: Returns the UpdateSeq that was recorded the last time
// mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq BufferContext::
get_modified() const {
return _modified;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::set_active
// Access: Public
// Description: Changes the active flag associated with this object.
// An object is considered "active" if it was rendered
// in the current frame.
////////////////////////////////////////////////////////////////////
INLINE void BufferContext::
set_active(bool flag) {
#ifdef DO_PSTATS
if (flag) {
_residency_state |= BufferResidencyTracker::S_active;
// Assume that rendering the object automatically makes it
// resident.
_residency_state |= BufferResidencyTracker::S_resident;
} else {
_residency_state &= ~BufferResidencyTracker::S_active;
}
set_owning_chain(&_residency->_chains[_residency_state]);
#endif // DO_PSTATS
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::set_resident
// Access: Public
// Description: Changes the resident flag associated with this
// object. An object is considered "resident" if it
// appears to be resident in texture memory.
////////////////////////////////////////////////////////////////////
INLINE void BufferContext::
set_resident(bool flag) {
#ifdef DO_PSTATS
if (flag) {
_residency_state |= BufferResidencyTracker::S_resident;
} else {
_residency_state &= ~BufferResidencyTracker::S_resident;
}
set_owning_chain(&_residency->_chains[_residency_state]);
#endif // DO_PSTATS
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::get_next
// Access: Public
// Description: This can be used along with
// BufferContextChain::get_first() to walk through the
// list of objects stored on a tracker.
////////////////////////////////////////////////////////////////////
INLINE BufferContext *BufferContext::
get_next() const {
if ((BufferContextChain *)_next == _owning_chain) {
return NULL;
}
return (BufferContext *)_next;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::update_data_size_bytes
// Access: Public
// Description: Should be called (usually by a derived class) when
// the on-card size of this object has changed.
////////////////////////////////////////////////////////////////////
INLINE void BufferContext::
update_data_size_bytes(size_t new_data_size_bytes) {
_owning_chain->adjust_bytes((int)new_data_size_bytes - (int)_data_size_bytes);
_data_size_bytes = new_data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::update_modified
// Access: Public
// Description: Should be called (usually by a derived class) when
// the modified counter for this object has changed.
////////////////////////////////////////////////////////////////////
INLINE void BufferContext::
update_modified(UpdateSeq new_modified) {
_modified = new_modified;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContext::set_owning_chain
// Access: Private
// Description: Moves this object to a different BufferContextChain.
////////////////////////////////////////////////////////////////////
INLINE void BufferContext::
set_owning_chain(BufferContextChain *chain) {
if (chain != _owning_chain) {
--(_owning_chain->_count);
_owning_chain->adjust_bytes(-(int)_data_size_bytes);
remove_from_list();
_owning_chain = chain;
++(_owning_chain->_count);
_owning_chain->adjust_bytes((int)_data_size_bytes);
insert_before(_owning_chain);
}
}

View File

@ -0,0 +1,36 @@
// Filename: bufferContext.cxx
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 "bufferContext.h"
TypeHandle BufferContext::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: BufferContext::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
BufferContext::
~BufferContext() {
#ifdef DO_PSTATS
--(_owning_chain->_count);
_owning_chain->adjust_bytes(-(int)_data_size_bytes);
remove_from_list();
#endif // DO_PSTATS
_owning_chain = NULL;
}

View File

@ -0,0 +1,97 @@
// Filename: bufferContext.h
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 BUFFERCONTEXT_H
#define BUFFERCONTEXT_H
#include "pandabase.h"
#include "savedContext.h"
#include "updateSeq.h"
#include "linkedListNode.h"
#include "bufferContextChain.h"
#include "bufferResidencyTracker.h"
class PreparedGraphicsObjects;
////////////////////////////////////////////////////////////////////
// Class : BufferContext
// Description : This is a base class for those kinds of SavedContexts
// that occupy an easily-measured (and substantial)
// number of bytes in the video card's frame buffer
// memory or AGP memory. At the present, this includes
// most of the SavedContext types: VertexBufferContext
// and IndexBufferContext, as well as TextureContext.
//
// This class provides methods for tracking the video
// memory utilization, as well as residency of each
// object, via PStats.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA BufferContext : public SavedContext, private LinkedListNode {
public:
INLINE BufferContext(BufferResidencyTracker *residency);
virtual ~BufferContext();
INLINE size_t get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
INLINE void set_active(bool flag);
INLINE void set_resident(bool flag);
INLINE BufferContext *get_next() const;
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
INLINE void update_modified(UpdateSeq new_modified);
private:
INLINE void set_owning_chain(BufferContextChain *chain);
private:
BufferResidencyTracker *_residency;
int _residency_state;
size_t _data_size_bytes;
UpdateSeq _modified;
BufferContextChain *_owning_chain;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
SavedContext::init_type();
register_type(_type_handle, "BufferContext",
SavedContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
friend class BufferResidencyTracker;
friend class BufferContextChain;
};
#include "bufferContext.I"
#endif

View File

@ -0,0 +1,73 @@
// Filename: bufferContextChain.I
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain::
BufferContextChain() :
LinkedListNode(true), // This object is the root of a list of BufferContexts.
_total_size(0),
_count(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain::
~BufferContextChain() {
nassertv(_total_size == 0 && _count == 0);
}
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::get_total_size
// Access: Public
// Description: Returns the total number of bytes represented by the
// BufferContexts currently assigned to this tracker.
////////////////////////////////////////////////////////////////////
INLINE size_t BufferContextChain::
get_total_size() const {
return _total_size;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::get_count
// Access: Public
// Description: Returns the total number of BufferContexts currently
// assigned to this tracker.
////////////////////////////////////////////////////////////////////
INLINE int BufferContextChain::
get_count() const {
return _count;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::adjust_bytes
// Access: Private
// Description: Adds or removes some from the total byte count.
////////////////////////////////////////////////////////////////////
INLINE void BufferContextChain::
adjust_bytes(int delta) {
_total_size += delta;
}

View File

@ -0,0 +1,62 @@
// Filename: bufferContextChain.cxx
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 "bufferContextChain.h"
#include "bufferContext.h"
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::get_first
// Access: Public
// Description: Returns the first BufferContext object stored in the
// tracker. You can walk through the entire list of
// objects stored on the tracker by calling get_next()
// on each returned object, until the return value is
// NULL.
////////////////////////////////////////////////////////////////////
BufferContext *BufferContextChain::
get_first() {
// This method is declared non-inline so we can include
// bufferContext.h, which is necessary for proper downcasting of the
// _next pointer.
if (_next == this) {
return NULL;
}
return (BufferContext *)_next;
}
////////////////////////////////////////////////////////////////////
// Function: BufferContextChain::take_from
// Access: Public
// Description: Moves all of the BufferContexts from the other
// tracker onto this one.
////////////////////////////////////////////////////////////////////
void BufferContextChain::
take_from(BufferContextChain &other) {
_total_size += other._total_size;
_count += other._count;
other._total_size = 0;
other._count = 0;
LinkedListNode *llnode = other._next;
while (llnode != &other) {
((BufferContext *)llnode)->_owning_chain = this;
llnode = ((BufferContext *)llnode)->_next;
}
take_list_from(&other);
}

View File

@ -0,0 +1,61 @@
// Filename: bufferContextChain.h
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 BUFFERCONTEXTCHAIN_H
#define BUFFERCONTEXTCHAIN_H
#include "pandabase.h"
#include "linkedListNode.h"
class BufferContext;
////////////////////////////////////////////////////////////////////
// Class : BufferContextChain
// Description : This class maintains a linked list of BufferContexts
// that might be allocated on the graphics card in some
// context. There is a different BufferContextChain for
// resident textures, active textures, evicted textures,
// etc.
//
// The primary purpose of this class is to facilitate
// PStats reporting of graphics memory usage.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA BufferContextChain : private LinkedListNode {
public:
INLINE BufferContextChain();
INLINE ~BufferContextChain();
INLINE size_t get_total_size() const;
INLINE int get_count() const;
BufferContext *get_first();
void take_from(BufferContextChain &other);
private:
INLINE void adjust_bytes(int delta);
size_t _total_size;
int _count;
friend class BufferContext;
};
#include "bufferContextChain.I"
#endif

View File

@ -0,0 +1,58 @@
// Filename: bufferResidencyTracker.I
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::get_inactive_nonresident
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain &BufferResidencyTracker::
get_inactive_nonresident() {
return _chains[S_inactive_nonresident];
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::get_active_nonresident
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain &BufferResidencyTracker::
get_active_nonresident() {
return _chains[S_active_nonresident];
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::get_inactive_resident
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain &BufferResidencyTracker::
get_inactive_resident() {
return _chains[S_inactive_resident];
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::get_active_resident
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE BufferContextChain &BufferResidencyTracker::
get_active_resident() {
return _chains[S_active_resident];
}

View File

@ -0,0 +1,92 @@
// Filename: bufferResidencyTracker.cxx
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 "bufferResidencyTracker.h"
#include "clockObject.h"
PStatCollector BufferResidencyTracker::_gmem_collector("Graphics memory");
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
BufferResidencyTracker::
BufferResidencyTracker(const string &pgo_name, const string &type_name) :
_pgo_collector(_gmem_collector, pgo_name),
_active_resident_collector(PStatCollector(_pgo_collector, "Active"), type_name),
_active_nonresident_collector(PStatCollector(_pgo_collector, "Thrashing"), type_name),
_inactive_resident_collector(PStatCollector(_pgo_collector, "Inactive"), type_name),
_inactive_nonresident_collector(PStatCollector(_pgo_collector, "Nonresident"), type_name),
_active_frame(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::begin_frame
// Access: Public
// Description: To be called at the beginning of a frame, this
// initializes the active/inactive status.
////////////////////////////////////////////////////////////////////
void BufferResidencyTracker::
begin_frame() {
#ifdef DO_PSTATS
int this_frame = ClockObject::get_global_clock()->get_frame_count();
if (_active_frame != this_frame) {
_active_frame = this_frame;
// Move all of the previously "active" objects into "inactive".
// They'll get re-added to "active" as they get rendered.
move_inactive(_chains[S_inactive_nonresident],
_chains[S_active_nonresident]);
move_inactive(_chains[S_inactive_resident],
_chains[S_active_resident]);
}
#endif // DO_PSTATS
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::end_frame
// Access: Public
// Description: To be called at the end of a frame, this
// updates the PStatCollectors appropriately.
////////////////////////////////////////////////////////////////////
void BufferResidencyTracker::
end_frame() {
_inactive_nonresident_collector.set_level(_chains[S_inactive_nonresident].get_total_size());
_active_nonresident_collector.set_level(_chains[S_active_nonresident].get_total_size());
_inactive_resident_collector.set_level(_chains[S_inactive_resident].get_total_size());
_active_resident_collector.set_level(_chains[S_active_resident].get_total_size());
}
////////////////////////////////////////////////////////////////////
// Function: BufferResidencyTracker::move_inactive
// Access: Private
// Description: Moves all of the "active" objects into "inactive".
////////////////////////////////////////////////////////////////////
void BufferResidencyTracker::
move_inactive(BufferContextChain &inactive, BufferContextChain &active) {
BufferContext *node = active.get_first();
while (node != (BufferContext *)NULL) {
nassertv((node->_residency_state & S_active) != 0);
node->_residency_state &= ~S_active;
node = node->get_next();
}
inactive.take_from(active);
}

View File

@ -0,0 +1,92 @@
// Filename: bufferResidencyTracker.h
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 BUFFERRESIDENCYTRACKER_H
#define BUFFERRESIDENCYTRACKER_H
#include "pandabase.h"
#include "bufferContextChain.h"
#include "pStatCollector.h"
class BufferContext;
////////////////////////////////////////////////////////////////////
// Class : BufferResidencyTracker
// Description : This class is used to keep track of the current state
// of all the BufferContexts for a particular graphics
// context: whether each one is active (rendered this
// frame) or inactive (not rendered this frame), and
// whether it is resident or nonresident in video
// memory.
//
// The primary purpose of this class is to facilitate
// PStats reporting of video card memory usage.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA BufferResidencyTracker {
public:
BufferResidencyTracker(const string &pgo_name, const string &type_name);
void begin_frame();
void end_frame();
INLINE BufferContextChain &get_inactive_nonresident();
INLINE BufferContextChain &get_active_nonresident();
INLINE BufferContextChain &get_inactive_resident();
INLINE BufferContextChain &get_active_resident();
private:
void move_inactive(BufferContextChain &inactive, BufferContextChain &active);
private:
enum State {
// Individual bits.
S_active = 0x01,
S_resident = 0x02,
// Aggregate bits: unions of the above.
S_inactive_nonresident = 0x00,
S_active_nonresident = 0x01,
S_inactive_resident = 0x02,
S_active_resident = 0x03,
// The total number of different states.
S_num_states = 4,
};
// One chain for each of the possible states, ordered as above.
BufferContextChain _chains[S_num_states];
// A couple of PStatCollectors just to organize names.
static PStatCollector _gmem_collector;
PStatCollector _pgo_collector;
// One PStatCollector for each state. These are ordered in reverse
// order that we would like them to appear in the PStats graph.
PStatCollector _active_resident_collector;
PStatCollector _active_nonresident_collector;
PStatCollector _inactive_resident_collector;
PStatCollector _inactive_nonresident_collector;
// The frame number currently considered "active".
int _active_frame;
friend class BufferContext;
};
#include "bufferResidencyTracker.I"
#endif

View File

@ -16,6 +16,7 @@
//
////////////////////////////////////////////////////////////////////
#include "bufferContext.h"
#include "config_util.h"
#include "config_gobj.h"
#include "geom.h"
@ -238,6 +239,7 @@ ConfigVariableDouble default_keystone
ConfigureFn(config_gobj) {
BufferContext::init_type();
Geom::init_type();
GeomMunger::init_type();
GeomPrimitive::init_type();

View File

@ -1,4 +1,6 @@
#include "bufferContext.cxx"
#include "bufferContextChain.cxx"
#include "bufferResidencyTracker.cxx"
#include "geom.cxx"
#include "geomContext.cxx"
#include "geomEnums.cxx"

View File

@ -23,11 +23,9 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE IndexBufferContext::
IndexBufferContext(GeomPrimitive *data) :
_data(data),
// Initially, the number of bytes is zero, until the data has been
// loaded (and mark_loaded() is called).
_data_size_bytes(0)
IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
BufferContext(&pgo->_ibuffer_residency),
_data(data)
{
}
@ -42,19 +40,6 @@ get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: IndexBufferContext::get_data_size_bytes
// Access: Public
// Description: Returns the number of bytes previously reported for
// the data object. This is used to track changes in
// the data object's allocated size; if it changes from
// this, we need to create a new buffer.
////////////////////////////////////////////////////////////////////
INLINE int IndexBufferContext::
get_data_size_bytes() const {
return _data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: IndexBufferContext::changed_size
// Access: Public
@ -63,7 +48,7 @@ get_data_size_bytes() const {
////////////////////////////////////////////////////////////////////
INLINE bool IndexBufferContext::
changed_size() const {
return get_data_size_bytes() != _data->get_data_size_bytes();
return get_data_size_bytes() != (size_t)_data->get_data_size_bytes();
}
////////////////////////////////////////////////////////////////////
@ -85,18 +70,7 @@ changed_usage_hint() const {
////////////////////////////////////////////////////////////////////
INLINE bool IndexBufferContext::
was_modified() const {
return _modified != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: IndexBufferContext::get_modified
// Access: Public
// Description: Returns the UpdateSeq that was recorded the last time
// mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq IndexBufferContext::
get_modified() const {
return _modified;
return get_modified() != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
@ -108,7 +82,10 @@ get_modified() const {
////////////////////////////////////////////////////////////////////
INLINE void IndexBufferContext::
mark_loaded() {
_data_size_bytes = _data->get_data_size_bytes();
update_data_size_bytes(_data->get_data_size_bytes());
update_modified(_data->get_modified());
_usage_hint = _data->get_usage_hint();
_modified = _data->get_modified();
// Assume the buffer is now resident.
set_resident(true);
}

View File

@ -21,9 +21,9 @@
#include "pandabase.h"
#include "savedContext.h"
#include "updateSeq.h"
#include "bufferContext.h"
#include "geomPrimitive.h"
#include "preparedGraphicsObjects.h"
////////////////////////////////////////////////////////////////////
// Class : IndexBufferContext
@ -36,17 +36,15 @@
// allocate a vertex buffer for the array. OpenGL can
// create a buffer object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA IndexBufferContext : public SavedContext {
class EXPCL_PANDA IndexBufferContext : public BufferContext {
public:
INLINE IndexBufferContext(GeomPrimitive *data);
INLINE IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
INLINE GeomPrimitive *get_data() const;
INLINE int get_data_size_bytes() const;
INLINE bool changed_size() const;
INLINE bool changed_usage_hint() const;
INLINE bool was_modified() const;
INLINE UpdateSeq get_modified() const;
INLINE void mark_loaded();
@ -55,8 +53,6 @@ private:
// the GSG both own their IndexBufferContexts! That would create a
// circular reference count.
GeomPrimitive *_data;
UpdateSeq _modified;
int _data_size_bytes;
GeomEnums::UsageHint _usage_hint;
public:
@ -64,9 +60,9 @@ public:
return _type_handle;
}
static void init_type() {
SavedContext::init_type();
BufferContext::init_type();
register_type(_type_handle, "IndexBufferContext",
SavedContext::get_class_type());
BufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -17,6 +17,18 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::get_name
// Access: Public
// Description: Returns the name of the PreparedGraphicsObjects
// structure. This is an arbitrary name that serves
// mainly to uniquify the context for PStats reporting.
////////////////////////////////////////////////////////////////////
INLINE const string &PreparedGraphicsObjects::
get_name() const {
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::release_all
// Access: Public

View File

@ -27,8 +27,7 @@
#include "shaderExpansion.h"
#include "reMutexHolder.h"
PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer size");
int PreparedGraphicsObjects::_name_index = 0;
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::Constructor
@ -36,7 +35,12 @@ PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer
// Description:
////////////////////////////////////////////////////////////////////
PreparedGraphicsObjects::
PreparedGraphicsObjects() {
PreparedGraphicsObjects() :
_name(init_name()),
_texture_residency(_name, "texture"),
_vbuffer_residency(_name, "vbuffer"),
_ibuffer_residency(_name, "ibuffer")
{
}
////////////////////////////////////////////////////////////////////
@ -58,8 +62,7 @@ PreparedGraphicsObjects::
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
tc->_texture->clear_prepared(this);
tc->get_texture()->clear_prepared(this);
}
_prepared_textures.clear();
@ -95,7 +98,6 @@ PreparedGraphicsObjects::
vbci != _prepared_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (*vbci);
_total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
vbc->_data->clear_prepared(this);
}
@ -108,7 +110,6 @@ PreparedGraphicsObjects::
ibci != _prepared_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (*ibci);
_total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
ibc->_data->clear_prepared(this);
}
@ -175,8 +176,7 @@ void PreparedGraphicsObjects::
release_texture(TextureContext *tc) {
ReMutexHolder holder(_lock);
tc->_texture->clear_prepared(this);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
tc->get_texture()->clear_prepared(this);
// 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
@ -208,8 +208,7 @@ release_all_textures() {
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
tc->_texture->clear_prepared(this);
_total_texusage_pcollector.sub_level(tc->estimate_texture_memory());
tc->get_texture()->clear_prepared(this);
tc->_texture = (Texture *)NULL;
_released_textures.insert(tc);
@ -255,8 +254,6 @@ prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg) {
if (tc != (TextureContext *)NULL) {
bool prepared = _prepared_textures.insert(tc).second;
nassertr(prepared, tc);
_total_texusage_pcollector.add_level(tc->estimate_texture_memory());
}
return tc;
@ -600,7 +597,6 @@ release_vertex_buffer(VertexBufferContext *vbc) {
ReMutexHolder holder(_lock);
vbc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
// We have to set the Data pointer to NULL at this point, since
// the Data itself might destruct at any time after it has been
@ -633,7 +629,6 @@ release_all_vertex_buffers() {
++vbci) {
VertexBufferContext *vbc = (*vbci);
vbc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
vbc->_data = (GeomVertexArrayData *)NULL;
_released_vertex_buffers.insert(vbc);
@ -679,11 +674,6 @@ prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *
if (vbc != (VertexBufferContext *)NULL) {
bool prepared = _prepared_vertex_buffers.insert(vbc).second;
nassertr(prepared, vbc);
// The size has already been counted by
// GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to
// count it again here.
//_total_buffers_pcollector.add_level(vbc->get_data_size_bytes());
}
return vbc;
@ -747,7 +737,6 @@ release_index_buffer(IndexBufferContext *ibc) {
ReMutexHolder holder(_lock);
ibc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
// We have to set the Data pointer to NULL at this point, since
// the Data itself might destruct at any time after it has been
@ -780,7 +769,6 @@ release_all_index_buffers() {
++ibci) {
IndexBufferContext *ibc = (*ibci);
ibc->_data->clear_prepared(this);
_total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
ibc->_data = (GeomPrimitive *)NULL;
_released_index_buffers.insert(ibc);
@ -826,22 +814,17 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
if (ibc != (IndexBufferContext *)NULL) {
bool prepared = _prepared_index_buffers.insert(ibc).second;
nassertr(prepared, ibc);
// The size has already been counted by
// GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to
// count it again here.
//_total_buffers_pcollector.add_level(ibc->get_data_size_bytes());
}
return ibc;
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::update
// Function: PreparedGraphicsObjects::begin_frame
// Access: Public
// Description: This is called by the GraphicsStateGuardian to
// indicate that it is in a state to load or release
// textures.
// indicate that it is about to begin processing of the
// frame.
//
// Any texture contexts that were previously passed to
// release_texture() are actually passed to the GSG to
@ -849,7 +832,7 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
// passed to prepare_texture are actually loaded.
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
update(GraphicsStateGuardianBase *gsg) {
begin_frame(GraphicsStateGuardianBase *gsg) {
ReMutexHolder holder(_lock);
// First, release all the textures, geoms, and buffers awaiting
@ -904,6 +887,11 @@ update(GraphicsStateGuardianBase *gsg) {
_released_index_buffers.clear();
// Reset the residency trackers.
_texture_residency.begin_frame();
_vbuffer_residency.begin_frame();
_ibuffer_residency.begin_frame();
// Now prepare all the textures, geoms, and buffers awaiting
// preparation.
EnqueuedTextures::iterator qti;
@ -956,3 +944,33 @@ update(GraphicsStateGuardianBase *gsg) {
_enqueued_index_buffers.clear();
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::end_frame
// Access: Public
// Description: This is called by the GraphicsStateGuardian to
// indicate that it has finished processing of the
// frame.
////////////////////////////////////////////////////////////////////
void PreparedGraphicsObjects::
end_frame() {
ReMutexHolder holder(_lock);
_texture_residency.end_frame();
_vbuffer_residency.end_frame();
_ibuffer_residency.end_frame();
}
////////////////////////////////////////////////////////////////////
// Function: PreparedGraphicsObjects::init_name
// Access: Private, Static
// Description: Returns a new, unique name for a newly-constructed
// object.
////////////////////////////////////////////////////////////////////
string PreparedGraphicsObjects::
init_name() {
++_name_index;
ostringstream strm;
strm << "context" << _name_index;
return strm.str();
}

View File

@ -30,6 +30,7 @@
#include "pStatCollector.h"
#include "pset.h"
#include "reMutex.h"
#include "bufferResidencyTracker.h"
class TextureContext;
class GeomContext;
@ -62,6 +63,8 @@ public:
PreparedGraphicsObjects();
~PreparedGraphicsObjects();
INLINE const string &get_name() const;
INLINE void release_all();
void enqueue_texture(Texture *tex);
@ -103,7 +106,11 @@ public:
prepare_index_buffer_now(GeomPrimitive *data,
GraphicsStateGuardianBase *gsg);
void update(GraphicsStateGuardianBase *gsg);
void begin_frame(GraphicsStateGuardianBase *gsg);
void end_frame();
private:
static string init_name();
private:
typedef phash_set<TextureContext *, pointer_hash> Textures;
@ -118,6 +125,7 @@ private:
typedef phash_set< PT(GeomPrimitive) > EnqueuedIndexBuffers;
ReMutex _lock;
string _name;
Textures _prepared_textures, _released_textures;
EnqueuedTextures _enqueued_textures;
Geoms _prepared_geoms, _released_geoms;
@ -129,8 +137,13 @@ private:
IndexBuffers _prepared_index_buffers, _released_index_buffers;
EnqueuedIndexBuffers _enqueued_index_buffers;
static PStatCollector _total_texusage_pcollector;
static PStatCollector _total_buffers_pcollector;
public:
BufferResidencyTracker _texture_residency;
BufferResidencyTracker _vbuffer_residency;
BufferResidencyTracker _ibuffer_residency;
private:
static int _name_index;
friend class GraphicsStateGuardian;
};

View File

@ -542,6 +542,18 @@ set_keep_ram_image(bool keep_ram_image) {
_keep_ram_image = keep_ram_image;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_modified
// Access: Published
// Description: Returns a sequence number which is guaranteed to
// change at least every time the texture data or
// properties are modified.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq Texture::
get_modified() const {
return _modified;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::set_filename
// Access: Published

View File

@ -61,7 +61,6 @@ Texture(const string &name) :
_wrap_w = WM_repeat;
_anisotropic_degree = 1;
_keep_ram_image = true;
_all_dirty_flags = 0;
_border_color.set(0.0f, 0.0f, 0.0f, 1.0f);
_compression = CM_default;
_ram_image_compression = CM_off;
@ -115,7 +114,6 @@ Texture(const Texture &copy) :
_border_color(copy._border_color),
_compression(copy._compression),
_match_framebuffer_format(copy._match_framebuffer_format),
_all_dirty_flags(0),
_ram_image(copy._ram_image),
_ram_image_compression(copy._ram_image_compression),
_ram_page_size(copy._ram_page_size)
@ -157,10 +155,10 @@ operator = (const Texture &copy) {
_border_color = copy._border_color;
_compression = copy._compression;
_match_framebuffer_format = copy._match_framebuffer_format;
_all_dirty_flags = 0;
_ram_image = copy._ram_image;
_ram_image_compression = copy._ram_image_compression;
_ram_page_size = copy._ram_page_size;
++_modified;
}
////////////////////////////////////////////////////////////////////
@ -915,7 +913,7 @@ load(const PNMImage &pnmimage, int z) {
nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false);
}
mark_dirty(DF_image);
++_modified;
return true;
}
@ -1037,7 +1035,7 @@ load_related(const PT(InternalName) &suffix) const {
void Texture::
set_wrap_u(Texture::WrapMode wrap) {
if (_wrap_u != wrap) {
mark_dirty(DF_wrap);
++_modified;
_wrap_u = wrap;
}
}
@ -1050,7 +1048,7 @@ set_wrap_u(Texture::WrapMode wrap) {
void Texture::
set_wrap_v(Texture::WrapMode wrap) {
if (_wrap_v != wrap) {
mark_dirty(DF_wrap);
++_modified;
_wrap_v = wrap;
}
}
@ -1063,7 +1061,7 @@ set_wrap_v(Texture::WrapMode wrap) {
void Texture::
set_wrap_w(Texture::WrapMode wrap) {
if (_wrap_w != wrap) {
mark_dirty(DF_wrap);
++_modified;
_wrap_w = wrap;
}
}
@ -1076,11 +1074,7 @@ set_wrap_w(Texture::WrapMode wrap) {
void Texture::
set_minfilter(Texture::FilterType filter) {
if (_minfilter != filter) {
if (is_mipmap(_minfilter) != is_mipmap(filter)) {
mark_dirty(DF_filter | DF_mipmap);
} else {
mark_dirty(DF_filter);
}
++_modified;
_minfilter = filter;
}
}
@ -1093,7 +1087,7 @@ set_minfilter(Texture::FilterType filter) {
void Texture::
set_magfilter(Texture::FilterType filter) {
if (_magfilter != filter) {
mark_dirty(DF_filter);
++_modified;
_magfilter = filter;
}
}
@ -1110,7 +1104,7 @@ set_magfilter(Texture::FilterType filter) {
void Texture::
set_anisotropic_degree(int anisotropic_degree) {
if (_anisotropic_degree != anisotropic_degree) {
mark_dirty(DF_filter);
++_modified;
_anisotropic_degree = anisotropic_degree;
}
}
@ -1126,7 +1120,7 @@ set_anisotropic_degree(int anisotropic_degree) {
void Texture::
set_border_color(const Colorf &color) {
if (_border_color != color) {
mark_dirty(DF_border);
++_modified;
_border_color = color;
}
}
@ -1153,7 +1147,7 @@ set_border_color(const Colorf &color) {
void Texture::
set_compression(Texture::CompressionMode compression) {
if (_compression != compression) {
mark_dirty(DF_image);
++_modified;
_compression = compression;
}
}
@ -1254,7 +1248,7 @@ modify_ram_image() {
make_ram_image();
}
mark_dirty(DF_image);
++_modified;
_keep_ram_image = true;
return _ram_image;
}
@ -1272,7 +1266,7 @@ PTA_uchar Texture::
make_ram_image() {
_ram_image = PTA_uchar::empty_array(get_expected_ram_image_size());
_ram_image_compression = CM_off;
mark_dirty(DF_image);
++_modified;
_keep_ram_image = true;
return _ram_image;
}
@ -1299,7 +1293,7 @@ set_ram_image(PTA_uchar image, Texture::CompressionMode compression,
if (page_size == 0) {
_ram_page_size = image.size();
}
mark_dirty(DF_image);
++_modified;
}
_keep_ram_image = true;
}
@ -1685,12 +1679,6 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
_contexts[prepared_objects] = tc;
if (tc != (TextureContext *)NULL) {
// Now that we have a new TextureContext with zero dirty flags, our
// intersection of all dirty flags must be zero. This doesn't mean
// that some other contexts aren't still dirty, but at least one
// context isn't.
_all_dirty_flags = 0;
if (!keep_texture_ram && !_keep_ram_image) {
// Once we have prepared the texture, we can generally safely
// remove the pixels from main RAM. The GSG is now responsible
@ -1706,41 +1694,6 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
return tc;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::mark_dirty
// Access: Public
// Description: Sets the indicated dirty bits on for all texture
// contexts that share this Texture. Does not change
// the bits that are not on. This presumably will
// inform the GSG that the texture properties have
// changed. See also TextureContext::mark_dirty().
//
// Normally, this does not need to be called directly;
// changing the properties on the texture will
// automatically call this. However, if you fiddle with
// the texture image directly, you may need to
// explicitly call mark_dirty(Texture::DF_image).
////////////////////////////////////////////////////////////////////
void Texture::
mark_dirty(int flags_to_set) {
if ((_all_dirty_flags & flags_to_set) == flags_to_set) {
// If all the texture contexts already share these bits, no need
// to do anything else.
return;
}
// Otherwise, iterate through the contexts and mark them all dirty.
Contexts::iterator ci;
for (ci = _contexts.begin(); ci != _contexts.end(); ++ci) {
TextureContext *tc = (*ci).second;
if (tc != (TextureContext *)NULL) {
tc->mark_dirty(flags_to_set);
}
}
_all_dirty_flags |= flags_to_set;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::has_cull_callback
// Access: Public, Virtual

View File

@ -26,6 +26,7 @@
#include "namable.h"
#include "internalName.h"
#include "graphicsStateGuardianBase.h"
#include "updateSeq.h"
#include "pmap.h"
class PNMImage;
@ -267,6 +268,8 @@ PUBLISHED:
INLINE void set_keep_ram_image(bool keep_ram_image);
virtual bool get_keep_ram_image() const;
INLINE UpdateSeq get_modified() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
@ -307,19 +310,6 @@ public:
TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
// These bits are used as parameters to Texture::mark_dirty() and
// also TextureContext::mark_dirty() (and related functions in
// TextureContext).
enum DirtyFlags {
DF_image = 0x001, // The image pixels have changed.
DF_wrap = 0x002, // The wrap properties have changed.
DF_filter = 0x004, // The minfilter or magfilter have changed.
DF_mipmap = 0x008, // The use of mipmaps or not has changed.
DF_border = 0x010, // The border has changed.
};
void mark_dirty(int flags_to_set);
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
@ -415,15 +405,11 @@ protected:
typedef pmap<PT(InternalName), PT(Texture)> RelatedTextures;
RelatedTextures _related_textures;
// This value represents the intersection of all the dirty flags of
// the various TextureContexts that might be associated with this
// texture.
int _all_dirty_flags;
PTA_uchar _ram_image;
CompressionMode _ram_image_compression;
size_t _ram_page_size;
UpdateSeq _modified;
// Datagram stuff
public:

View File

@ -23,70 +23,49 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE TextureContext::
TextureContext(Texture *tex) :
TextureContext(PreparedGraphicsObjects *pgo, Texture *tex) :
BufferContext(&pgo->_texture_residency),
_texture(tex)
{
_dirty_flags = ~0;
#ifdef DO_PSTATS
update_data_size_bytes(estimate_texture_memory());
#endif
}
////////////////////////////////////////////////////////////////////
// Function: TextureContext::mark_dirty
// Function: TextureContext::get_texture
// Access: Public
// Description: Marks the context "dirty", i.e. its properties are
// different from the last time the GSG has seen them.
// Presumably, the GSG will respond by updating the
// properties and clearing the dirty bits the next time
// it renders the texture.
//
// The value is the union of all the bits that are to be
// set dirty; bits that are not set in this parameter
// are left unchanged. See Texture::DirtyFlags for a
// list of available bits.
//
// Usually this function is not called directly, but
// rather is called by Texture::mark_dirty() as a result
// of changing properties directly on the texture.
// Description: Returns the pointer to the associated Texture
// object.
////////////////////////////////////////////////////////////////////
INLINE Texture *TextureContext::
get_texture() const {
return _texture;
}
////////////////////////////////////////////////////////////////////
// Function: TextureContext::was_modified
// Access: Public
// Description: Returns true if the texture has been modified since the
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool TextureContext::
was_modified() const {
return get_modified() != _texture->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: TextureContext::mark_loaded
// Access: Public
// Description: Should be called after the TextureContext has been
// loaded into graphics memory, this updates the
// internal flags for changed_size() and modified().
////////////////////////////////////////////////////////////////////
INLINE void TextureContext::
mark_dirty(int flags_to_set) {
_dirty_flags |= flags_to_set;
}
mark_loaded() {
// _data_size_bytes = _data->get_texture_size_bytes();
update_modified(_texture->get_modified());
////////////////////////////////////////////////////////////////////
// Function: TextureContext::clear_dirty_flags
// Access: Public
// Description: Removes the indicated flags from the "dirty" bits.
// See mark_dirty().
//
// The value is the union of all the bits that are to be
// cleared; if a bit is set in the parameter, it will be
// removed from the dirty set. Bits that are not set in
// this parameter are left unchanged.
//
// This function is intended to be called by the GSG
// after it has updated the texture parameters.
////////////////////////////////////////////////////////////////////
INLINE void TextureContext::
clear_dirty_flags(int flags_to_clear) {
_dirty_flags &= ~flags_to_clear;
_texture->_all_dirty_flags &= ~flags_to_clear;
// Assume the texture is now resident.
set_resident(true);
}
////////////////////////////////////////////////////////////////////
// Function: TextureContext::get_dirty_flags
// Access: Public
// Description: Returns the current state of the dirty flags. If
// this is non-zero, it represents the union of all
// properties that have been changed since the last call
// to clear_dirty_flags().
//
// This function is intended to be called by the GSG to
// determine what properties need to be updated. See
// Texture::DirtyFlags for a list of possible bits.
////////////////////////////////////////////////////////////////////
INLINE int TextureContext::
get_dirty_flags() const {
_texture->reconsider_dirty();
return _dirty_flags;
}

View File

@ -21,8 +21,9 @@
#include "pandabase.h"
#include "savedContext.h"
#include "bufferContext.h"
#include "texture.h"
#include "preparedGraphicsObjects.h"
////////////////////////////////////////////////////////////////////
// Class : TextureContext
@ -37,33 +38,31 @@
// texture and store it here. The texture stores all of
// these handles internally.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TextureContext : public SavedContext {
class EXPCL_PANDA TextureContext : public BufferContext {
public:
INLINE TextureContext(Texture *tex);
INLINE TextureContext(PreparedGraphicsObjects *pgo, Texture *tex);
INLINE Texture *get_texture() const;
INLINE bool was_modified() const;
INLINE void mark_loaded();
virtual size_t estimate_texture_memory();
private:
// This cannot be a PT(Texture), because the texture and the GSG
// both own their TextureContexts! That would create a circular
// reference count.
Texture *_texture;
INLINE void mark_dirty(int flags_to_set);
INLINE void clear_dirty_flags(int flags_to_clear = ~0);
INLINE int get_dirty_flags() const;
private:
int _dirty_flags;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
SavedContext::init_type();
BufferContext::init_type();
register_type(_type_handle, "TextureContext",
SavedContext::get_class_type());
BufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -72,6 +71,8 @@ public:
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
#include "textureContext.I"

View File

@ -23,11 +23,9 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexBufferContext::
VertexBufferContext(GeomVertexArrayData *data) :
_data(data),
// Initially, the number of bytes is zero, until the data has been
// loaded (and mark_loaded() is called).
_data_size_bytes(0)
VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
BufferContext(&pgo->_vbuffer_residency),
_data(data)
{
}
@ -42,19 +40,6 @@ get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::get_data_size_bytes
// Access: Public
// Description: Returns the number of bytes previously reported for
// the data object. This is used to track changes in
// the data object's allocated size; if it changes from
// this, we need to create a new buffer.
////////////////////////////////////////////////////////////////////
INLINE int VertexBufferContext::
get_data_size_bytes() const {
return _data_size_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::changed_size
// Access: Public
@ -63,7 +48,7 @@ get_data_size_bytes() const {
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
changed_size() const {
return get_data_size_bytes() != _data->get_data_size_bytes();
return get_data_size_bytes() != (size_t)_data->get_data_size_bytes();
}
////////////////////////////////////////////////////////////////////
@ -85,18 +70,7 @@ changed_usage_hint() const {
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
was_modified() const {
return _modified != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
// Function: VertexBufferContext::get_modified
// Access: Public
// Description: Returns the UpdateSeq that was recorded the last time
// mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq VertexBufferContext::
get_modified() const {
return _modified;
return get_modified() != _data->get_modified();
}
////////////////////////////////////////////////////////////////////
@ -108,7 +82,10 @@ get_modified() const {
////////////////////////////////////////////////////////////////////
INLINE void VertexBufferContext::
mark_loaded() {
_data_size_bytes = _data->get_data_size_bytes();
update_data_size_bytes(_data->get_data_size_bytes());
update_modified(_data->get_modified());
_usage_hint = _data->get_usage_hint();
_modified = _data->get_modified();
// Assume the buffer is now resident.
set_resident(true);
}

View File

@ -21,9 +21,9 @@
#include "pandabase.h"
#include "savedContext.h"
#include "updateSeq.h"
#include "bufferContext.h"
#include "geomVertexArrayData.h"
#include "preparedGraphicsObjects.h"
////////////////////////////////////////////////////////////////////
// Class : VertexBufferContext
@ -36,17 +36,16 @@
// allocate a vertex buffer for the array. OpenGL can
// create a buffer object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VertexBufferContext : public SavedContext {
class EXPCL_PANDA VertexBufferContext : public BufferContext {
public:
INLINE VertexBufferContext(GeomVertexArrayData *data);
INLINE VertexBufferContext(PreparedGraphicsObjects *pgo,
GeomVertexArrayData *data);
INLINE GeomVertexArrayData *get_data() const;
INLINE int get_data_size_bytes() const;
INLINE bool changed_size() const;
INLINE bool changed_usage_hint() const;
INLINE bool was_modified() const;
INLINE UpdateSeq get_modified() const;
INLINE void mark_loaded();
@ -55,8 +54,6 @@ private:
// the GSG both own their VertexBufferContexts! That would create a
// circular reference count.
GeomVertexArrayData *_data;
UpdateSeq _modified;
int _data_size_bytes;
GeomEnums::UsageHint _usage_hint;
public:
@ -64,9 +61,9 @@ public:
return _type_handle;
}
static void init_type() {
SavedContext::init_type();
BufferContext::init_type();
register_type(_type_handle, "VertexBufferContext",
SavedContext::get_class_type());
BufferContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -154,21 +154,7 @@ static TimeCollectorProperties time_properties[] = {
};
static LevelCollectorProperties level_properties[] = {
{ 1, "Texture usage", { 1.0, 0.0, 0.5 }, "MB", 12, 1048576 },
{ 1, "Texture usage:Active", { 0.5, 1.0, 0.8 } },
{ 1, "Texture memory", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 },
{ 1, "Texture memory:In use", { 0.0, 1.0, 1.0 } },
{ 1, "Texture manager", { 1.0, 0.0, 0.0 }, "MB", 12, 1048576 },
{ 1, "Texture manager:Resident", { 1.0, 1.0, 0.0 } },
{ 1, "Prepared Textures", { 0.6, 0.8, 0.0 }, "", 500 },
{ 1, "Prepared Textures:Active", { 0.0, 0.6, 0.8 } },
{ 1, "Prepared Geoms", { 1.0, 0.0, 0.5 }, "", 500 },
{ 1, "Prepared Geoms:Active", { 0.5, 1.0, 0.8 } },
{ 1, "Prepared GeomNodes", { 1.0, 0.0, 0.5 }, "", 500 },
{ 1, "Prepared GeomNodes:Active", { 0.5, 1.0, 0.8 } },
{ 1, "Vertex buffer size", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 },
{ 1, "Vertex buffer size:Active vertex", { 1.0, 0.0, 0.5 } },
{ 1, "Vertex buffer size:Active index" , { 0.5, 0.6, 1.0 } },
{ 1, "Graphics memory", { 0.0, 0.0, 1.0 }, "MB", 64, 1048576 },
{ 1, "Vertex buffer switch", { 0.0, 0.6, 0.8 }, "", 500 },
{ 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } },
{ 1, "Vertex buffer switch:Index", { 0.8, 0.6, 0.3 } },

View File

@ -39,6 +39,7 @@
ioPtaDatagramFloat.h ioPtaDatagramInt.h \
ioPtaDatagramShort.h keyboardButton.h lineStream.I \
lineStream.h lineStreamBuf.I lineStreamBuf.h \
linkedListNode.I linkedListNode.h \
load_prc_file.h \
modifierButtons.I modifierButtons.h mouseButton.h \
mouseData.I mouseData.h nameUniquifier.I nameUniquifier.h \
@ -75,6 +76,7 @@
ioPtaDatagramFloat.cxx \
ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \
keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \
linkedListNode.cxx \
load_prc_file.cxx \
modifierButtons.cxx mouseButton.cxx mouseData.cxx \
nameUniquifier.cxx \
@ -119,6 +121,7 @@
ioPtaDatagramFloat.h ioPtaDatagramInt.h \
ioPtaDatagramShort.h iterator_types.h keyboardButton.h lineStream.I \
lineStream.h lineStreamBuf.I lineStreamBuf.h \
linkedListNode.I linkedListNode.h \
load_prc_file.h \
modifierButtons.I \
modifierButtons.h mouseButton.h mouseData.I mouseData.h \

View File

@ -0,0 +1,108 @@
// Filename: linkedListNode.I
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE LinkedListNode::
LinkedListNode() {
#ifndef NDEBUG
_next = NULL;
_prev = NULL;
#endif
}
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::Constructor 2
// Access: Protected
// Description: This constructor should be invoked for any
// LinkedListNodes that will be used to serve as the
// root of a list. It sets up the pointers as an empty
// list.
////////////////////////////////////////////////////////////////////
INLINE LinkedListNode::
LinkedListNode(bool) {
_next = this;
_prev = this;
}
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::Destructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE LinkedListNode::
~LinkedListNode() {
nassertv((_next == NULL && _prev == NULL) || (_next == this && _prev == this));
}
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::remove_from_list
// Access: Protected
// Description: Removes a LinkedListNode record from the
// doubly-linked list.
////////////////////////////////////////////////////////////////////
INLINE void LinkedListNode::
remove_from_list() {
nassertv(_prev->_next == this && _next->_prev == this);
_prev->_next = _next;
_next->_prev = _prev;
#ifndef NDEBUG
_next = NULL;
_prev = NULL;
#endif
}
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::insert_before
// Access: Protected
// Description: Adds a LinkedListNode record before the indicated
// node in the doubly-linked list.
////////////////////////////////////////////////////////////////////
INLINE void LinkedListNode::
insert_before(LinkedListNode *node) {
nassertv(node->_prev != NULL && node->_prev->_next == node && node->_next->_prev == node);
nassertv(_prev == (LinkedListNode *)NULL &&
_next == (LinkedListNode *)NULL);
_prev = node->_prev;
_next = node;
_prev->_next = this;
node->_prev = this;
}
////////////////////////////////////////////////////////////////////
// Function: LinkedListNode::take_list_from
// Access: Protected
// Description: Given that this LinkedListNode represents the root of
// a list, and the other pointer represents the root of
// a different list, move all of the nodes (except the
// root itself) from other_root onto this list.
////////////////////////////////////////////////////////////////////
INLINE void LinkedListNode::
take_list_from(LinkedListNode *other_root) {
other_root->_next->_prev = _prev;
_prev->_next = other_root->_next;
other_root->_prev->_next = this;
_prev = other_root->_prev;
other_root->_next = other_root;
other_root->_prev = other_root;
}

View File

@ -0,0 +1,19 @@
// Filename: linkedListNode.cxx
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 "linkedListNode.h"

View File

@ -0,0 +1,50 @@
// Filename: linkedListNode.h
// Created by: drose (16Mar06)
//
////////////////////////////////////////////////////////////////////
//
// 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 LINKEDLISTNODE_H
#define LINKEDLISTNODE_H
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Class : LinkedListNode
// Description : This just stores the pointers to implement a
// doubly-linked list of some kind of object. There are
// occasions when a hand-rolled linked list is more
// appropriate than an STL container.
//
// Typically, each node of the linked list, as well as
// the root of the list, will inherit from this class.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LinkedListNode {
protected:
INLINE LinkedListNode();
INLINE LinkedListNode(bool);
INLINE ~LinkedListNode();
INLINE void remove_from_list();
INLINE void insert_before(LinkedListNode *node);
INLINE void take_list_from(LinkedListNode *other_root);
LinkedListNode *_prev, *_next;
};
#include "linkedListNode.I"
#endif

View File

@ -23,4 +23,5 @@
#include "keyboardButton.cxx"
#include "lineStream.cxx"
#include "lineStreamBuf.cxx"
#include "linkedListNode.cxx"
#include "load_prc_file.cxx"