mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -04:00
work-in-progress: asynchronous texture loads
This commit is contained in:
parent
b83c917981
commit
d7e6603118
@ -32,7 +32,7 @@ void DrawCullHandler::
|
||||
record_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
// Munge vertices as needed for the GSG's requirements, and the
|
||||
// object's current state.
|
||||
bool force = !allow_incomplete_render;
|
||||
bool force = !_gsg->get_incomplete_render();
|
||||
Thread *current_thread = traverser->get_current_thread();
|
||||
|
||||
if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
|
||||
|
@ -205,6 +205,15 @@ ConfigVariableBool alpha_scale_via_texture
|
||||
"application specifically enables it. See also "
|
||||
"color-scale-via-lighting."));
|
||||
|
||||
ConfigVariableBool allow_incomplete_render
|
||||
("allow-incomplete-render", false,
|
||||
PRC_DESC("When this is true, the frame may be rendered even if some of the "
|
||||
"geometry in the scene has been paged out. The nonresident "
|
||||
"geometry will be rendered as soon as it can be paged back in, "
|
||||
"which may be several frames in the future. When this is false, "
|
||||
"geometry is always paged in when needed, holding up the frame "
|
||||
"render if necessary."));
|
||||
|
||||
ConfigVariableInt win_size
|
||||
("win-size", "640 480",
|
||||
PRC_DESC("This is the default size at which to open a new window. This "
|
||||
|
@ -58,6 +58,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableString red_blue_stereo_colors;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool auto_generate_mipmaps;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool color_scale_via_lighting;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool alpha_scale_via_texture;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool allow_incomplete_render;
|
||||
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt win_size;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt win_origin;
|
||||
|
@ -74,6 +74,30 @@ get_portal_cull() const {
|
||||
return _portal_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::set_default_loader
|
||||
// Access: Public
|
||||
// Description: Sets the Loader object that will be assigned to every
|
||||
// GSG created with this GraphicsEngine. See
|
||||
// GraphicsStateGuardian::set_loader().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsEngine::
|
||||
set_default_loader(Loader *loader) {
|
||||
_default_loader = loader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::get_default_loader
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the Loader object that will be assigned to
|
||||
// every GSG created with this GraphicsEngine. See
|
||||
// GraphicsStateGuardian::set_loader().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Loader *GraphicsEngine::
|
||||
get_default_loader() const {
|
||||
return _default_loader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::close_gsg
|
||||
// Access: Published
|
||||
|
@ -1760,6 +1760,9 @@ do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
|
||||
gsg->_threading_model = threading_model;
|
||||
gsg->_pipe = pipe;
|
||||
gsg->_engine = this;
|
||||
if (!_default_loader.is_null()) {
|
||||
gsg->set_loader(_default_loader);
|
||||
}
|
||||
|
||||
auto_adjust_capabilities(gsg);
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "pset.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "indirectLess.h"
|
||||
#include "loader.h"
|
||||
|
||||
class Pipeline;
|
||||
class DisplayRegion;
|
||||
@ -66,6 +67,9 @@ PUBLISHED:
|
||||
INLINE void set_portal_cull(bool value);
|
||||
INLINE bool get_portal_cull() const;
|
||||
|
||||
INLINE void set_default_loader(Loader *loader);
|
||||
INLINE Loader *get_default_loader() const;
|
||||
|
||||
GraphicsOutput *make_output(GraphicsPipe *pipe,
|
||||
const string &name, int sort,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
@ -322,6 +326,7 @@ private:
|
||||
GraphicsThreadingModel _threading_model;
|
||||
bool _auto_flip;
|
||||
bool _portal_enabled; //toggle to portal culling on/off
|
||||
PT(Loader) _default_loader;
|
||||
|
||||
enum FlipState {
|
||||
FS_draw, // Still drawing.
|
||||
|
@ -105,6 +105,79 @@ is_valid() const {
|
||||
return _is_valid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::needs_reset
|
||||
// Access: Public
|
||||
// Description: Returns true if the gsg is marked as needing a
|
||||
// reset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
needs_reset() const {
|
||||
return _needs_reset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_incomplete_render
|
||||
// Access: Public
|
||||
// Description: Sets the incomplete_render flag. When this is
|
||||
// true, the frame will be rendered even if some of the
|
||||
// geometry or textures in the scene are not available
|
||||
// (e.g. they have been temporarily paged out). When
|
||||
// this is false, the frame will be held up while this
|
||||
// data is reloaded.
|
||||
//
|
||||
// Setting this true allows for a smoother frame rate,
|
||||
// but occasionally parts of the frame will be invisible
|
||||
// or missing (they will generally come in within a
|
||||
// second or two). Setting this false guarantees that
|
||||
// every frame will be complete, but may cause more
|
||||
// chugs as things are loaded up at runtime.
|
||||
//
|
||||
// You may want to set this false during loading
|
||||
// screens, to guarantee that all of your assets are
|
||||
// available by the time you take the loading screen
|
||||
// down.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsStateGuardian::
|
||||
set_incomplete_render(bool incomplete_render) {
|
||||
_incomplete_render = incomplete_render;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_incomplete_render
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the incomplete_render flag. See
|
||||
// set_incomplete_render().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
get_incomplete_render() const {
|
||||
return _incomplete_render;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_loader
|
||||
// Access: Public
|
||||
// Description: Sets the Loader object that will be used by this GSG
|
||||
// to load textures when necessary, if
|
||||
// get_incomplete_render() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsStateGuardian::
|
||||
set_loader(Loader *loader) {
|
||||
_loader = loader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_loader
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the Loader object that will be used by this
|
||||
// GSG to load textures when necessary, if
|
||||
// get_incomplete_render() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Loader *GraphicsStateGuardian::
|
||||
get_loader() const {
|
||||
return _loader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_pipe
|
||||
// Access: Published
|
||||
@ -716,17 +789,6 @@ mark_new() {
|
||||
_needs_reset = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::needs_reset
|
||||
// Access: Public
|
||||
// Description: Returns true if the gsg is marked as needing a
|
||||
// reset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
needs_reset() const {
|
||||
return _needs_reset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_external_transform
|
||||
// Access: Public
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "directionalLight.h"
|
||||
#include "pointLight.h"
|
||||
#include "spotlight.h"
|
||||
#include "textureReloadRequest.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
@ -131,6 +132,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
|
||||
_active = true;
|
||||
_prepared_objects = new PreparedGraphicsObjects;
|
||||
_stereo_buffer_mask = ~0;
|
||||
_incomplete_render = allow_incomplete_render;
|
||||
|
||||
_is_hardware = false;
|
||||
_prefers_triangle_strips = false;
|
||||
@ -317,106 +319,6 @@ get_internal_coordinate_system() const {
|
||||
return _internal_coordinate_system;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::reset
|
||||
// Access: Public, Virtual
|
||||
// Description: Resets all internal state as if the gsg were newly
|
||||
// created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
reset() {
|
||||
_needs_reset = false;
|
||||
_is_valid = false;
|
||||
|
||||
_state_rs = NULL;
|
||||
_target_rs = NULL;
|
||||
_state.clear_to_zero();
|
||||
_target.clear_to_defaults();
|
||||
_internal_transform = _cs_transform;
|
||||
_scene_null = new SceneSetup;
|
||||
_scene_setup = _scene_null;
|
||||
|
||||
_color_write_mask = ColorWriteAttrib::C_all;
|
||||
|
||||
_has_scene_graph_color = false;
|
||||
_scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_transform_stale = true;
|
||||
_color_blend_involves_color_scale = false;
|
||||
_texture_involves_color_scale = false;
|
||||
_vertex_colors_enabled = true;
|
||||
_lighting_enabled = false;
|
||||
_num_lights_enabled = 0;
|
||||
_num_clip_planes_enabled = 0;
|
||||
|
||||
_color_scale_enabled = false;
|
||||
_current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_has_texture_alpha_scale = false;
|
||||
|
||||
_has_material_force_color = false;
|
||||
_material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
_tex_gen_modifies_mat = false;
|
||||
_last_max_stage_index = 0;
|
||||
|
||||
_is_valid = true;
|
||||
|
||||
if (_stencil_render_states) {
|
||||
delete _stencil_render_states;
|
||||
_stencil_render_states = 0;
|
||||
}
|
||||
_stencil_render_states = new StencilRenderStates (this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_state_and_transform
|
||||
// Access: Public
|
||||
// Description: Simultaneously resets the render state and the
|
||||
// transform state.
|
||||
//
|
||||
// This transform specified is the "internal" net
|
||||
// transform, already converted into the GSG's internal
|
||||
// coordinate space by composing it to
|
||||
// get_cs_transform(). (Previously, this used to be the
|
||||
// "external" net transform, with the assumption that
|
||||
// that GSG would convert it internally, but that is no
|
||||
// longer the case.)
|
||||
//
|
||||
// Special case: if (state==NULL), then the target
|
||||
// state is already stored in _target.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
set_state_and_transform(const RenderState *state,
|
||||
const TransformState *trans) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::clear
|
||||
// Access: Public
|
||||
// Description: Clears the framebuffer within the current
|
||||
// DisplayRegion, according to the flags indicated by
|
||||
// the given DrawableRegion object.
|
||||
//
|
||||
// This does not set the DisplayRegion first. You
|
||||
// should call prepare_display_region() to specify the
|
||||
// region you wish the clear operation to apply to.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
clear(DrawableRegion *clearable) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_render_buffer
|
||||
// Access: Public
|
||||
// Description: Returns a RenderBuffer object suitable for operating
|
||||
// on the requested set of buffers. buffer_type is the
|
||||
// union of all the desired RenderBuffer::Type values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RenderBuffer GraphicsStateGuardian::
|
||||
get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
|
||||
return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_prepared_objects
|
||||
// Access: Public, Virtual
|
||||
@ -429,6 +331,37 @@ get_prepared_objects() {
|
||||
return _prepared_objects;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_gamma
|
||||
// Access: Published, Virtual
|
||||
// Description: Set gamma. Returns true on success.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
set_gamma(float gamma) {
|
||||
_gamma = gamma;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_gamma
|
||||
// Access: Published
|
||||
// Description: Get the current gamma setting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float GraphicsStateGuardian::
|
||||
get_gamma(float gamma) {
|
||||
return _gamma;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::restore_gamma
|
||||
// Access: Published, Virtual
|
||||
// Description: Restore original gamma setting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
restore_gamma() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_scene
|
||||
// Access: Public
|
||||
@ -1152,6 +1085,26 @@ prepare_lens() {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::calc_projection_mat
|
||||
// Access: Public, Virtual
|
||||
// Description: Given a lens, this function calculates the appropriate
|
||||
// projection matrix for this gsg. The result depends
|
||||
// on the peculiarities of the rendering API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) GraphicsStateGuardian::
|
||||
calc_projection_mat(const Lens *lens) {
|
||||
if (lens == (Lens *)NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!lens->is_linear()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TransformState::make_identity();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::begin_frame
|
||||
// Access: Public, Virtual
|
||||
@ -1462,6 +1415,106 @@ end_draw_primitives() {
|
||||
_data_reader = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::reset
|
||||
// Access: Public, Virtual
|
||||
// Description: Resets all internal state as if the gsg were newly
|
||||
// created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
reset() {
|
||||
_needs_reset = false;
|
||||
_is_valid = false;
|
||||
|
||||
_state_rs = NULL;
|
||||
_target_rs = NULL;
|
||||
_state.clear_to_zero();
|
||||
_target.clear_to_defaults();
|
||||
_internal_transform = _cs_transform;
|
||||
_scene_null = new SceneSetup;
|
||||
_scene_setup = _scene_null;
|
||||
|
||||
_color_write_mask = ColorWriteAttrib::C_all;
|
||||
|
||||
_has_scene_graph_color = false;
|
||||
_scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_transform_stale = true;
|
||||
_color_blend_involves_color_scale = false;
|
||||
_texture_involves_color_scale = false;
|
||||
_vertex_colors_enabled = true;
|
||||
_lighting_enabled = false;
|
||||
_num_lights_enabled = 0;
|
||||
_num_clip_planes_enabled = 0;
|
||||
|
||||
_color_scale_enabled = false;
|
||||
_current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_has_texture_alpha_scale = false;
|
||||
|
||||
_has_material_force_color = false;
|
||||
_material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
_tex_gen_modifies_mat = false;
|
||||
_last_max_stage_index = 0;
|
||||
|
||||
_is_valid = true;
|
||||
|
||||
if (_stencil_render_states) {
|
||||
delete _stencil_render_states;
|
||||
_stencil_render_states = 0;
|
||||
}
|
||||
_stencil_render_states = new StencilRenderStates (this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_state_and_transform
|
||||
// Access: Public
|
||||
// Description: Simultaneously resets the render state and the
|
||||
// transform state.
|
||||
//
|
||||
// This transform specified is the "internal" net
|
||||
// transform, already converted into the GSG's internal
|
||||
// coordinate space by composing it to
|
||||
// get_cs_transform(). (Previously, this used to be the
|
||||
// "external" net transform, with the assumption that
|
||||
// that GSG would convert it internally, but that is no
|
||||
// longer the case.)
|
||||
//
|
||||
// Special case: if (state==NULL), then the target
|
||||
// state is already stored in _target.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
set_state_and_transform(const RenderState *state,
|
||||
const TransformState *trans) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::clear
|
||||
// Access: Public
|
||||
// Description: Clears the framebuffer within the current
|
||||
// DisplayRegion, according to the flags indicated by
|
||||
// the given DrawableRegion object.
|
||||
//
|
||||
// This does not set the DisplayRegion first. You
|
||||
// should call prepare_display_region() to specify the
|
||||
// region you wish the clear operation to apply to.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
clear(DrawableRegion *clearable) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_render_buffer
|
||||
// Access: Public
|
||||
// Description: Returns a RenderBuffer object suitable for operating
|
||||
// on the requested set of buffers. buffer_type is the
|
||||
// union of all the desired RenderBuffer::Type values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RenderBuffer GraphicsStateGuardian::
|
||||
get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
|
||||
return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_cs_transform
|
||||
// Access: Public, Virtual
|
||||
@ -1798,6 +1851,58 @@ init_frame_pstats() {
|
||||
}
|
||||
#endif // DO_PSTATS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::create_gamma_table
|
||||
// Access: Public, Static
|
||||
// Description: Create a gamma table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
create_gamma_table (float gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
|
||||
int i;
|
||||
|
||||
if (gamma <= 0.0) {
|
||||
// avoid divide by zero and negative exponents
|
||||
gamma = 1.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
double g;
|
||||
double x;
|
||||
float gamma_correction;
|
||||
|
||||
x = ((double) i / 255.0);
|
||||
gamma_correction = 1.0 / gamma;
|
||||
x = pow (x, (double) gamma_correction);
|
||||
if (x > 1.00) {
|
||||
x = 1.0;
|
||||
}
|
||||
|
||||
g = x * 65535.0;
|
||||
red_table [i] = (int)g;
|
||||
green_table [i] = (int)g;
|
||||
blue_table [i] = (int)g;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::traverse_prepared_textures
|
||||
// Access: Public
|
||||
// Description: Calls the indicated function on all
|
||||
// currently-prepared textures, or until the callback
|
||||
// function returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
|
||||
PreparedGraphicsObjects::Textures::const_iterator ti;
|
||||
for (ti = _prepared_objects->_prepared_textures.begin();
|
||||
ti != _prepared_objects->_prepared_textures.end();
|
||||
++ti) {
|
||||
bool bResult=(*pertex_callbackfn)(*ti,callback_arg);
|
||||
if(!bResult)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::enable_lighting
|
||||
// Access: Protected, Virtual
|
||||
@ -2095,104 +2200,20 @@ get_untextured_state() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::traverse_prepared_textures
|
||||
// Access: Public
|
||||
// Description: Calls the indicated function on all
|
||||
// currently-prepared textures, or until the callback
|
||||
// function returns false.
|
||||
// Function: GraphicsStateGuardian::async_reload_texture
|
||||
// Access: Protected
|
||||
// Description: Should be called when a texture is encountered that
|
||||
// needs to have its RAM image reloaded, and
|
||||
// get_incomplete_render() is true. This will fire off
|
||||
// a thread on the current Loader object that will
|
||||
// request the texture to load its image. The image
|
||||
// will be available at some point in the future (no
|
||||
// event will be generated).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
|
||||
PreparedGraphicsObjects::Textures::const_iterator ti;
|
||||
for (ti = _prepared_objects->_prepared_textures.begin();
|
||||
ti != _prepared_objects->_prepared_textures.end();
|
||||
++ti) {
|
||||
bool bResult=(*pertex_callbackfn)(*ti,callback_arg);
|
||||
if(!bResult)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::calc_projection_mat
|
||||
// Access: Public, Virtual
|
||||
// Description: Given a lens, this function calculates the appropriate
|
||||
// projection matrix for this gsg. The result depends
|
||||
// on the peculiarities of the rendering API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) GraphicsStateGuardian::
|
||||
calc_projection_mat(const Lens *lens) {
|
||||
if (lens == (Lens *)NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!lens->is_linear()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TransformState::make_identity();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::set_gamma
|
||||
// Access: Published, Virtual
|
||||
// Description: Set gamma. Returns true on success.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
set_gamma(float gamma) {
|
||||
_gamma = gamma;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::create_gamma_table
|
||||
// Access: Published
|
||||
// Description: Get the current gamma setting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float GraphicsStateGuardian::
|
||||
get_gamma(float gamma) {
|
||||
return _gamma;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::restore_gamma
|
||||
// Access: Published, Virtual
|
||||
// Description: Restore original gamma setting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
restore_gamma() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::create_gamma_table
|
||||
// Access: Public, Static
|
||||
// Description: Create a gamma table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
create_gamma_table (float gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
|
||||
int i;
|
||||
|
||||
if (gamma <= 0.0) {
|
||||
// avoid divide by zero and negative exponents
|
||||
gamma = 1.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
double g;
|
||||
double x;
|
||||
float gamma_correction;
|
||||
|
||||
x = ((double) i / 255.0);
|
||||
gamma_correction = 1.0 / gamma;
|
||||
x = pow (x, (double) gamma_correction);
|
||||
if (x > 1.00) {
|
||||
x = 1.0;
|
||||
}
|
||||
|
||||
g = x * 65535.0;
|
||||
red_table [i] = (int)g;
|
||||
green_table [i] = (int)g;
|
||||
blue_table [i] = (int)g;
|
||||
}
|
||||
async_reload_texture(TextureContext *tc) {
|
||||
nassertv(_loader != (Loader *)NULL);
|
||||
|
||||
PT(AsyncTask) request = new TextureReloadRequest(tc);
|
||||
_loader->load_async(request);
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "texture.h"
|
||||
#include "occlusionQueryContext.h"
|
||||
#include "stencilRenderStates.h"
|
||||
#include "loader.h"
|
||||
|
||||
class DrawableRegion;
|
||||
class GraphicsEngine;
|
||||
@ -90,6 +91,12 @@ PUBLISHED:
|
||||
INLINE bool is_valid() const;
|
||||
INLINE bool needs_reset() const;
|
||||
|
||||
INLINE void set_incomplete_render(bool incomplete_render);
|
||||
virtual INLINE bool get_incomplete_render() const;
|
||||
|
||||
INLINE void set_loader(Loader *loader);
|
||||
INLINE Loader *get_loader() const;
|
||||
|
||||
INLINE GraphicsPipe *get_pipe() const;
|
||||
INLINE GraphicsEngine *get_engine() const;
|
||||
INLINE const GraphicsThreadingModel &get_threading_model() const;
|
||||
@ -268,6 +275,8 @@ public:
|
||||
static void init_frame_pstats();
|
||||
#endif
|
||||
|
||||
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
|
||||
|
||||
protected:
|
||||
virtual void enable_lighting(bool enable);
|
||||
virtual void set_ambient_light(const Colorf &color);
|
||||
@ -293,6 +302,8 @@ protected:
|
||||
static CPT(RenderState) get_unclipped_state();
|
||||
static CPT(RenderState) get_untextured_state();
|
||||
|
||||
void async_reload_texture(TextureContext *tc);
|
||||
|
||||
protected:
|
||||
PT(SceneSetup) _scene_null;
|
||||
PT(SceneSetup) _scene_setup;
|
||||
@ -353,6 +364,8 @@ protected:
|
||||
bool _is_valid;
|
||||
bool _closing_gsg;
|
||||
bool _active;
|
||||
bool _incomplete_render;
|
||||
PT(Loader) _loader;
|
||||
|
||||
PT(PreparedGraphicsObjects) _prepared_objects;
|
||||
|
||||
@ -482,9 +495,6 @@ private:
|
||||
GraphicsEngine *_engine;
|
||||
GraphicsThreadingModel _threading_model;
|
||||
|
||||
public:
|
||||
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -2377,7 +2377,7 @@ bool vertex_buffer_page_in_function (LruPage *lru_page)
|
||||
Not sure if this is the correct thing to do. Can we return false
|
||||
from the page_in function? Will we get called again next frame if
|
||||
we do?
|
||||
if (allow_incomplete_render) {
|
||||
if (_incomplete_render) {
|
||||
// Check if the data is resident before continuing.
|
||||
const unsigned char *data_pointer = reader->get_read_pointer(false);
|
||||
if (data_pointer == NULL) {
|
||||
@ -2431,7 +2431,7 @@ bool index_buffer_page_in_function (LruPage *lru_page)
|
||||
Not sure if this is the correct thing to do. Can we return false
|
||||
from the page_in function? Will we get called again next frame if
|
||||
we do?
|
||||
if (allow_incomplete_render) {
|
||||
if (_incomplete_render) {
|
||||
// Check if the data is resident before continuing.
|
||||
const unsigned char *data_pointer = reader.get_read_pointer(false);
|
||||
if (data_pointer == NULL) {
|
||||
|
@ -290,7 +290,6 @@ CLP(GraphicsStateGuardian)::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
reset() {
|
||||
cerr << "begin reset\n";
|
||||
free_pointers();
|
||||
GraphicsStateGuardian::reset();
|
||||
|
||||
@ -1332,7 +1331,6 @@ reset() {
|
||||
// Now that the GSG has been initialized, make it available for
|
||||
// optimizations.
|
||||
add_gsg(this);
|
||||
cerr << "end reset()\n";
|
||||
}
|
||||
|
||||
|
||||
@ -6393,7 +6391,10 @@ update_standard_texture_bindings() {
|
||||
}
|
||||
GLP(Enable)(target);
|
||||
|
||||
apply_texture(tc);
|
||||
if (!apply_texture(tc)) {
|
||||
GLP(Disable)(target);
|
||||
break;
|
||||
}
|
||||
|
||||
if (stage->involves_color_scale() && _color_scale_enabled) {
|
||||
Colorf color = stage->get_color();
|
||||
@ -6939,14 +6940,14 @@ specify_texture(Texture *tex) {
|
||||
// texture, and makes it the current texture available
|
||||
// for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
apply_texture(TextureContext *tc) {
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
|
||||
gtc->set_active(true);
|
||||
GLenum target = get_texture_target(gtc->get_texture()->get_texture_type());
|
||||
if (target == GL_NONE) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
GLP(BindTexture)(target, gtc->_index);
|
||||
|
||||
@ -6954,8 +6955,12 @@ apply_texture(TextureContext *tc) {
|
||||
// If the texture image was modified, reload the texture. This
|
||||
// means we also re-specify the properties for good measure.
|
||||
specify_texture(gtc->get_texture());
|
||||
upload_texture(gtc);
|
||||
gtc->mark_loaded();
|
||||
bool okflag = upload_texture(gtc);
|
||||
if (!okflag) {
|
||||
GLCAT.error()
|
||||
<< "Could not load " << *gtc->get_texture() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (gtc->was_properties_modified()) {
|
||||
// If only the properties have been modified, we don't necessarily
|
||||
@ -6965,6 +6970,7 @@ apply_texture(TextureContext *tc) {
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -6980,6 +6986,21 @@ bool CLP(GraphicsStateGuardian)::
|
||||
upload_texture(CLP(TextureContext) *gtc) {
|
||||
Texture *tex = gtc->get_texture();
|
||||
|
||||
if (_incomplete_render &&
|
||||
!tex->has_ram_image() && tex->might_have_ram_image() &&
|
||||
tex->has_simple_ram_image() &&
|
||||
!_loader.is_null()) {
|
||||
// If we don't have the texture data right now, go get it, but in
|
||||
// the meantime load a temporary simple image in its place.
|
||||
async_reload_texture(gtc);
|
||||
if (!tex->has_ram_image()) {
|
||||
if (gtc->was_simple_image_modified()) {
|
||||
return upload_simple_texture(gtc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CPTA_uchar image = tex->get_ram_image();
|
||||
|
||||
Texture::CompressionMode image_compression;
|
||||
@ -7139,6 +7160,7 @@ upload_texture(CLP(TextureContext) *gtc) {
|
||||
#endif
|
||||
|
||||
tex->texture_uploaded();
|
||||
gtc->mark_loaded();
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
@ -7462,6 +7484,68 @@ upload_texture_image(CLP(TextureContext) *gtc,
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::upload_simple_texture
|
||||
// Access: Protected
|
||||
// Description: This is used as a standin for upload_texture
|
||||
// when the texture in question is unavailable (e.g. it
|
||||
// hasn't yet been loaded from disk). Until the texture
|
||||
// image itself becomes available, we will render the
|
||||
// texture's "simple" image--a sharply reduced version
|
||||
// of the same texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
upload_simple_texture(CLP(TextureContext) *gtc) {
|
||||
report_my_gl_errors();
|
||||
|
||||
PStatTimer timer(_load_texture_pcollector);
|
||||
Texture *tex = gtc->get_texture();
|
||||
nassertr(tex != (Texture *)NULL, false);
|
||||
|
||||
int internal_format = GL_RGBA;
|
||||
int external_format = GL_BGRA;
|
||||
|
||||
const unsigned char *image_ptr = tex->get_simple_ram_image();
|
||||
if (image_ptr == (const unsigned char *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t image_size = tex->get_simple_ram_image_size();
|
||||
PTA_uchar bgr_image;
|
||||
if (!_supports_bgr) {
|
||||
// If the GL doesn't claim to support BGR, we may have to reverse
|
||||
// the component ordering of the image.
|
||||
external_format = GL_RGBA;
|
||||
image_ptr = fix_component_ordering(bgr_image, image_ptr, image_size,
|
||||
external_format, tex);
|
||||
}
|
||||
|
||||
int width = tex->get_simple_x_size();
|
||||
int height = tex->get_simple_y_size();
|
||||
int component_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "loading simple image for " << tex->get_name() << "\n";
|
||||
}
|
||||
|
||||
// Turn off mipmaps for the simple texture.
|
||||
if (tex->uses_mipmaps()) {
|
||||
if (is_at_least_version(1, 2)) {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format,
|
||||
width, height, 0,
|
||||
external_format, component_type, image_ptr);
|
||||
|
||||
gtc->mark_simple_loaded();
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::get_texture_memory_size
|
||||
// Access: Protected
|
||||
|
@ -323,7 +323,7 @@ protected:
|
||||
|
||||
void do_auto_rescale_normal();
|
||||
void specify_texture(Texture *tex);
|
||||
void apply_texture(TextureContext *tc);
|
||||
bool apply_texture(TextureContext *tc);
|
||||
bool upload_texture(CLP(TextureContext) *gtc);
|
||||
bool upload_texture_image(CLP(TextureContext) *gtc,
|
||||
bool uses_mipmaps, int mipmap_bias,
|
||||
@ -331,7 +331,8 @@ protected:
|
||||
GLint internal_format, GLint external_format,
|
||||
GLenum component_type,
|
||||
bool one_page_only, int z,
|
||||
Texture::CompressionMode image_compression);
|
||||
Texture::CompressionMode image_compression);
|
||||
bool upload_simple_texture(CLP(TextureContext) *gtc);
|
||||
|
||||
size_t get_texture_memory_size(Texture *tex);
|
||||
void check_nonresident_texture(BufferContextChain &chain);
|
||||
|
@ -108,6 +108,15 @@ ConfigVariableBool preload_textures
|
||||
"wasted memory from Textures that are created but never used "
|
||||
"to render."));
|
||||
|
||||
ConfigVariableBool preload_simple_textures
|
||||
("preload-simple-textures", false,
|
||||
PRC_DESC("When this is true, every texture image will have a simple "
|
||||
"image generated for it at load time. (Normally, textures "
|
||||
"get a simple image at egg2bam time.) This slows the initial "
|
||||
"loading time of textures, but allows you to take advantage "
|
||||
"of gsg::set_incomplete_render() to load textures on-the-fly "
|
||||
"in a sub-thread."));
|
||||
|
||||
ConfigVariableBool compressed_textures
|
||||
("compressed-textures", false,
|
||||
PRC_DESC("Set this to true to compress textures as they are loaded into "
|
||||
@ -253,6 +262,31 @@ ConfigVariableBool textures_auto_power_2
|
||||
"you then open a second window that doesn't support the same "
|
||||
"capabilities, it will have no choice but to print an error message."));
|
||||
|
||||
ConfigVariableBool textures_header_only
|
||||
("textures-header-only", false,
|
||||
PRC_DESC("If this is true, texture images will not actually be loaded from "
|
||||
"disk, but the image header information will be consulted to verify "
|
||||
"number of channels and so forth. The texture images themselves "
|
||||
"will be generated in a default blue color."));
|
||||
|
||||
ConfigVariableInt simple_image_size
|
||||
("simple-image-size", "16 16",
|
||||
PRC_DESC("This is an x y pair that specifies the maximum size of an "
|
||||
"automatically-generated "
|
||||
"texture simple image. The simple image can displayed before "
|
||||
"the texture has been loaded from disk."));
|
||||
|
||||
ConfigVariableDouble simple_image_threshold
|
||||
("simple-image-threshold", 0.1,
|
||||
PRC_DESC("This is a value that indicates how closely a texture's "
|
||||
"generated simple "
|
||||
"image should approximate the original image. The smaller the "
|
||||
"number, the closer the match; small numbers will result in "
|
||||
"simple images close to the maximum size specified by "
|
||||
"simple-image-size. Larger numbers will result in smaller "
|
||||
"simple images. Generally the value should be considerably "
|
||||
"less than 1."));
|
||||
|
||||
ConfigVariableEnum<ShaderUtilization> shader_utilization
|
||||
("shader-utilization", SUT_none,
|
||||
PRC_DESC("At times, panda may generate shaders. This variable controls what "
|
||||
@ -270,14 +304,6 @@ ConfigVariableBool shader_auto_utilization
|
||||
"you then open a second window that doesn't support the same "
|
||||
"capabilities, it will have no choice but to print an error message."));
|
||||
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool textures_header_only;
|
||||
ConfigVariableBool textures_header_only
|
||||
("textures-header-only", false,
|
||||
PRC_DESC("If this is true, texture images will not actually be loaded from "
|
||||
"disk, but the image header information will be consulted to verify "
|
||||
"number of channels and so forth. The texture images themselves "
|
||||
"will be generated in a default blue color."));
|
||||
|
||||
ConfigVariableInt geom_cache_size
|
||||
("geom-cache-size", 5000,
|
||||
PRC_DESC("Specifies the maximum number of entries in the cache "
|
||||
|
@ -52,6 +52,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableList exclude_texture_scale;
|
||||
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool keep_texture_ram;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool preload_textures;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool preload_simple_textures;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool compressed_textures;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_arrays;
|
||||
@ -69,6 +70,8 @@ extern EXPCL_PANDA_GOBJ ConfigVariableEnum<AutoTextureScale> textures_power_2;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableEnum<AutoTextureScale> textures_square;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool textures_auto_power_2;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool textures_header_only;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt simple_image_size;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableDouble simple_image_threshold;
|
||||
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableEnum<ShaderUtilization> shader_utilization;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool shader_auto_utilization;
|
||||
|
@ -194,6 +194,17 @@ release_texture(TextureContext *tc) {
|
||||
_released_textures.insert(tc);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PreparedGraphicsObjects::release_texture
|
||||
// Access: Public
|
||||
// Description: Releases a texture if it has already been prepared,
|
||||
// or removes it from the preparation queue.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PreparedGraphicsObjects::
|
||||
release_texture(Texture *tex) {
|
||||
tex->release(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PreparedGraphicsObjects::release_all_textures
|
||||
// Access: Public
|
||||
|
@ -71,6 +71,7 @@ PUBLISHED:
|
||||
bool dequeue_texture(Texture *tex);
|
||||
bool is_texture_prepared(const Texture *tex) const;
|
||||
void release_texture(TextureContext *tc);
|
||||
void release_texture(Texture *tex);
|
||||
int release_all_textures();
|
||||
int get_num_queued_textures() const;
|
||||
int get_num_prepared_textures() const;
|
||||
|
@ -129,9 +129,10 @@ setup_cube_map(int size, ComponentType component_type,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
read(const Filename &fullpath) {
|
||||
ReMutexHolder holder(_lock);
|
||||
clear();
|
||||
return do_read(fullpath, Filename(), 0, 0, 0, 0, false, false,
|
||||
!preload_textures, NULL);
|
||||
!preload_textures && !preload_simple_textures, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -148,9 +149,11 @@ read(const Filename &fullpath) {
|
||||
INLINE bool Texture::
|
||||
read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
int primary_file_num_channels, int alpha_file_channel) {
|
||||
ReMutexHolder holder(_lock);
|
||||
clear();
|
||||
return do_read(fullpath, alpha_fullpath, primary_file_num_channels,
|
||||
alpha_file_channel, 0, 0, false, false, !preload_textures,
|
||||
alpha_file_channel, 0, 0, false, false,
|
||||
!preload_textures && !preload_simple_textures,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@ -167,10 +170,11 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
INLINE bool Texture::
|
||||
read(const Filename &fullpath, int z, int n,
|
||||
bool read_pages, bool read_mipmaps) {
|
||||
ReMutexHolder holder(_lock);
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
return do_read(fullpath, Filename(), 0, 0, z, n, read_pages, read_mipmaps,
|
||||
!preload_textures, NULL);
|
||||
!preload_textures && !preload_simple_textures, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -247,11 +251,12 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
int primary_file_num_channels, int alpha_file_channel,
|
||||
int z, int n, bool read_pages, bool read_mipmaps,
|
||||
BamCacheRecord *record) {
|
||||
ReMutexHolder holder(_lock);
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
return do_read(fullpath, alpha_fullpath, primary_file_num_channels,
|
||||
alpha_file_channel, z, n, read_pages, read_mipmaps,
|
||||
!preload_textures, record);
|
||||
!preload_textures && !preload_simple_textures, record);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -261,6 +266,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
write(const Filename &fullpath) {
|
||||
ReMutexHolder holder(_lock);
|
||||
return do_write(fullpath, 0, 0, false, false);
|
||||
}
|
||||
|
||||
@ -321,6 +327,7 @@ write(const Filename &fullpath) {
|
||||
INLINE bool Texture::
|
||||
write(const Filename &fullpath, int z, int n,
|
||||
bool write_pages, bool write_mipmaps) {
|
||||
ReMutexHolder holder(_lock);
|
||||
return do_write(fullpath, z, n, write_pages, write_mipmaps);
|
||||
}
|
||||
|
||||
@ -331,6 +338,7 @@ write(const Filename &fullpath, int z, int n,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
load(const PNMImage &pnmimage) {
|
||||
ReMutexHolder holder(_lock);
|
||||
clear();
|
||||
return do_load_one(pnmimage, get_name(), 0, 0);
|
||||
}
|
||||
@ -343,6 +351,7 @@ load(const PNMImage &pnmimage) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
load(const PNMImage &pnmimage, int z, int n) {
|
||||
ReMutexHolder holder(_lock);
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
return do_load_one(pnmimage, get_name(), z, n);
|
||||
@ -356,6 +365,7 @@ load(const PNMImage &pnmimage, int z, int n) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
store(PNMImage &pnmimage) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return do_store_one(pnmimage, 0, 0);
|
||||
}
|
||||
|
||||
@ -367,6 +377,7 @@ store(PNMImage &pnmimage) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
store(PNMImage &pnmimage, int z, int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return do_store_one(pnmimage, z, n);
|
||||
}
|
||||
|
||||
@ -378,6 +389,7 @@ store(PNMImage &pnmimage, int z, int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_filename() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_filename.empty();
|
||||
}
|
||||
|
||||
@ -390,6 +402,7 @@ has_filename() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &Texture::
|
||||
get_filename() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _filename;
|
||||
}
|
||||
|
||||
@ -401,6 +414,7 @@ get_filename() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_alpha_filename() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_alpha_filename.empty();
|
||||
}
|
||||
|
||||
@ -414,6 +428,7 @@ has_alpha_filename() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &Texture::
|
||||
get_alpha_filename() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _alpha_filename;
|
||||
}
|
||||
|
||||
@ -425,6 +440,7 @@ get_alpha_filename() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_fullpath() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_fullpath.empty();
|
||||
}
|
||||
|
||||
@ -437,6 +453,7 @@ has_fullpath() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &Texture::
|
||||
get_fullpath() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _fullpath;
|
||||
}
|
||||
|
||||
@ -448,6 +465,7 @@ get_fullpath() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_alpha_fullpath() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_alpha_fullpath.empty();
|
||||
}
|
||||
|
||||
@ -461,6 +479,7 @@ has_alpha_fullpath() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &Texture::
|
||||
get_alpha_fullpath() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _alpha_fullpath;
|
||||
}
|
||||
|
||||
@ -546,6 +565,7 @@ get_pad_z_size() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_pad_size(int x, int y, int z) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (x > _x_size) x = _x_size;
|
||||
if (y > _y_size) y = _y_size;
|
||||
if (z > _z_size) z = _z_size;
|
||||
@ -770,6 +790,7 @@ get_quality_level() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
might_have_ram_image() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return (has_ram_image() || has_filename());
|
||||
}
|
||||
|
||||
@ -781,6 +802,7 @@ might_have_ram_image() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_ram_image_size() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_ram_images.empty()) {
|
||||
return 0;
|
||||
}
|
||||
@ -801,6 +823,7 @@ get_ram_image_size() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_ram_page_size() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_ram_image_compression == CM_off || _ram_images.empty()) {
|
||||
return get_expected_ram_page_size();
|
||||
} else {
|
||||
@ -817,6 +840,7 @@ get_ram_page_size() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_expected_ram_image_size() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return get_expected_ram_page_size() * (size_t)_z_size;
|
||||
}
|
||||
|
||||
@ -830,6 +854,7 @@ get_expected_ram_image_size() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_expected_ram_page_size() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return (size_t)(_x_size * _y_size * _num_components * _component_width);
|
||||
}
|
||||
|
||||
@ -860,6 +885,7 @@ get_ram_image_compression() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_uchar Texture::
|
||||
modify_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
do_modify_ram_image();
|
||||
++_image_modified;
|
||||
return _ram_images[0]._image;
|
||||
@ -876,6 +902,7 @@ modify_ram_image() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_uchar Texture::
|
||||
make_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
++_image_modified;
|
||||
do_make_ram_image();
|
||||
return _ram_images[0]._image;
|
||||
@ -911,6 +938,7 @@ set_keep_ram_image(bool keep_ram_image) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Texture::
|
||||
get_num_ram_mipmap_images() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _ram_images.size();
|
||||
}
|
||||
|
||||
@ -926,6 +954,7 @@ get_num_ram_mipmap_images() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_ram_mipmap_image(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return (n >= 0 && n < (int)_ram_images.size() && !_ram_images[n]._image.empty());
|
||||
}
|
||||
|
||||
@ -938,6 +967,7 @@ has_ram_mipmap_image(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_ram_mipmap_image_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (n >= 0 && n < (int)_ram_images.size()) {
|
||||
return _ram_images[n]._image.size();
|
||||
}
|
||||
@ -959,6 +989,7 @@ get_ram_mipmap_image_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_ram_mipmap_page_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_ram_image_compression != CM_off) {
|
||||
if (n >= 0 && n < (int)_ram_images.size()) {
|
||||
return _ram_images[n]._page_size;
|
||||
@ -978,6 +1009,7 @@ get_ram_mipmap_page_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_expected_ram_mipmap_image_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return get_expected_ram_mipmap_page_size(n) * (size_t)get_expected_mipmap_z_size(n);
|
||||
}
|
||||
|
||||
@ -991,6 +1023,7 @@ get_expected_ram_mipmap_image_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_expected_ram_mipmap_page_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return (size_t)(get_expected_mipmap_x_size(n) * get_expected_mipmap_y_size(n) * _num_components * _component_width);
|
||||
}
|
||||
|
||||
@ -1006,11 +1039,79 @@ get_expected_ram_mipmap_page_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_uchar Texture::
|
||||
modify_ram_mipmap_image(int n) {
|
||||
ReMutexHolder holder(_lock);
|
||||
do_modify_ram_mipmap_image(n);
|
||||
++_image_modified;
|
||||
return _ram_images[n]._image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_simple_x_size
|
||||
// Access: Published
|
||||
// Description: Returns the width of the "simple" image in texels.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Texture::
|
||||
get_simple_x_size() const {
|
||||
return _simple_x_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_simple_y_size
|
||||
// Access: Published
|
||||
// Description: Returns the height of the "simple" image in texels.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Texture::
|
||||
get_simple_y_size() const {
|
||||
return _simple_y_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::has_simple_ram_image
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns true if the Texture has a "simple" image
|
||||
// available in main RAM.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
has_simple_ram_image() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_simple_ram_image._image.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_simple_ram_image_size
|
||||
// Access: Published
|
||||
// Description: Returns the number of bytes used by the "simple"
|
||||
// image, or 0 if there is no simple image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t Texture::
|
||||
get_simple_ram_image_size() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _simple_ram_image._image.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_simple_ram_image
|
||||
// Access: Published
|
||||
// Description: Returns the image data associated with the "simple"
|
||||
// texture image. This is provided for some textures as
|
||||
// an option to display while the main texture image is
|
||||
// being loaded from disk.
|
||||
//
|
||||
// Unlike get_ram_image(), this function will always
|
||||
// return immediately. Either the simple image is
|
||||
// available, or it is not.
|
||||
//
|
||||
// The "simple" image is always 4 components, 1 byte
|
||||
// each, regardless of the parameters of the full
|
||||
// texture. The simple image is only supported for
|
||||
// ordinary 2-d textures.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPTA_uchar Texture::
|
||||
get_simple_ram_image() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _simple_ram_image._image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_properties_modified
|
||||
// Access: Published
|
||||
@ -1035,6 +1136,18 @@ get_image_modified() const {
|
||||
return _image_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_simple_image_modified
|
||||
// Access: Published
|
||||
// Description: Returns a sequence number which is guaranteed to
|
||||
// change at least every time the texture's "simple"
|
||||
// image data is modified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE UpdateSeq Texture::
|
||||
get_simple_image_modified() const {
|
||||
return _simple_image_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::set_filename
|
||||
// Access: Published
|
||||
@ -1050,6 +1163,7 @@ get_image_modified() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_filename(const Filename &filename) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_filename = filename;
|
||||
}
|
||||
|
||||
@ -1061,6 +1175,7 @@ set_filename(const Filename &filename) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
clear_filename() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_filename = Filename();
|
||||
}
|
||||
|
||||
@ -1082,6 +1197,7 @@ clear_filename() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_alpha_filename(const Filename &alpha_filename) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_alpha_filename = alpha_filename;
|
||||
}
|
||||
|
||||
@ -1093,6 +1209,7 @@ set_alpha_filename(const Filename &alpha_filename) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
clear_alpha_filename() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_alpha_filename = Filename();
|
||||
}
|
||||
|
||||
@ -1106,6 +1223,7 @@ clear_alpha_filename() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_fullpath(const Filename &fullpath) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_fullpath = fullpath;
|
||||
}
|
||||
|
||||
@ -1117,6 +1235,7 @@ set_fullpath(const Filename &fullpath) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
clear_fullpath() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_fullpath = Filename();
|
||||
}
|
||||
|
||||
@ -1131,6 +1250,7 @@ clear_fullpath() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_alpha_fullpath(const Filename &alpha_fullpath) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_alpha_fullpath = alpha_fullpath;
|
||||
}
|
||||
|
||||
@ -1142,6 +1262,7 @@ set_alpha_fullpath(const Filename &alpha_fullpath) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
clear_alpha_fullpath() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_alpha_fullpath = Filename();
|
||||
}
|
||||
|
||||
@ -1154,6 +1275,7 @@ clear_alpha_fullpath() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_x_size(int x_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_x_size != x_size) {
|
||||
_x_size = x_size;
|
||||
++_image_modified;
|
||||
@ -1171,6 +1293,7 @@ set_x_size(int x_size) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_y_size(int y_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_y_size != y_size) {
|
||||
nassertv(_texture_type != Texture::TT_1d_texture || y_size == 1);
|
||||
_y_size = y_size;
|
||||
@ -1189,6 +1312,7 @@ set_y_size(int y_size) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Texture::
|
||||
set_z_size(int z_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_z_size != z_size) {
|
||||
nassertv(_texture_type == Texture::TT_3d_texture ||
|
||||
(_texture_type == Texture::TT_cube_map && z_size == 6) ||
|
||||
|
@ -96,6 +96,10 @@ Texture(const string &name) :
|
||||
_has_read_pages = false;
|
||||
_has_read_mipmaps = false;
|
||||
_num_mipmap_levels_read = 0;
|
||||
|
||||
_simple_x_size = 0;
|
||||
_simple_y_size = 0;
|
||||
_simple_ram_image._page_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -105,44 +109,12 @@ Texture(const string &name) :
|
||||
// an existing Texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Texture::
|
||||
Texture(const Texture ©) :
|
||||
Namable(copy),
|
||||
_filename(copy._filename),
|
||||
_alpha_filename(copy._alpha_filename),
|
||||
_fullpath(copy._fullpath),
|
||||
_alpha_fullpath(copy._alpha_fullpath),
|
||||
_primary_file_num_channels(copy._primary_file_num_channels),
|
||||
_alpha_file_channel(copy._alpha_file_channel),
|
||||
_x_size(copy._x_size),
|
||||
_y_size(copy._y_size),
|
||||
_z_size(copy._z_size),
|
||||
_num_components(copy._num_components),
|
||||
_component_width(copy._component_width),
|
||||
_texture_type(copy._texture_type),
|
||||
_format(copy._format),
|
||||
_component_type(copy._component_type),
|
||||
_loaded_from_image(copy._loaded_from_image),
|
||||
_loaded_from_txo(copy._loaded_from_txo),
|
||||
_has_read_pages(copy._has_read_pages),
|
||||
_has_read_mipmaps(copy._has_read_mipmaps),
|
||||
_num_mipmap_levels_read(copy._num_mipmap_levels_read),
|
||||
_wrap_u(copy._wrap_u),
|
||||
_wrap_v(copy._wrap_v),
|
||||
_wrap_w(copy._wrap_w),
|
||||
_minfilter(copy._minfilter),
|
||||
_magfilter(copy._magfilter),
|
||||
_anisotropic_degree(copy._anisotropic_degree),
|
||||
_keep_ram_image(copy._keep_ram_image),
|
||||
_border_color(copy._border_color),
|
||||
_compression(copy._compression),
|
||||
_match_framebuffer_format(copy._match_framebuffer_format),
|
||||
_quality_level(copy._quality_level),
|
||||
_pad_x_size(copy._pad_x_size),
|
||||
_pad_y_size(copy._pad_y_size),
|
||||
_pad_z_size(copy._pad_z_size),
|
||||
_ram_image_compression(copy._ram_image_compression),
|
||||
_ram_images(copy._ram_images)
|
||||
{
|
||||
Texture(const Texture ©) {
|
||||
_has_read_pages = false;
|
||||
_has_read_mipmaps = false;
|
||||
_num_mipmap_levels_read = 0;
|
||||
|
||||
operator = (copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -154,6 +126,10 @@ Texture(const Texture ©) :
|
||||
void Texture::
|
||||
operator = (const Texture ©) {
|
||||
Namable::operator = (copy);
|
||||
|
||||
ReMutexHolder holder(_lock);
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
|
||||
_filename = copy._filename;
|
||||
_alpha_filename = copy._alpha_filename;
|
||||
if (!copy._fullpath.empty()) {
|
||||
@ -190,8 +166,13 @@ operator = (const Texture ©) {
|
||||
_quality_level = copy._quality_level;
|
||||
_ram_image_compression = copy._ram_image_compression;
|
||||
_ram_images = copy._ram_images;
|
||||
_simple_x_size = copy._simple_x_size;
|
||||
_simple_y_size = copy._simple_y_size;
|
||||
_simple_ram_image = copy._simple_ram_image;
|
||||
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
++_simple_image_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -245,6 +226,7 @@ void Texture::
|
||||
setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||
int z_size, Texture::ComponentType component_type,
|
||||
Texture::Format format) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (texture_type == TT_cube_map) {
|
||||
// Cube maps must always consist of six square images.
|
||||
nassertv(x_size == y_size && z_size == 6);
|
||||
@ -256,6 +238,9 @@ setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||
_wrap_v = WM_clamp;
|
||||
_wrap_w = WM_clamp;
|
||||
}
|
||||
if (texture_type != TT_2d_texture) {
|
||||
clear_simple_ram_image();
|
||||
}
|
||||
|
||||
_texture_type = texture_type;
|
||||
_x_size = x_size;
|
||||
@ -284,6 +269,7 @@ setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
generate_normalization_cube_map(int size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
setup_cube_map(size, T_unsigned_byte, F_rgb);
|
||||
PTA_uchar image = make_ram_image();
|
||||
_keep_ram_image = true;
|
||||
@ -385,6 +371,7 @@ generate_normalization_cube_map(int size) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
generate_alpha_scale_map() {
|
||||
ReMutexHolder holder(_lock);
|
||||
setup_1d_texture(256, T_unsigned_byte, F_alpha);
|
||||
set_wrap_u(WM_clamp);
|
||||
set_minfilter(FT_nearest);
|
||||
@ -416,6 +403,7 @@ generate_alpha_scale_map() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t Texture::
|
||||
estimate_texture_memory() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
size_t pixels = get_x_size() * get_y_size();
|
||||
|
||||
size_t bpp = 4;
|
||||
@ -487,6 +475,7 @@ estimate_texture_memory() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_aux_data(const string &key, TypedReferenceCount *aux_data) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_aux_data[key] = aux_data;
|
||||
}
|
||||
|
||||
@ -498,6 +487,7 @@ set_aux_data(const string &key, TypedReferenceCount *aux_data) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
clear_aux_data(const string &key) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_aux_data.erase(key);
|
||||
}
|
||||
|
||||
@ -510,6 +500,7 @@ clear_aux_data(const string &key) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedReferenceCount *Texture::
|
||||
get_aux_data(const string &key) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
AuxData::const_iterator di;
|
||||
di = _aux_data.find(key);
|
||||
if (di != _aux_data.end()) {
|
||||
@ -529,6 +520,7 @@ get_aux_data(const string &key) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
read_txo(istream &in, const string &filename) {
|
||||
ReMutexHolder holder(_lock);
|
||||
DatagramInputFile din;
|
||||
|
||||
if (!din.open(in)) {
|
||||
@ -605,6 +597,7 @@ read_txo(istream &in, const string &filename) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
write_txo(ostream &out, const string &filename) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
DatagramOutputFile dout;
|
||||
|
||||
if (!dout.open(out)) {
|
||||
@ -651,6 +644,7 @@ write_txo(ostream &out, const string &filename) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
reload() {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_loaded_from_image && has_filename()) {
|
||||
reload_ram_image();
|
||||
++_image_modified;
|
||||
@ -671,6 +665,7 @@ reload() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Texture *Texture::
|
||||
load_related(const InternalName *suffix) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
RelatedTextures::const_iterator ti;
|
||||
ti = _related_textures.find(suffix);
|
||||
if (ti != _related_textures.end()) {
|
||||
@ -719,6 +714,7 @@ load_related(const InternalName *suffix) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_wrap_u(Texture::WrapMode wrap) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_wrap_u != wrap) {
|
||||
++_properties_modified;
|
||||
_wrap_u = wrap;
|
||||
@ -732,6 +728,7 @@ set_wrap_u(Texture::WrapMode wrap) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_wrap_v(Texture::WrapMode wrap) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_wrap_v != wrap) {
|
||||
++_properties_modified;
|
||||
_wrap_v = wrap;
|
||||
@ -745,6 +742,7 @@ set_wrap_v(Texture::WrapMode wrap) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_wrap_w(Texture::WrapMode wrap) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_wrap_w != wrap) {
|
||||
++_properties_modified;
|
||||
_wrap_w = wrap;
|
||||
@ -758,6 +756,7 @@ set_wrap_w(Texture::WrapMode wrap) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_minfilter(Texture::FilterType filter) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_minfilter != filter) {
|
||||
++_properties_modified;
|
||||
_minfilter = filter;
|
||||
@ -771,6 +770,7 @@ set_minfilter(Texture::FilterType filter) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_magfilter(Texture::FilterType filter) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_magfilter != filter) {
|
||||
++_properties_modified;
|
||||
_magfilter = filter;
|
||||
@ -788,6 +788,7 @@ set_magfilter(Texture::FilterType filter) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_anisotropic_degree(int anisotropic_degree) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_anisotropic_degree != anisotropic_degree) {
|
||||
++_properties_modified;
|
||||
_anisotropic_degree = anisotropic_degree;
|
||||
@ -804,6 +805,7 @@ set_anisotropic_degree(int anisotropic_degree) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_border_color(const Colorf &color) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_border_color != color) {
|
||||
++_properties_modified;
|
||||
_border_color = color;
|
||||
@ -831,6 +833,7 @@ set_border_color(const Colorf &color) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_compression(Texture::CompressionMode compression) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_compression != compression) {
|
||||
++_properties_modified;
|
||||
_compression = compression;
|
||||
@ -870,6 +873,7 @@ set_render_to_texture(bool render_to_texture) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_quality_level(Texture::QualityLevel quality_level) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_quality_level != quality_level) {
|
||||
++_properties_modified;
|
||||
_quality_level = quality_level;
|
||||
@ -888,6 +892,7 @@ set_quality_level(Texture::QualityLevel quality_level) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Texture::
|
||||
get_expected_num_mipmap_levels() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
int size = max(_x_size, max(_y_size, _z_size));
|
||||
int count = 1;
|
||||
while (size > 1) {
|
||||
@ -905,6 +910,7 @@ get_expected_num_mipmap_levels() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Texture::
|
||||
get_expected_mipmap_x_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
int size = max(_x_size, 1);
|
||||
while (n > 0 && size > 1) {
|
||||
size >>= 1;
|
||||
@ -921,6 +927,7 @@ get_expected_mipmap_x_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Texture::
|
||||
get_expected_mipmap_y_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
int size = max(_y_size, 1);
|
||||
while (n > 0 && size > 1) {
|
||||
size >>= 1;
|
||||
@ -937,6 +944,7 @@ get_expected_mipmap_y_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Texture::
|
||||
get_expected_mipmap_z_size(int n) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
// 3-D textures have a different number of pages per each mipmap
|
||||
// level. Other kinds of textures--especially, cube map
|
||||
// textures--always have the same.
|
||||
@ -983,6 +991,7 @@ get_expected_mipmap_z_size(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
has_ram_image() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return !_ram_images.empty() && !_ram_images[0]._image.empty();
|
||||
}
|
||||
|
||||
@ -1016,6 +1025,7 @@ has_ram_image() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPTA_uchar Texture::
|
||||
get_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_loaded_from_image && !has_ram_image() && has_filename()) {
|
||||
reload_ram_image();
|
||||
}
|
||||
@ -1040,6 +1050,7 @@ get_ram_image() {
|
||||
void Texture::
|
||||
set_ram_image(PTA_uchar image, Texture::CompressionMode compression,
|
||||
size_t page_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(compression != CM_default);
|
||||
nassertv(compression != CM_off || image.size() == get_expected_ram_image_size());
|
||||
if (_ram_images.empty()) {
|
||||
@ -1067,6 +1078,7 @@ set_ram_image(PTA_uchar image, Texture::CompressionMode compression,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
clear_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_ram_image_compression = CM_off;
|
||||
_ram_images.clear();
|
||||
}
|
||||
@ -1093,6 +1105,7 @@ get_keep_ram_image() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
has_all_ram_mipmap_images() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_ram_images.empty() || _ram_images[0]._image.empty()) {
|
||||
// If we don't even have a base image, the answer is no.
|
||||
return false;
|
||||
@ -1128,6 +1141,7 @@ has_all_ram_mipmap_images() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPTA_uchar Texture::
|
||||
get_ram_mipmap_image(int n) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (n < (int)_ram_images.size()) {
|
||||
return _ram_images[n]._image;
|
||||
}
|
||||
@ -1145,6 +1159,7 @@ get_ram_mipmap_image(int n) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PTA_uchar Texture::
|
||||
make_ram_mipmap_image(int n) {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertr(_ram_image_compression == CM_off, PTA_uchar(get_class_type()));
|
||||
|
||||
while (n >= (int)_ram_images.size()) {
|
||||
@ -1171,6 +1186,7 @@ make_ram_mipmap_image(int n) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(_ram_image_compression != CM_off || image.size() == get_expected_ram_mipmap_image_size(n));
|
||||
|
||||
while (n >= (int)_ram_images.size()) {
|
||||
@ -1197,6 +1213,7 @@ set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
clear_ram_mipmap_image(int n) {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (n >= (int)_ram_images.size()) {
|
||||
return;
|
||||
}
|
||||
@ -1212,6 +1229,7 @@ clear_ram_mipmap_image(int n) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
clear_ram_mipmap_images() {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (!_ram_images.empty()) {
|
||||
_ram_images.erase(_ram_images.begin() + 1, _ram_images.end());
|
||||
}
|
||||
@ -1232,6 +1250,7 @@ clear_ram_mipmap_images() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
generate_ram_mipmap_images() {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(has_ram_image());
|
||||
nassertv(get_ram_image_compression() == CM_off);
|
||||
nassertv(get_component_type() != T_float);
|
||||
@ -1274,6 +1293,142 @@ generate_ram_mipmap_images() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::set_simple_ram_image
|
||||
// Access: Published
|
||||
// Description: Replaces the internal "simple" texture image. This
|
||||
// can be used as an option to display while the main
|
||||
// texture image is being loaded from disk. It is
|
||||
// normally a very small image, 16x16 or smaller (and
|
||||
// maybe even 1x1), that is designed to give just enough
|
||||
// sense of color to serve as a placeholder until the
|
||||
// full texture is available.
|
||||
//
|
||||
// The "simple" image is always 4 components, 1 byte
|
||||
// each, regardless of the parameters of the full
|
||||
// texture. The simple image is only supported for
|
||||
// ordinary 2-d textures.
|
||||
//
|
||||
// Also see generate_simple_ram_image().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_simple_ram_image(PTA_uchar image, int x_size, int y_size) {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(get_texture_type() == TT_2d_texture);
|
||||
size_t expected_page_size = (size_t)(x_size * y_size * 4);
|
||||
nassertv(image.size() == expected_page_size);
|
||||
|
||||
_simple_x_size = x_size;
|
||||
_simple_y_size = y_size;
|
||||
_simple_ram_image._image = image;
|
||||
_simple_ram_image._page_size = image.size();
|
||||
_simple_image_date_generated = 0;
|
||||
++_simple_image_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::generate_simple_ram_image
|
||||
// Access: Published
|
||||
// Description: Computes the "simple" ram image by loading the main
|
||||
// RAM image, if it is not already available, and
|
||||
// reducing it to 16x16 or smaller. This may be an
|
||||
// expensive operation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
generate_simple_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
if (get_texture_type() != TT_2d_texture) {
|
||||
clear_simple_ram_image();
|
||||
return;
|
||||
}
|
||||
|
||||
PNMImage pnmimage;
|
||||
if (!store(pnmimage)) {
|
||||
clear_simple_ram_image();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start at the suggested size from the config file.
|
||||
int x_size = simple_image_size.get_word(0);
|
||||
int y_size = simple_image_size.get_word(1);
|
||||
|
||||
// Limit it to no larger than the source image, and also make it a
|
||||
// power of two.
|
||||
x_size = down_to_power_2(min(x_size, get_x_size()));
|
||||
y_size = down_to_power_2(min(y_size, get_y_size()));
|
||||
|
||||
// Generate a reduced image of that size.
|
||||
PNMImage scaled(x_size, y_size, pnmimage.get_num_channels());
|
||||
scaled.quick_filter_from(pnmimage);
|
||||
|
||||
// Make sure the reduced image has 4 components, by convention.
|
||||
if (!scaled.has_alpha()) {
|
||||
scaled.add_alpha();
|
||||
scaled.alpha_fill(1.0);
|
||||
}
|
||||
scaled.set_num_channels(4);
|
||||
|
||||
// Now see if we can go even smaller.
|
||||
bool did_anything;
|
||||
do {
|
||||
did_anything = false;
|
||||
|
||||
// Try to reduce X.
|
||||
if (x_size > 1) {
|
||||
int new_x_size = (x_size >> 1);
|
||||
PNMImage smaller(new_x_size, y_size, 4);
|
||||
smaller.quick_filter_from(scaled);
|
||||
PNMImage bigger(x_size, y_size, 4);
|
||||
bigger.quick_filter_from(smaller);
|
||||
|
||||
if (compare_images(scaled, bigger)) {
|
||||
scaled.take_from(smaller);
|
||||
x_size = new_x_size;
|
||||
did_anything = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to reduce Y.
|
||||
if (y_size > 1) {
|
||||
int new_y_size = (y_size >> 1);
|
||||
PNMImage smaller(x_size, new_y_size, 4);
|
||||
smaller.quick_filter_from(scaled);
|
||||
PNMImage bigger(x_size, y_size, 4);
|
||||
bigger.quick_filter_from(smaller);
|
||||
|
||||
if (compare_images(scaled, bigger)) {
|
||||
scaled.take_from(smaller);
|
||||
y_size = new_y_size;
|
||||
did_anything = true;
|
||||
}
|
||||
}
|
||||
} while (did_anything);
|
||||
|
||||
size_t expected_page_size = (size_t)(x_size * y_size * 4);
|
||||
PTA_uchar image = PTA_uchar::empty_array(expected_page_size, get_class_type());
|
||||
convert_from_pnmimage(image, expected_page_size, 0, scaled, 4, 1);
|
||||
|
||||
set_simple_ram_image(image, x_size, y_size);
|
||||
_simple_image_date_generated = (PN_int32)time(NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::clear_simple_ram_image
|
||||
// Access: Published
|
||||
// Description: Discards the current "simple" image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
clear_simple_ram_image() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_simple_x_size = 0;
|
||||
_simple_y_size = 0;
|
||||
_simple_ram_image._image.clear();
|
||||
_simple_ram_image._page_size = 0;
|
||||
_simple_image_date_generated = 0;
|
||||
++_simple_image_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::prepare
|
||||
// Access: Published
|
||||
@ -1300,6 +1455,7 @@ prepare(PreparedGraphicsObjects *prepared_objects) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
is_prepared(PreparedGraphicsObjects *prepared_objects) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
Contexts::const_iterator ci;
|
||||
ci = _contexts.find(prepared_objects);
|
||||
if (ci != _contexts.end()) {
|
||||
@ -1317,6 +1473,7 @@ is_prepared(PreparedGraphicsObjects *prepared_objects) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
release(PreparedGraphicsObjects *prepared_objects) {
|
||||
ReMutexHolder holder(_lock);
|
||||
Contexts::iterator ci;
|
||||
ci = _contexts.find(prepared_objects);
|
||||
if (ci != _contexts.end()) {
|
||||
@ -1342,6 +1499,7 @@ release(PreparedGraphicsObjects *prepared_objects) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Texture::
|
||||
release_all() {
|
||||
ReMutexHolder holder(_lock);
|
||||
// We have to traverse a copy of the _contexts list, because the
|
||||
// PreparedGraphicsObjects object will call clear_prepared() in response
|
||||
// to each release_texture(), and we don't want to be modifying the
|
||||
@ -1373,6 +1531,7 @@ release_all() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
write(ostream &out, int indent_level) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
indent(out, indent_level)
|
||||
<< get_type() << " " << get_name();
|
||||
if (!get_filename().empty()) {
|
||||
@ -1549,6 +1708,13 @@ write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level + 2)
|
||||
<< "no ram image\n";
|
||||
}
|
||||
|
||||
if (has_simple_ram_image()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "simple image: " << get_simple_x_size() << " x "
|
||||
<< get_simple_y_size() << ", "
|
||||
<< get_simple_ram_image_size() << " bytes\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1559,6 +1725,7 @@ write(ostream &out, int indent_level) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_format(Texture::Format format) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_format = format;
|
||||
|
||||
switch (_format) {
|
||||
@ -1606,6 +1773,7 @@ set_format(Texture::Format format) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
set_component_type(Texture::ComponentType component_type) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_component_type = component_type;
|
||||
|
||||
switch (component_type) {
|
||||
@ -1662,6 +1830,7 @@ is_mipmap(FilterType filter_type) {
|
||||
TextureContext *Texture::
|
||||
prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
GraphicsStateGuardianBase *gsg) {
|
||||
ReMutexHolder holder(_lock);
|
||||
Contexts::const_iterator ci;
|
||||
ci = _contexts.find(prepared_objects);
|
||||
if (ci != _contexts.end()) {
|
||||
@ -1689,6 +1858,7 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
texture_uploaded() {
|
||||
ReMutexHolder holder(_lock);
|
||||
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
|
||||
@ -2074,6 +2244,7 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
||||
return false;
|
||||
}
|
||||
Thread::consider_yield();
|
||||
}
|
||||
|
||||
PNMImage alpha_image;
|
||||
@ -2119,6 +2290,7 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
|
||||
return false;
|
||||
}
|
||||
Thread::consider_yield();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2156,6 +2328,7 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
alpha_image.get_num_channels(),
|
||||
alpha_image.get_maxval(), alpha_image.get_type());
|
||||
scaled.quick_filter_from(alpha_image);
|
||||
Thread::consider_yield();
|
||||
alpha_image = scaled;
|
||||
}
|
||||
}
|
||||
@ -2375,17 +2548,19 @@ do_load_one(const PNMImage &pnmimage, const string &name, int z, int n) {
|
||||
PNMImage scaled(x_size, y_size, pnmimage.get_num_channels(),
|
||||
pnmimage.get_maxval(), pnmimage.get_type());
|
||||
scaled.quick_filter_from(pnmimage);
|
||||
Thread::consider_yield();
|
||||
|
||||
convert_from_pnmimage(_ram_images[n]._image,
|
||||
get_expected_ram_mipmap_page_size(n), z,
|
||||
scaled);
|
||||
scaled, _num_components, _component_width);
|
||||
} else {
|
||||
// Now copy the pixel data from the PNMImage into our internal
|
||||
// _image component.
|
||||
convert_from_pnmimage(_ram_images[n]._image,
|
||||
get_expected_ram_mipmap_page_size(n), z,
|
||||
pnmimage);
|
||||
pnmimage, _num_components, _component_width);
|
||||
}
|
||||
Thread::consider_yield();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2408,6 +2583,7 @@ do_store_one(PNMImage &pnmimage, int z, int n) const {
|
||||
return convert_to_pnmimage(pnmimage,
|
||||
get_expected_mipmap_x_size(n),
|
||||
get_expected_mipmap_y_size(n),
|
||||
_num_components, _component_width,
|
||||
_ram_images[n]._image,
|
||||
get_ram_mipmap_page_size(n), z);
|
||||
}
|
||||
@ -2718,26 +2894,27 @@ reconsider_image_properties(int x_size, int y_size, int num_components,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::convert_from_pnmimage
|
||||
// Access: Private
|
||||
// Access: Private, Static
|
||||
// Description: Internal method to convert pixel data from the
|
||||
// indicated PNMImage into the given ram_image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
const PNMImage &pnmimage) {
|
||||
const PNMImage &pnmimage,
|
||||
int num_components, int component_width) {
|
||||
int x_size = pnmimage.get_x_size();
|
||||
int y_size = pnmimage.get_y_size();
|
||||
xelval maxval = pnmimage.get_maxval();
|
||||
|
||||
bool is_grayscale = (_num_components == 1 || _num_components == 2);
|
||||
bool has_alpha = (_num_components == 2 || _num_components == 4);
|
||||
bool is_grayscale = (num_components == 1 || num_components == 2);
|
||||
bool has_alpha = (num_components == 2 || num_components == 4);
|
||||
bool img_has_alpha = pnmimage.has_alpha();
|
||||
|
||||
int idx = page_size * z;
|
||||
nassertv(idx + page_size <= image.size());
|
||||
unsigned char *p = &image[idx];
|
||||
|
||||
if (maxval == 255) {
|
||||
if (maxval == 255 && component_width == 1) {
|
||||
// Most common case: one byte per pixel, and the source image
|
||||
// shows a maxval of 255. No scaling is necessary.
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
@ -2759,7 +2936,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
}
|
||||
}
|
||||
|
||||
} else if (maxval == 65535) {
|
||||
} else if (maxval == 65535 && component_width == 2) {
|
||||
// Another possible case: two bytes per pixel, and the source
|
||||
// image shows a maxval of 65535. Again, no scaling is necessary.
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
@ -2781,7 +2958,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
}
|
||||
}
|
||||
|
||||
} else if (maxval <= 255) {
|
||||
} else if (component_width == 1) {
|
||||
// A less common case: one byte per pixel, but the maxval is
|
||||
// something other than 255. In this case, we should scale the
|
||||
// pixel values up to the appropriate amount.
|
||||
@ -2806,7 +2983,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
} else { // component_width == 2
|
||||
// Another uncommon case: two bytes per pixel, and the maxval is
|
||||
// something other than 65535. Again, we must scale the pixel
|
||||
// values.
|
||||
@ -2837,14 +3014,15 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::convert_to_pnmimage
|
||||
// Access: Private
|
||||
// Access: Private, Static
|
||||
// Description: Internal method to convert pixel data to the
|
||||
// indicated PNMImage from the given ram_image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
CPTA_uchar image, size_t page_size, int z) const {
|
||||
pnmimage.clear(x_size, y_size, _num_components);
|
||||
int num_components, int component_width,
|
||||
CPTA_uchar image, size_t page_size, int z) {
|
||||
pnmimage.clear(x_size, y_size, num_components);
|
||||
bool has_alpha = pnmimage.has_alpha();
|
||||
bool is_grayscale = pnmimage.is_grayscale();
|
||||
|
||||
@ -2852,7 +3030,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
nassertr(idx + page_size <= image.size(), false);
|
||||
const unsigned char *p = &image[idx];
|
||||
|
||||
if (_component_type == T_unsigned_byte) {
|
||||
if (component_width == 1) {
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
if (is_grayscale) {
|
||||
@ -2868,7 +3046,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_component_type == T_unsigned_short) {
|
||||
} else if (component_width == 2) {
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
if (is_grayscale) {
|
||||
@ -2885,9 +3063,6 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
}
|
||||
|
||||
} else {
|
||||
gobj_cat.error()
|
||||
<< "Couldn't write image for " << get_name()
|
||||
<< "; inappropriate data type " << (int)_component_type << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3043,6 +3218,34 @@ consider_downgrade(PNMImage &pnmimage, int num_channels) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::compare_images
|
||||
// Access: Private, Static
|
||||
// Description: Called by generate_simple_ram_image(), this compares
|
||||
// the two PNMImages pixel-by-pixel. If they're similar
|
||||
// enough (within a given threshold), returns true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
compare_images(const PNMImage &a, const PNMImage &b) {
|
||||
nassertr(a.get_maxval() == 255 && b.get_maxval() == 255, false);
|
||||
nassertr(a.get_num_channels() == 4 && b.get_num_channels() == 4, false);
|
||||
nassertr(a.get_x_size() == b.get_x_size() &&
|
||||
a.get_y_size() == b.get_y_size(), false);
|
||||
|
||||
int delta = 0;
|
||||
for (int yi = 0; yi < a.get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < a.get_x_size(); ++xi) {
|
||||
delta += abs(a.get_red_val(xi, yi) - b.get_red_val(xi, yi));
|
||||
delta += abs(a.get_green_val(xi, yi) - b.get_green_val(xi, yi));
|
||||
delta += abs(a.get_blue_val(xi, yi) - b.get_blue_val(xi, yi));
|
||||
delta += abs(a.get_alpha_val(xi, yi) - b.get_alpha_val(xi, yi));
|
||||
}
|
||||
}
|
||||
|
||||
double average_delta = (double)delta / ((double)a.get_x_size() * (double)b.get_y_size() * (double)a.get_maxval());
|
||||
return (average_delta <= simple_image_threshold);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::read_txo_file
|
||||
// Access: Private
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "pmap.h"
|
||||
#include "config_gobj.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "reMutex.h"
|
||||
#include "reMutexHolder.h"
|
||||
|
||||
class PNMImage;
|
||||
class TextureContext;
|
||||
@ -313,8 +315,18 @@ PUBLISHED:
|
||||
void clear_ram_mipmap_images();
|
||||
void generate_ram_mipmap_images();
|
||||
|
||||
INLINE int get_simple_x_size() const;
|
||||
INLINE int get_simple_y_size() const;
|
||||
INLINE bool has_simple_ram_image() const;
|
||||
INLINE size_t get_simple_ram_image_size() const;
|
||||
INLINE CPTA_uchar get_simple_ram_image() const;
|
||||
void set_simple_ram_image(PTA_uchar image, int x_size, int y_size);
|
||||
void generate_simple_ram_image();
|
||||
void clear_simple_ram_image();
|
||||
|
||||
INLINE UpdateSeq get_properties_modified() const;
|
||||
INLINE UpdateSeq get_image_modified() const;
|
||||
INLINE UpdateSeq get_simple_image_modified() const;
|
||||
|
||||
void prepare(PreparedGraphicsObjects *prepared_objects);
|
||||
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
|
||||
@ -428,15 +440,20 @@ protected:
|
||||
};
|
||||
|
||||
private:
|
||||
void convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
||||
const PNMImage &pnmimage);
|
||||
bool convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
CPTA_uchar image, size_t page_size, int z) const;
|
||||
static void convert_from_pnmimage(PTA_uchar &image, size_t page_size,
|
||||
int z, const PNMImage &pnmimage,
|
||||
int num_components, int component_width);
|
||||
static bool convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||
int num_components, int component_width,
|
||||
CPTA_uchar image, size_t page_size,
|
||||
int z);
|
||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||
|
||||
void consider_rescale(PNMImage &pnmimage, const string &name);
|
||||
void consider_downgrade(PNMImage &pnmimage, int num_channels);
|
||||
|
||||
static bool compare_images(const PNMImage &a, const PNMImage &b);
|
||||
|
||||
INLINE static void store_unscaled_byte(unsigned char *&p, int value);
|
||||
INLINE static void store_unscaled_short(unsigned char *&p, int value);
|
||||
INLINE static void store_scaled_byte(unsigned char *&p, int value, double scale);
|
||||
@ -480,6 +497,9 @@ private:
|
||||
size_t page_size);
|
||||
|
||||
protected:
|
||||
// Protects all of the members of this class.
|
||||
ReMutex _lock;
|
||||
|
||||
Filename _filename;
|
||||
Filename _alpha_filename;
|
||||
Filename _fullpath;
|
||||
@ -550,9 +570,17 @@ protected:
|
||||
// additional mipmap levels.
|
||||
typedef pvector<RamImage> RamImages;
|
||||
RamImages _ram_images;
|
||||
|
||||
// This is the simple image, which may be loaded before the texture
|
||||
// is loaded from disk. It exists only for 2-d textures.
|
||||
RamImage _simple_ram_image;
|
||||
int _simple_x_size;
|
||||
int _simple_y_size;
|
||||
PN_int32 _simple_image_date_generated;
|
||||
|
||||
UpdateSeq _properties_modified;
|
||||
UpdateSeq _image_modified;
|
||||
UpdateSeq _simple_image_modified;
|
||||
|
||||
private:
|
||||
// The auxiliary data is not recorded to a bam file.
|
||||
|
@ -72,12 +72,24 @@ was_image_modified() const {
|
||||
return _image_modified != _texture->get_image_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::was_simple_image_modified
|
||||
// Access: Public
|
||||
// Description: Returns true if the texture's "simple" image has been
|
||||
// modified since the last time mark_simple_loaded() was
|
||||
// called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TextureContext::
|
||||
was_simple_image_modified() const {
|
||||
return _simple_image_modified != _texture->get_simple_image_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().
|
||||
// Description: Should be called after the texture has been loaded
|
||||
// into graphics memory, this updates the internal flags
|
||||
// for changed_size() and modified().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextureContext::
|
||||
mark_loaded() {
|
||||
@ -89,3 +101,19 @@ mark_loaded() {
|
||||
// Assume the texture is now resident.
|
||||
set_resident(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::mark_simple_loaded
|
||||
// Access: Public
|
||||
// Description: Should be called after the texture's "simple" image
|
||||
// has been loaded into graphics memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextureContext::
|
||||
mark_simple_loaded() {
|
||||
_properties_modified = _texture->get_properties_modified();
|
||||
_simple_image_modified = _texture->get_simple_image_modified();
|
||||
update_modified(max(_properties_modified, _simple_image_modified));
|
||||
|
||||
// The texture's not exactly resident now, but some part of it is.
|
||||
set_resident(true);
|
||||
}
|
||||
|
@ -44,9 +44,11 @@ PUBLISHED:
|
||||
INLINE bool was_modified() const;
|
||||
INLINE bool was_properties_modified() const;
|
||||
INLINE bool was_image_modified() const;
|
||||
INLINE bool was_simple_image_modified() const;
|
||||
|
||||
public:
|
||||
INLINE void mark_loaded();
|
||||
INLINE void mark_simple_loaded();
|
||||
|
||||
private:
|
||||
// This cannot be a PT(Texture), because the texture and the GSG
|
||||
@ -55,6 +57,7 @@ private:
|
||||
Texture *_texture;
|
||||
UpdateSeq _properties_modified;
|
||||
UpdateSeq _image_modified;
|
||||
UpdateSeq _simple_image_modified;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -278,6 +278,9 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
gobj_cat.info()
|
||||
<< "Texture " << filename << " found in disk cache.\n";
|
||||
tex = DCAST(Texture, record->extract_data());
|
||||
if (preload_simple_textures && !tex->has_simple_ram_image()) {
|
||||
tex->generate_simple_ram_image();
|
||||
}
|
||||
if (!preload_textures) {
|
||||
// But drop the RAM until we need it.
|
||||
tex->clear_ram_image();
|
||||
@ -300,6 +303,11 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
report_texture_unreadable(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (preload_simple_textures) {
|
||||
tex->generate_simple_ram_image();
|
||||
}
|
||||
|
||||
store_record = (record != (BamCacheRecord *)NULL);
|
||||
}
|
||||
|
||||
@ -331,11 +339,11 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
nassertr(tex->has_ram_image(), tex);
|
||||
record->set_data(tex, false);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
if (!preload_textures) {
|
||||
// And now drop the RAM until we need it.
|
||||
tex->clear_ram_image();
|
||||
}
|
||||
if (!preload_textures) {
|
||||
// And now drop the RAM until we need it.
|
||||
tex->clear_ram_image();
|
||||
}
|
||||
|
||||
nassertr(!tex->get_fullpath().empty(), tex);
|
||||
@ -424,6 +432,11 @@ ns_load_texture(const Filename &orig_filename,
|
||||
report_texture_unreadable(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (preload_simple_textures) {
|
||||
tex->generate_simple_ram_image();
|
||||
}
|
||||
|
||||
store_record = (record != (BamCacheRecord *)NULL);
|
||||
}
|
||||
|
||||
@ -457,6 +470,11 @@ ns_load_texture(const Filename &orig_filename,
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
if (!preload_textures) {
|
||||
// And now drop the RAM until we need it.
|
||||
tex->clear_ram_image();
|
||||
}
|
||||
|
||||
nassertr(!tex->get_fullpath().empty(), tex);
|
||||
|
||||
// Finally, apply any post-loading texture filters.
|
||||
|
@ -108,6 +108,8 @@ class Lens;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GSGBASE GraphicsStateGuardianBase : public TypedWritableReferenceCount {
|
||||
PUBLISHED:
|
||||
virtual bool get_incomplete_render() const=0;
|
||||
|
||||
virtual bool prefers_triangle_strips() const=0;
|
||||
virtual int get_max_vertices_per_array() const=0;
|
||||
virtual int get_max_vertices_per_primitive() const=0;
|
||||
|
@ -119,6 +119,7 @@
|
||||
textureAttrib.I textureAttrib.h \
|
||||
texGenAttrib.I texGenAttrib.h \
|
||||
textureCollection.I textureCollection.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStageCollection.I textureStageCollection.h \
|
||||
transformState.I transformState.h \
|
||||
transparencyAttrib.I transparencyAttrib.h \
|
||||
@ -232,6 +233,7 @@
|
||||
textureAttrib.cxx \
|
||||
texGenAttrib.cxx \
|
||||
textureCollection.cxx \
|
||||
textureReloadRequest.cxx \
|
||||
textureStageCollection.cxx \
|
||||
transformState.cxx \
|
||||
transparencyAttrib.cxx \
|
||||
@ -343,6 +345,7 @@
|
||||
textureAttrib.I textureAttrib.h \
|
||||
texGenAttrib.I texGenAttrib.h \
|
||||
textureCollection.I textureCollection.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStageCollection.I textureStageCollection.h \
|
||||
transformState.I transformState.h \
|
||||
transparencyAttrib.I transparencyAttrib.h \
|
||||
|
@ -94,6 +94,7 @@
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "texProjectorEffect.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "textureReloadRequest.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "transformState.h"
|
||||
#include "transparencyAttrib.h"
|
||||
@ -338,15 +339,6 @@ ConfigVariableString default_model_extension
|
||||
"Panda's loader; new code should probably give the correct name "
|
||||
"for each model file they intend to load."));
|
||||
|
||||
ConfigVariableBool allow_incomplete_render
|
||||
("allow-incomplete-render", false,
|
||||
PRC_DESC("When this is true, the frame may be rendered even if some of the "
|
||||
"geometry in the scene has been paged out. The nonresident "
|
||||
"geometry will be rendered as soon as it can be paged back in, "
|
||||
"which may be several frames in the future. When this is false, "
|
||||
"geometry is always paged in when needed, holding up the frame "
|
||||
"render if necessary."));
|
||||
|
||||
ConfigVariableEnum<LODNodeType> default_lod_type
|
||||
("default-lod-type", LNT_pop,
|
||||
PRC_DESC("Set this to either 'pop' or 'fade' to determine the type of "
|
||||
@ -448,6 +440,7 @@ init_libpgraph() {
|
||||
TexMatrixAttrib::init_type();
|
||||
TexProjectorEffect::init_type();
|
||||
TextureAttrib::init_type();
|
||||
TextureReloadRequest::init_type();
|
||||
TexGenAttrib::init_type();
|
||||
TransformState::init_type();
|
||||
TransparencyAttrib::init_type();
|
||||
|
@ -68,7 +68,6 @@ extern ConfigVariableBool m_dual_flash;
|
||||
|
||||
extern ConfigVariableList load_file_type;
|
||||
extern ConfigVariableString default_model_extension;
|
||||
extern EXPCL_PANDA_PGRAPH ConfigVariableBool allow_incomplete_render;
|
||||
|
||||
extern ConfigVariableEnum<LODNodeType> default_lod_type;
|
||||
|
||||
|
@ -107,7 +107,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
static const Colorf flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f);
|
||||
static const Colorf flash_dual_color(0.92f, 0.01f, 0.01f, 1.0f);
|
||||
|
||||
bool force = !allow_incomplete_render;
|
||||
bool force = !_gsg->get_incomplete_render();
|
||||
Thread *current_thread = traverser->get_current_thread();
|
||||
|
||||
// Check to see if there's a special transparency setting.
|
||||
@ -264,7 +264,7 @@ finish_cull(SceneSetup *scene_setup, Thread *current_thread) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullResult::
|
||||
draw(Thread *current_thread) {
|
||||
bool force = !allow_incomplete_render;
|
||||
bool force = !_gsg->get_incomplete_render();
|
||||
|
||||
// Ask the bin manager for the correct order to draw all the bins.
|
||||
CullBinManager *bin_manager = CullBinManager::get_global_ptr();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "textureAttrib.cxx"
|
||||
#include "texGenAttrib.cxx"
|
||||
#include "textureCollection.cxx"
|
||||
#include "textureReloadRequest.cxx"
|
||||
#include "textureStageCollection.cxx"
|
||||
#include "transformState.cxx"
|
||||
#include "transparencyAttrib.cxx"
|
||||
|
51
panda/src/pgraph/textureReloadRequest.I
Normal file
51
panda/src/pgraph/textureReloadRequest.I
Normal file
@ -0,0 +1,51 @@
|
||||
// Filename: textureReloadRequest.I
|
||||
// Created by: drose (12Aug08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureReloadRequest::Constructor
|
||||
// Access: Published
|
||||
// Description: Create a new TextureReloadRequest, and add it to the loader
|
||||
// via load_async(), to begin an asynchronous load.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextureReloadRequest::
|
||||
TextureReloadRequest(TextureContext *tc) :
|
||||
_texture_context(tc),
|
||||
_is_ready(false)
|
||||
{
|
||||
nassertv(_texture_context != (TextureContext *)NULL);
|
||||
_texture = _texture_context->get_texture();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureReloadRequest::get_texture_context
|
||||
// Access: Published
|
||||
// Description: Returns the TextureContext object associated with
|
||||
// this asynchronous TextureReloadRequest.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextureContext *TextureReloadRequest::
|
||||
get_texture_context() const {
|
||||
return _texture_context;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureReloadRequest::is_ready
|
||||
// Access: Published
|
||||
// Description: Returns true if this request has completed, false if
|
||||
// it is still pending.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TextureReloadRequest::
|
||||
is_ready() const {
|
||||
return _is_ready;
|
||||
}
|
35
panda/src/pgraph/textureReloadRequest.cxx
Normal file
35
panda/src/pgraph/textureReloadRequest.cxx
Normal file
@ -0,0 +1,35 @@
|
||||
// Filename: textureReloadRequest.cxx
|
||||
// Created by: drose (12Aug08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "textureReloadRequest.h"
|
||||
#include "loader.h"
|
||||
|
||||
TypeHandle TextureReloadRequest::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureReloadRequest::do_task
|
||||
// Access: Protected, Virtual
|
||||
// Description: Performs the task: that is, loads the one model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TextureReloadRequest::
|
||||
do_task() {
|
||||
// Don't reload the texture if it doesn't need it.
|
||||
if (_texture_context->was_image_modified()) {
|
||||
_texture->get_ram_image();
|
||||
}
|
||||
_is_ready = true;
|
||||
|
||||
// Don't continue the task; we're done.
|
||||
return false;
|
||||
}
|
71
panda/src/pgraph/textureReloadRequest.h
Normal file
71
panda/src/pgraph/textureReloadRequest.h
Normal file
@ -0,0 +1,71 @@
|
||||
// Filename: textureReloadRequest.h
|
||||
// Created by: drose (12Aug08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TEXTURERELOADREQUEST
|
||||
#define TEXTURERELOADREQUEST
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "asyncTask.h"
|
||||
#include "texture.h"
|
||||
#include "textureContext.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TextureReloadRequest
|
||||
// Description : This loader request will call
|
||||
// Texture::get_ram_image() in a sub-thread, to force
|
||||
// the texture's image to be re-read from disk. It is
|
||||
// used by GraphicsStateGuardian::async_reload_texture(),
|
||||
// when get_incomplete_render() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PGRAPH TextureReloadRequest : public AsyncTask {
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(TextureReloadRequest);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE TextureReloadRequest(TextureContext *tc);
|
||||
|
||||
INLINE TextureContext *get_texture_context() const;
|
||||
INLINE bool is_ready() const;
|
||||
|
||||
protected:
|
||||
virtual bool do_task();
|
||||
|
||||
private:
|
||||
TextureContext *_texture_context;
|
||||
PT(Texture) _texture;
|
||||
bool _is_ready;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
AsyncTask::init_type();
|
||||
register_type(_type_handle, "TextureReloadRequest",
|
||||
AsyncTask::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;
|
||||
};
|
||||
|
||||
#include "textureReloadRequest.I"
|
||||
|
||||
#endif
|
@ -415,6 +415,7 @@ read_data(xel *array, xelval *) {
|
||||
}
|
||||
x++;
|
||||
}
|
||||
Thread::consider_yield();
|
||||
}
|
||||
|
||||
/* Step 7: Finish decompression */
|
||||
|
Loading…
x
Reference in New Issue
Block a user