fix dx resize crash some more; first pass at dx cube map support

This commit is contained in:
David Rose 2005-07-20 12:45:44 +00:00
parent 0b8f6c1f3f
commit af49897d5e
18 changed files with 653 additions and 213 deletions

View File

@ -273,6 +273,27 @@ get_supports_texture_dot3() const {
return _supports_texture_dot3;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_3d_texture
// Access: Published
// Description: Returns true if this GSG can render 3-d (volumetric)
// textures.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_supports_3d_texture() const {
return _supports_3d_texture;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_cube_map
// Access: Published
// Description: Returns true if this GSG can render cube map textures.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_supports_cube_map() const {
return _supports_cube_map;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_max_lights
// Access: Published
@ -690,6 +711,17 @@ get_cs_transform() const {
return _cs_transform;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_inv_cs_transform
// Access: Public
// Description: Returns the inverse of the transform returned by
// get_cs_transform().
////////////////////////////////////////////////////////////////////
INLINE const TransformState *GraphicsStateGuardian::
get_inv_cs_transform() const {
return _inv_cs_transform;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_light
// Access: Protected

View File

@ -126,6 +126,9 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_supports_texture_saved_result = false;
_supports_texture_dot3 = false;
_supports_3d_texture = false;
_supports_cube_map = false;
// Assume no limits on number of lights or clip planes.
_max_lights = -1;
_max_clip_planes = -1;
@ -946,12 +949,17 @@ set_coordinate_system(CoordinateSystem cs) {
if (_internal_coordinate_system == CS_default ||
_internal_coordinate_system == _coordinate_system) {
_cs_transform = TransformState::make_identity();
_inv_cs_transform = TransformState::make_identity();
} else {
_cs_transform =
TransformState::make_mat
(LMatrix4f::convert_mat(_coordinate_system,
_internal_coordinate_system));
_inv_cs_transform =
TransformState::make_mat
(LMatrix4f::convert_mat(_internal_coordinate_system,
_coordinate_system));
}
_internal_transform = _cs_transform->compose(_external_transform);
}

View File

@ -98,6 +98,9 @@ PUBLISHED:
INLINE bool get_supports_texture_saved_result() const;
INLINE bool get_supports_texture_dot3() const;
INLINE bool get_supports_3d_texture() const;
INLINE bool get_supports_cube_map() const;
INLINE int get_max_lights() const;
INLINE int get_max_clip_planes() const;
@ -205,6 +208,7 @@ public:
virtual CoordinateSystem get_internal_coordinate_system() const;
INLINE const TransformState *get_cs_transform() const;
INLINE const TransformState *get_inv_cs_transform() const;
virtual void issue_transform(const TransformState *transform);
virtual void issue_color_scale(const ColorScaleAttrib *attrib);
@ -317,6 +321,7 @@ protected:
CoordinateSystem _coordinate_system;
CoordinateSystem _internal_coordinate_system;
CPT(TransformState) _cs_transform;
CPT(TransformState) _inv_cs_transform;
Colorf _scene_graph_color;
bool _has_scene_graph_color;
@ -370,6 +375,9 @@ protected:
bool _supports_texture_saved_result;
bool _supports_texture_dot3;
bool _supports_3d_texture;
bool _supports_cube_map;
int _max_lights;
int _max_clip_planes;

View File

@ -295,7 +295,6 @@ appear before they are referenced.
WORLD_NORMAL
EYE_NORMAL
WORLD_POSITION
OBJECT_POSITION
EYE_POSITION
POINT_SPRITE

View File

@ -116,7 +116,7 @@ munge_format_impl(const GeomVertexFormat *orig,
int num_stages = _texture->get_num_on_stages();
for (int i = 0; i < num_stages; ++i) {
TextureStage *stage = _texture->get_on_stage(i);
const InternalName *name = stage->get_texcoord_name();
if (used_stages.insert(name).second) {
// This is the first time we've encountered this texcoord name.

View File

@ -146,7 +146,7 @@ DXGraphicsStateGuardian8::
TextureContext *DXGraphicsStateGuardian8::
prepare_texture(Texture *tex) {
DXTextureContext8 *dtc = new DXTextureContext8(tex);
if (dtc->create_texture(*_screen) == (IDirect3DTexture8 *)NULL) {
if (!dtc->create_texture(*_screen)) {
delete dtc;
return NULL;
}
@ -191,7 +191,7 @@ apply_texture(int i, TextureContext *tc) {
<< "Texture " << *dtc->_texture << " has changed mipmap state.\n";
}
if (dtc->create_texture(*_screen) == (IDirect3DTexture8 *)NULL) {
if (!dtc->create_texture(*_screen)) {
// Oops, we can't re-create the texture for some reason.
dxgsg8_cat.error()
<< "Unable to re-create texture " << *dtc->_texture << endl;
@ -1320,8 +1320,11 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, const
}
DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
nassertv(dtc->get_d3d_2d_texture() != NULL);
IDirect3DSurface8 *tex_level_0, *render_target;
hr = dtc->get_d3d_texture()->GetSurfaceLevel(0, &tex_level_0);
hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
if (FAILED(hr)) {
dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
return;
@ -1519,6 +1522,9 @@ reset() {
_supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0);
_supports_texture_dot3 = true;
_supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0);
_supports_cube_map = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) != 0);
ZeroMemory(&_lmodel_ambient, sizeof(Colorf));
_d3d_device->SetRenderState(D3DRS_AMBIENT, 0x0);
@ -2225,26 +2231,22 @@ do_issue_texture() {
apply_texture(i, tc);
set_texture_blend_mode(i, stage);
bool has_tex_mat = false;
LMatrix4f tex_mat;
bool texcoords_3d = false;
CPT(TransformState) tex_mat = TransformState::make_identity();
if (_current_tex_mat->has_stage(stage)) {
// We have to reorder the elements of the matrix for some reason.
const LMatrix4f &m = _current_tex_mat->get_mat(stage);
tex_mat.set(m(0, 0), m(0, 1), m(0, 3), 0.0f,
m(1, 0), m(1, 1), m(1, 3), 0.0f,
m(3, 0), m(3, 1), m(3, 3), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
has_tex_mat = true;
tex_mat = _current_tex_mat->get_transform(stage);
}
// Issue the texgen mode.
TexGenAttrib::Mode mode = _current_tex_gen->get_mode(stage);
bool any_point_sprite = false;
switch (mode) {
case TexGenAttrib::M_off:
case TexGenAttrib::M_light_vector:
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index);
texcoords_3d = false;
break;
case TexGenAttrib::M_eye_sphere_map:
@ -2254,20 +2256,75 @@ do_issue_texture() {
// This texture matrix, applied on top of the texcoord
// computed by D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR,
// approximates the effect produced by OpenGL's GL_SPHERE_MAP.
static const LMatrix4f sphere_map
(0.33f, 0.0f, 0.0f, 0.0f,
0.0f, 0.33f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f);
if (has_tex_mat) {
tex_mat = sphere_map * tex_mat;
} else {
tex_mat = sphere_map;
has_tex_mat = true;
}
static CPT(TransformState) sphere_map =
TransformState::make_mat(LMatrix4f(0.33f, 0.0f, 0.0f, 0.0f,
0.0f, 0.33f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f));
tex_mat = tex_mat->compose(sphere_map);
texcoords_3d = true;
}
break;
case TexGenAttrib::M_world_cube_map:
// To achieve world reflection vector, we must transform camera
// coordinates to world coordinates; i.e. apply the camera
// transform. In the case of a vector, we should not apply the
// pos component of the transform.
{
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
texcoords_3d = true;
CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3f::zero()));
}
break;
case TexGenAttrib::M_eye_cube_map:
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
texcoords_3d = true;
break;
case TexGenAttrib::M_world_normal:
// To achieve world normal, we must transform camera coordinates
// to world coordinates; i.e. apply the camera transform. In
// the case of a normal, we should not apply the pos component
// of the transform.
{
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
texcoords_3d = true;
CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3f::zero()));
}
break;
case TexGenAttrib::M_eye_normal:
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
texcoords_3d = true;
break;
case TexGenAttrib::M_world_position:
// To achieve world position, we must transform camera
// coordinates to world coordinates; i.e. apply the
// inverse root_transform.
{
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
texcoords_3d = true;
CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
tex_mat = tex_mat->compose(camera_transform);
}
break;
case TexGenAttrib::M_eye_position:
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX,
texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
texcoords_3d = true;
tex_mat = tex_mat->compose(_inv_cs_transform);
break;
case TexGenAttrib::M_point_sprite:
_d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index);
@ -2277,8 +2334,17 @@ do_issue_texture() {
_d3d_device->SetRenderState(D3DRS_POINTSPRITEENABLE, any_point_sprite);
if (has_tex_mat) {
_d3d_device->SetTransform(get_tex_mat_sym(i), (D3DMATRIX *)tex_mat.get_data());
if (!tex_mat->is_identity()) {
LMatrix4f m = tex_mat->get_mat();
if (!texcoords_3d) {
// For 2-d texture coordinates, we have to reorder the matrix.
m.set(m(0, 0), m(0, 1), m(0, 3), 0.0f,
m(1, 0), m(1, 1), m(1, 3), 0.0f,
m(3, 0), m(3, 1), m(3, 3), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
_d3d_device->SetTransform(get_tex_mat_sym(i), (D3DMATRIX *)m.get_data());
_d3d_device->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTTFF_COUNT2);
} else {
@ -2964,10 +3030,10 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
assert(IS_VALID_PTR(_screen->_d3d8));
assert(IS_VALID_PTR(_d3d_device));
// It is not clear whether we need to call this or not. Calling
// this forces all of the textures and vbuffers to be regenerated,
// but it doesn't appear to be necessary.
//release_all();
// Calling this forces all of the textures and vbuffers to be
// regenerated. It appears to be necessary on some cards but not
// on others.
release_all();
// for windowed mode make sure our format matches the desktop fmt,
// in case the desktop mode has been changed

View File

@ -32,9 +32,42 @@ has_mipmaps() const {
// Function: DXTextureContext8::get_d3d_texture
// Access: Public
// Description: Returns the Direct3D object that represents the
// texture.
// texture, whatever kind of texture it is.
////////////////////////////////////////////////////////////////////
INLINE IDirect3DTexture8 *DXTextureContext8::
INLINE IDirect3DBaseTexture8 *DXTextureContext8::
get_d3d_texture() const {
return _d3d_texture;
}
////////////////////////////////////////////////////////////////////
// Function: DXTextureContext8::get_d3d_2d_texture
// Access: Public
// Description: Returns the Direct3D object that represents the
// texture, in the case of a 1-d or 2-d texture.
////////////////////////////////////////////////////////////////////
INLINE IDirect3DTexture8 *DXTextureContext8::
get_d3d_2d_texture() const {
return _d3d_2d_texture;
}
////////////////////////////////////////////////////////////////////
// Function: DXTextureContext8::get_d3d_volume_texture
// Access: Public
// Description: Returns the Direct3D object that represents the
// texture, in the case of a 3-d texture.
////////////////////////////////////////////////////////////////////
INLINE IDirect3DVolumeTexture8 *DXTextureContext8::
get_d3d_volume_texture() const {
return _d3d_volume_texture;
}
////////////////////////////////////////////////////////////////////
// Function: DXTextureContext8::get_d3d_cube_texture
// Access: Public
// Description: Returns the Direct3D object that represents the
// texture, in the case of a cube map texture.
////////////////////////////////////////////////////////////////////
INLINE IDirect3DCubeTexture8 *DXTextureContext8::
get_d3d_cube_texture() const {
return _d3d_cube_texture;
}

View File

@ -43,8 +43,10 @@ DXTextureContext8(Texture *tex) :
}
_d3d_texture = NULL;
_d3d_2d_texture = NULL;
_d3d_volume_texture = NULL;
_d3d_cube_texture = NULL;
_has_mipmaps = false;
_tex = tex;
}
////////////////////////////////////////////////////////////////////
@ -56,11 +58,10 @@ DXTextureContext8::
~DXTextureContext8() {
if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam()
<< "Deleting texture context for " << _tex->get_name() << "\n";
<< "Deleting texture context for " << _texture->get_name() << "\n";
}
delete_texture();
TextureContext::~TextureContext();
_tex = NULL;
}
////////////////////////////////////////////////////////////////////
@ -70,16 +71,17 @@ DXTextureContext8::
// for the specified device. This code gets the
// attributes of the texture from the bitmap, creates
// the texture, and then copies the bitmap into the
// texture.
// texture. The return value is true if the texture is
// successfully created, false otherwise.
////////////////////////////////////////////////////////////////////
IDirect3DTexture8 *DXTextureContext8::
bool DXTextureContext8::
create_texture(DXScreenData &scrn) {
HRESULT hr;
int num_alpha_bits; // number of alpha bits in texture pixfmt
D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
bool needs_luminance = false;
nassertr(IS_VALID_PTR(_texture), NULL);
nassertr(IS_VALID_PTR(_texture), false);
delete_texture();
@ -93,6 +95,7 @@ create_texture(DXScreenData &scrn) {
DWORD orig_width = (DWORD)_texture->get_x_size();
DWORD orig_height = (DWORD)_texture->get_y_size();
DWORD orig_depth = (DWORD)_texture->get_z_size();
if ((_texture->get_format() == Texture::F_luminance_alpha)||
(_texture->get_format() == Texture::F_luminance_alphamask) ||
@ -103,7 +106,7 @@ create_texture(DXScreenData &scrn) {
if (num_alpha_bits > 0) {
if (num_color_channels == 3) {
dxgsg8_cat.error()
<< "texture " << _tex->get_name()
<< "texture " << _texture->get_name()
<< " has no inherent alpha channel, but alpha format is requested!\n";
}
}
@ -121,7 +124,7 @@ create_texture(DXScreenData &scrn) {
}
break;
case 2:
assert(needs_luminance && (num_alpha_bits > 0));
nassertr(needs_luminance && (num_alpha_bits > 0), false);
_d3d_format = D3DFMT_A8L8;
break;
case 3:
@ -133,43 +136,120 @@ create_texture(DXScreenData &scrn) {
}
// make sure we handled all the possible cases
assert(_d3d_format != D3DFMT_UNKNOWN);
nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
DWORD target_width = orig_width;
DWORD target_height = orig_height;
DWORD target_depth = orig_depth;
if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_POW2) {
if (!ISPOW2(target_width)) {
target_width = down_to_power_2(target_width);
}
if (!ISPOW2(target_height)) {
target_height = down_to_power_2(target_height);
}
}
DWORD filter_caps;
if (target_width > scrn._d3dcaps.MaxTextureWidth) {
target_width = scrn._d3dcaps.MaxTextureWidth;
}
if (target_height > scrn._d3dcaps.MaxTextureHeight) {
target_height = scrn._d3dcaps.MaxTextureHeight;
switch (_texture->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
filter_caps = scrn._d3dcaps.TextureFilterCaps;
if (target_width > scrn._d3dcaps.MaxTextureWidth) {
target_width = scrn._d3dcaps.MaxTextureWidth;
}
if (target_height > scrn._d3dcaps.MaxTextureHeight) {
target_height = scrn._d3dcaps.MaxTextureHeight;
}
if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_POW2) {
if (!ISPOW2(target_width)) {
target_width = down_to_power_2(target_width);
}
if (!ISPOW2(target_height)) {
target_height = down_to_power_2(target_height);
}
}
break;
case Texture::TT_3d_texture:
if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0) {
dxgsg8_cat.warning()
<< "3-d textures are not supported by this graphics driver.\n";
return false;
}
filter_caps = scrn._d3dcaps.VolumeTextureFilterCaps;
if (target_width > scrn._d3dcaps.MaxVolumeExtent) {
target_width = scrn._d3dcaps.MaxVolumeExtent;
}
if (target_height > scrn._d3dcaps.MaxVolumeExtent) {
target_height = scrn._d3dcaps.MaxVolumeExtent;
}
if (target_depth > scrn._d3dcaps.MaxVolumeExtent) {
target_depth = scrn._d3dcaps.MaxVolumeExtent;
}
if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) {
if (!ISPOW2(target_width)) {
target_width = down_to_power_2(target_width);
}
if (!ISPOW2(target_height)) {
target_height = down_to_power_2(target_height);
}
if (!ISPOW2(target_depth)) {
target_depth = down_to_power_2(target_depth);
}
}
break;
case Texture::TT_cube_map:
if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0) {
dxgsg8_cat.warning()
<< "Cube map textures are not supported by this graphics driver.\n";
return false;
}
filter_caps = scrn._d3dcaps.CubeTextureFilterCaps;
if (target_width > scrn._d3dcaps.MaxTextureWidth) {
target_width = scrn._d3dcaps.MaxTextureWidth;
}
if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) {
if (!ISPOW2(target_width)) {
target_width = down_to_power_2(target_width);
}
}
target_height = target_width;
break;
}
// checks for SQUARE reqmt (nvidia riva128 needs this)
if ((target_width != target_height) && (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) {
// assume pow2 textures. sum exponents, divide by 2 rounding down to get sq size
if ((target_width != target_height) &&
(scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0) {
// assume pow2 textures. sum exponents, divide by 2 rounding down
// to get sq size
int i, width_exp, height_exp;
for (i = target_width, width_exp = 0; i > 1; width_exp++, i >>= 1);
for (i = target_height, height_exp = 0; i > 1; height_exp++, i >>= 1);
for (i = target_width, width_exp = 0; i > 1; width_exp++, i >>= 1) {
}
for (i = target_height, height_exp = 0; i > 1; height_exp++, i >>= 1) {
}
target_height = target_width = 1<<((width_exp+height_exp)>>1);
}
bool shrink_original = false;
if (orig_width != target_width || orig_height != target_height) {
dxgsg8_cat.info()
<< "Reducing size of " << _tex->get_name()
<< " from " << orig_width << "x" << orig_height
<< " to " << target_width << "x" << target_height << "\n";
if (orig_width != target_width || orig_height != target_height ||
orig_depth != target_depth) {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
dxgsg8_cat.info()
<< "Reducing size of " << _texture->get_name()
<< " from " << orig_width << "x" << orig_height << "x" << orig_depth
<< " to " << target_width << "x" << target_height
<< "x" << target_depth << "\n";
} else {
dxgsg8_cat.info()
<< "Reducing size of " << _texture->get_name()
<< " from " << orig_width << "x" << orig_height
<< " to " << target_width << "x" << target_height << "\n";
}
shrink_original = true;
}
@ -218,7 +298,7 @@ create_texture(DXScreenData &scrn) {
}
if (num_alpha_bits>0) {
assert(num_color_channels == 4);
nassertr(num_color_channels == 4, false);
// no 32-bit fmt, look for 16 bit w/alpha (1-15)
@ -262,7 +342,7 @@ create_texture(DXScreenData &scrn) {
break;
case 24:
assert(num_color_channels == 3);
nassertr(num_color_channels == 3, false);
if (!dx_force_16bpptextures) {
CHECK_FOR_FMT(R8G8B8, Conv24to24);
@ -281,8 +361,8 @@ create_texture(DXScreenData &scrn) {
case 16:
if (needs_luminance) {
assert(num_alpha_bits>0);
assert(num_color_channels == 2);
nassertr(num_alpha_bits > 0, false);
nassertr(num_color_channels == 2, false);
CHECK_FOR_FMT(A8L8, ConvLum16to16);
@ -301,7 +381,7 @@ create_texture(DXScreenData &scrn) {
CHECK_FOR_FMT(A4R4G4B4, ConvLum16to16_4444);
CHECK_FOR_FMT(A1R5G5B5, ConvLum16to16_1555);
} else {
assert((num_color_channels == 3)||(num_color_channels == 4));
nassertr((num_color_channels == 3)||(num_color_channels == 4), false);
// look for compatible 16bit fmts, if none then give up
// (dont worry about other bitdepths for 16 bit)
switch(num_alpha_bits) {
@ -310,7 +390,7 @@ create_texture(DXScreenData &scrn) {
CHECK_FOR_FMT(R5G6B5, Conv24to16_0565);
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
} else {
assert(num_color_channels == 4);
nassertr(num_color_channels == 4, false);
// it could be 4 if user asks us to throw away the alpha channel
CHECK_FOR_FMT(R5G6B5, Conv32to16_0565);
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
@ -321,23 +401,24 @@ create_texture(DXScreenData &scrn) {
// explicitly want 1-5-5-5 fmt, as opposed to F_rgbm, which
// could use 32bpp ARGB. fail if this particular fmt not
// avail.
assert(num_color_channels == 4);
nassertr(num_color_channels == 4, false);
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
break;
case 4:
// app specifically requests 4-4-4-4 F_rgba4 case, as opposed
// to F_rgba, which could use 32bpp ARGB
assert(num_color_channels == 4);
nassertr(num_color_channels == 4, false);
CHECK_FOR_FMT(A4R4G4B4, Conv32to16_4444);
break;
default: assert(0); // problem in get_bits_per_pixel()?
default:
nassertr(false, false); // problem in get_bits_per_pixel()?
}
}
case 8:
if (needs_luminance) {
// dont bother handling those other 8bit lum fmts like 4-4,
// since 16 8-8 is usually supported too
assert(num_color_channels == 1);
nassertr(num_color_channels == 1, false);
// look for native lum fmt first
CHECK_FOR_FMT(L8, ConvLum8to8);
@ -375,9 +456,11 @@ create_texture(DXScreenData &scrn) {
// if we've gotten here, haven't found a match
dxgsg8_cat.error()
<< error_message << ": " << _tex->get_name() << endl
<< "NumColorChannels: " <<num_color_channels << "; NumAlphaBits: " << num_alpha_bits
<< "; targetbpp: " <<target_bpp << "; _supported_tex_formats_mask: 0x" << (void*)scrn._supported_tex_formats_mask
<< error_message << ": " << _texture->get_name() << endl
<< "NumColorChannels: " << num_color_channels << "; NumAlphaBits: "
<< num_alpha_bits << "; targetbpp: " <<target_bpp
<< "; _supported_tex_formats_mask: 0x"
<< (void*)scrn._supported_tex_formats_mask
<< "; NeedLuminance: " << needs_luminance << endl;
goto error_exit;
@ -421,7 +504,7 @@ create_texture(DXScreenData &scrn) {
Texture::FilterType ft;
ft = _tex->get_magfilter();
ft = _texture->get_magfilter();
if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) {
// mipmap settings make no sense for magfilter
if (ft == Texture::FT_nearest_mipmap_nearest) {
@ -431,13 +514,14 @@ create_texture(DXScreenData &scrn) {
}
}
if ((ft == Texture::FT_linear) && !(scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)) {
if (ft == Texture::FT_linear &&
(filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) {
ft = Texture::FT_nearest;
}
_tex->set_magfilter(ft);
_texture->set_magfilter(ft);
// figure out if we are mipmapping this texture
ft = _tex->get_minfilter();
ft = _texture->get_minfilter();
_has_mipmaps = false;
if (!dx_ignore_mipmaps) { // set if no HW mipmap capable
@ -453,11 +537,13 @@ create_texture(DXScreenData &scrn) {
_has_mipmaps = true;
if (dxgsg8_cat.is_spam()) {
if (ft != Texture::FT_linear_mipmap_linear) {
dxgsg8_cat.spam() << "Forcing trilinear mipmapping on DX texture [" << _tex->get_name() << "]\n";
dxgsg8_cat.spam()
<< "Forcing trilinear mipmapping on DX texture ["
<< _texture->get_name() << "]\n";
}
}
ft = Texture::FT_linear_mipmap_linear;
_tex->set_minfilter(ft);
_texture->set_minfilter(ft);
}
} else if ((ft == Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types
@ -469,15 +555,15 @@ create_texture(DXScreenData &scrn) {
ft = Texture::FT_linear;
}
assert((scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT) != 0);
nassertr((filter_caps & D3DPTFILTERCAPS_MINFPOINT) != 0, false);
#define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR)
// do any other filter type degradations necessary
switch(ft) {
case Texture::FT_linear_mipmap_linear:
if ((scrn._d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS) != TRILINEAR_MIPMAP_TEXFILTERCAPS) {
if (scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) {
if ((filter_caps & TRILINEAR_MIPMAP_TEXFILTERCAPS) != TRILINEAR_MIPMAP_TEXFILTERCAPS) {
if (filter_caps & D3DPTFILTERCAPS_MINFLINEAR) {
ft = Texture::FT_linear_mipmap_nearest;
} else {
// if you cant do linear in a level, you probably cant do
@ -489,43 +575,43 @@ create_texture(DXScreenData &scrn) {
case Texture::FT_nearest_mipmap_linear:
// if we dont have bilinear, do nearest_nearest
if (!((scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) &&
(scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR))) {
if (!((filter_caps & D3DPTFILTERCAPS_MIPFPOINT) &&
(filter_caps & D3DPTFILTERCAPS_MINFLINEAR))) {
ft = Texture::FT_nearest_mipmap_nearest;
}
break;
case Texture::FT_linear_mipmap_nearest:
// if we dont have mip linear, do nearest_nearest
if (!(scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)) {
if (!(filter_caps & D3DPTFILTERCAPS_MIPFLINEAR)) {
ft = Texture::FT_nearest_mipmap_nearest;
}
break;
case Texture::FT_linear:
if (!(scrn._d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)) {
if (!(filter_caps & D3DPTFILTERCAPS_MINFLINEAR)) {
ft = Texture::FT_nearest;
}
break;
}
_tex->set_minfilter(ft);
_texture->set_minfilter(ft);
uint aniso_degree;
aniso_degree = 1;
if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
aniso_degree = _tex->get_anisotropic_degree();
aniso_degree = _texture->get_anisotropic_degree();
if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) ||
dx_force_anisotropic_filtering) {
aniso_degree = scrn._d3dcaps.MaxAnisotropy;
}
}
_tex->set_anisotropic_degree(aniso_degree);
_texture->set_anisotropic_degree(aniso_degree);
#ifdef _DEBUG
dxgsg8_cat.spam()
<< "create_texture: setting aniso degree for " << _tex->get_name()
<< "create_texture: setting aniso degree for " << _texture->get_name()
<< " to: " << aniso_degree << endl;
#endif
@ -537,15 +623,37 @@ create_texture(DXScreenData &scrn) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "create_texture: generating mipmaps for " << _tex->get_name()
<< "create_texture: generating mipmaps for " << _texture->get_name()
<< endl;
}
} else {
mip_level_count = 1;
}
hr = scrn._d3d_device->CreateTexture(target_width, target_height, mip_level_count, 0x0,
target_pixel_format, D3DPOOL_MANAGED, &_d3d_texture);
switch (_texture->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
hr = scrn._d3d_device->CreateTexture
(target_width, target_height, mip_level_count, 0x0,
target_pixel_format, D3DPOOL_MANAGED, &_d3d_2d_texture);
_d3d_texture = _d3d_2d_texture;
break;
case Texture::TT_3d_texture:
hr = scrn._d3d_device->CreateVolumeTexture
(target_width, target_height, target_depth, mip_level_count, 0x0,
target_pixel_format, D3DPOOL_MANAGED, &_d3d_volume_texture);
_d3d_texture = _d3d_volume_texture;
break;
case Texture::TT_cube_map:
hr = scrn._d3d_device->CreateCubeTexture
(target_width, mip_level_count, 0x0,
target_pixel_format, D3DPOOL_MANAGED, &_d3d_cube_texture);
_d3d_texture = _d3d_cube_texture;
break;
}
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "D3D create_texture failed!" << D3DERRORSTRING(hr);
@ -554,7 +662,7 @@ create_texture(DXScreenData &scrn) {
if (dxgsg8_cat.is_debug()) {
dxgsg8_cat.debug()
<< "create_texture: " << _tex->get_name()
<< "create_texture: " << _texture->get_name()
<< " converting panda equivalent of " << D3DFormatStr(_d3d_format)
<< " => " << D3DFormatStr(target_pixel_format) << endl;
}
@ -566,13 +674,15 @@ create_texture(DXScreenData &scrn) {
// PRINT_REFCNT(dxgsg8, scrn._d3d8);
// Return the newly created texture
return _d3d_texture;
return true;
error_exit:
RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE);
return NULL;
_d3d_2d_texture = NULL;
_d3d_volume_texture = NULL;
_d3d_cube_texture = NULL;
return false;
}
////////////////////////////////////////////////////////////////////
@ -587,11 +697,10 @@ delete_texture() {
return;
}
if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
}
RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE);
_d3d_2d_texture = NULL;
_d3d_volume_texture = NULL;
_d3d_cube_texture = NULL;
}
////////////////////////////////////////////////////////////////////
@ -616,7 +725,9 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, Textur
BYTE *buf = result->modify_ram_image().p();
if (IsBadWritePtr(d3d_surface, sizeof(DWORD))) {
dxgsg8_cat.error() << "d3d_surface_to_texture failed: bad pD3DSurf ptr value (" << ((void*)d3d_surface) << ")\n";
dxgsg8_cat.error()
<< "d3d_surface_to_texture failed: bad pD3DSurf ptr value ("
<< ((void*)d3d_surface) << ")\n";
exit(1);
}
@ -632,18 +743,20 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, Textur
copy_width = RECT_XSIZE(source_rect);
copy_height = RECT_YSIZE(source_rect);
//make sure there's enough space in the texture, its size must match
//(especially xsize) or scanlines will be too long
// make sure there's enough space in the texture, its size must
// match (especially xsize) or scanlines will be too long
if (!((copy_width == result->get_x_size()) && (copy_height <= (DWORD)result->get_y_size()))) {
dxgsg8_cat.error() << "d3d_surface_to_texture, Texture size too small to hold display surface!\n";
dxgsg8_cat.error()
<< "d3d_surface_to_texture, Texture size too small to hold display surface!\n";
nassertr(false, E_FAIL);
return E_FAIL;
}
hr = d3d_surface->LockRect(&locked_rect, (CONST RECT*)NULL, (D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE /* | D3DLOCK_NOSYSLOCK */));
if (FAILED(hr)) {
dxgsg8_cat.error() << "d3d_surface_to_texture LockRect() failed!" << D3DERRORSTRING(hr);
dxgsg8_cat.error()
<< "d3d_surface_to_texture LockRect() failed!" << D3DERRORSTRING(hr);
return hr;
}
@ -816,7 +929,8 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, Textur
}
default:
dxgsg8_cat.error() << "d3d_surface_to_texture: unsupported D3DFORMAT!\n";
dxgsg8_cat.error()
<< "d3d_surface_to_texture: unsupported D3DFORMAT!\n";
}
d3d_surface->UnlockRect();
@ -830,8 +944,12 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, Textur
////////////////////////////////////////////////////////////////////
HRESULT DXTextureContext8::
fill_d3d_texture_pixels() {
if (_texture->get_texture_type() == Texture::TT_3d_texture) {
return fill_d3d_volume_texture_pixels();
}
HRESULT hr = E_FAIL;
assert(IS_VALID_PTR(_texture));
nassertr(IS_VALID_PTR(_texture), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
if (image.is_null()) {
@ -843,80 +961,266 @@ fill_d3d_texture_pixels() {
PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
assert(IS_VALID_PTR(_d3d_texture));
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *pixels = (BYTE*)image.p();
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
assert(IS_VALID_PTR(pixels));
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
IDirect3DSurface8 *mip_level_0 = NULL;
bool using_temp_buffer = false;
BYTE *pixels = NULL;
for (unsigned int di = 0; di < orig_depth; di++) {
pixels = image_pixels + di * _texture->get_expected_ram_page_size();
mip_level_0 = NULL;
if (_texture->get_texture_type() == Texture::TT_cube_map) {
nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)di, 0, &mip_level_0);
} else {
nassertr(IS_VALID_PTR(_d3d_2d_texture), E_FAIL);
hr = _d3d_2d_texture->GetSurfaceLevel(0, &mip_level_0);
}
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
RECT source_size;
source_size.left = source_size.top = 0;
source_size.right = orig_width;
source_size.bottom = orig_height;
UINT source_row_byte_length = orig_width * num_color_channels;
DWORD level_0_filter, mip_filter_flags;
using_temp_buffer = false;
// need filtering if size changes, (also if bitdepth reduced (need
// dithering)??)
level_0_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures
// D3DXLoadSurfaceFromMemory will load black luminance and we want
// full white, so convert to explicit luminance-alpha format
if (_d3d_format == D3DFMT_A8) {
// alloc buffer for explicit D3DFMT_A8L8
USHORT *temp_buffer = new USHORT[orig_width * orig_height];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillDDSurf;
}
using_temp_buffer = true;
USHORT *out_pixels = temp_buffer;
BYTE *source_pixels = pixels + component_width - 1;
for (UINT y = 0; y < orig_height; y++) {
for (UINT x = 0;
x < orig_width;
x++, source_pixels += component_width, out_pixels++) {
// add full white, which is our interpretation of alpha-only
// (similar to default adding full opaque alpha 0xFF to
// RGB-only textures)
*out_pixels = ((*source_pixels) << 8 ) | 0xFF;
}
}
source_format = D3DFMT_A8L8;
source_row_byte_length = orig_width * sizeof(USHORT);
pixels = (BYTE*)temp_buffer;
} else if (component_width != 1) {
// Convert from 16-bit per channel (or larger) format down to
// 8-bit per channel. This throws away precision in the
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_pixels = orig_width * orig_height * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillDDSurf;
}
using_temp_buffer = true;
BYTE *source_pixels = pixels + component_width - 1;
for (int i = 0; i < num_pixels; i++) {
temp_buffer[i] = *source_pixels;
source_pixels += component_width;
}
pixels = (BYTE*)temp_buffer;
}
// filtering may be done here if texture if targetsize != origsize
#ifdef DO_PSTATS
GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_row_byte_length * orig_height);
#endif
hr = D3DXLoadSurfaceFromMemory
(mip_level_0, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)pixels,
source_format, source_row_byte_length, (PALETTEENTRY*)NULL,
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
if (_has_mipmaps) {
if (!dx_use_triangle_mipgen_filter) {
mip_filter_flags = D3DX_FILTER_BOX;
} else {
mip_filter_flags = D3DX_FILTER_TRIANGLE;
}
// mip_filter_flags| = D3DX_FILTER_DITHER;
hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
mip_filter_flags);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
}
if (using_temp_buffer) {
SAFE_DELETE_ARRAY(pixels);
}
RELEASE(mip_level_0, dxgsg8, "FillDDSurf MipLev0 texture ptr", RELEASE_ONCE);
}
return hr;
exit_FillDDSurf:
if (using_temp_buffer) {
SAFE_DELETE_ARRAY(pixels);
}
RELEASE(mip_level_0, dxgsg8, "FillDDSurf MipLev0 texture ptr", RELEASE_ONCE);
return hr;
}
////////////////////////////////////////////////////////////////////
// Function: DXTextureContext8::fill_d3d_volume_texture_pixels
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
HRESULT DXTextureContext8::
fill_d3d_volume_texture_pixels() {
HRESULT hr = E_FAIL;
nassertr(IS_VALID_PTR(_texture), E_FAIL);
CPTA_uchar image = _texture->get_ram_image();
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
// operations or something.
return S_OK;
}
PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
nassertr(_texture->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
DWORD orig_width = (DWORD) _texture->get_x_size();
DWORD orig_height = (DWORD) _texture->get_y_size();
DWORD orig_depth = (DWORD) _texture->get_z_size();
DWORD num_color_channels = _texture->get_num_components();
D3DFORMAT source_format = _d3d_format;
BYTE *image_pixels = (BYTE*)image.p();
int component_width = _texture->get_component_width();
nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
IDirect3DVolume8 *mip_level_0 = NULL;
bool using_temp_buffer = false;
BYTE *pixels = image_pixels;
nassertr(IS_VALID_PTR(_d3d_volume_texture), E_FAIL);
hr = _d3d_volume_texture->GetVolumeLevel(0, &mip_level_0);
IDirect3DSurface8 *mip_level_0;
hr = _d3d_texture->GetSurfaceLevel(0, &mip_level_0);
if (FAILED(hr)) {
dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for " << _tex->get_name() << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
return E_FAIL;
}
RECT source_size;
source_size.left = source_size.top = 0;
source_size.right = orig_width;
source_size.bottom = orig_height;
D3DBOX source_size;
source_size.Left = source_size.Top = source_size.Front = 0;
source_size.Right = orig_width;
source_size.Bottom = orig_height;
source_size.Back = orig_depth;
UINT source_row_byte_length = orig_width * num_color_channels;
UINT source_page_byte_length = orig_height * source_row_byte_length;
DWORD level_0_filter, mip_filter_flags;
bool using_temp_buffer = false;
// need filtering if size changes, (also if bitdepth reduced (need dithering)??)
using_temp_buffer = false;
// need filtering if size changes, (also if bitdepth reduced (need
// dithering)??)
level_0_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures
// D3DXLoadSurfaceFromMemory will load black luminance and we want full white,
// so convert to explicit luminance-alpha format
// D3DXLoadSurfaceFromMemory will load black luminance and we want
// full white, so convert to explicit luminance-alpha format
if (_d3d_format == D3DFMT_A8) {
// alloc buffer for explicit D3DFMT_A8L8
USHORT *temp_buffer = new USHORT[orig_width*orig_height];
USHORT *temp_buffer = new USHORT[orig_width * orig_height * orig_depth];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillDDSurf;
}
using_temp_buffer = true;
USHORT *out_pixels = temp_buffer;
BYTE *source_pixels = pixels + component_width - 1;
for (UINT y = 0; y < orig_height; y++) {
for (UINT x = 0;
x < orig_width;
x++, source_pixels += component_width, out_pixels++) {
// add full white, which is our interpretation of alpha-only
// (similar to default adding full opaque alpha 0xFF to
// RGB-only textures)
*out_pixels = ((*source_pixels) << 8 ) | 0xFF;
for (UINT z = 0; z < orig_depth; z++) {
for (UINT y = 0; y < orig_height; y++) {
for (UINT x = 0;
x < orig_width;
x++, source_pixels += component_width, out_pixels++) {
// add full white, which is our interpretation of alpha-only
// (similar to default adding full opaque alpha 0xFF to
// RGB-only textures)
*out_pixels = ((*source_pixels) << 8 ) | 0xFF;
}
}
}
source_format = D3DFMT_A8L8;
source_row_byte_length = orig_width*sizeof(USHORT);
source_row_byte_length = orig_width * sizeof(USHORT);
source_page_byte_length = orig_height * source_row_byte_length;
pixels = (BYTE*)temp_buffer;
} else if (component_width != 1) {
// Convert from 16-bit per channel (or larger) format down to
// 8-bit per channel. This throws away precision in the
// original image, but dx8 doesn't support high-precision images
// anyway.
int num_components = _texture->get_num_components();
int num_pixels = orig_width * orig_height * num_components;
int num_pixels = orig_width * orig_height * orig_depth * num_components;
BYTE *temp_buffer = new BYTE[num_pixels];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillDDSurf;
}
using_temp_buffer = true;
BYTE *source_pixels = pixels + component_width - 1;
for (int i = 0; i < num_pixels; i++) {
temp_buffer[i] = *source_pixels;
@ -924,36 +1228,43 @@ fill_d3d_texture_pixels() {
}
pixels = (BYTE*)temp_buffer;
}
// filtering may be done here if texture if targetsize != origsize
#ifdef DO_PSTATS
GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_row_byte_length * orig_height);
GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_page_byte_length * orig_depth);
#endif
hr = D3DXLoadSurfaceFromMemory(mip_level_0, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)pixels, source_format,
source_row_byte_length, (PALETTEENTRY*)NULL, &source_size, level_0_filter, (D3DCOLOR)0x0);
hr = D3DXLoadVolumeFromMemory
(mip_level_0, (PALETTEENTRY*)NULL, (D3DBOX*)NULL, (LPCVOID)pixels,
source_format, source_row_byte_length, source_page_byte_length,
(PALETTEENTRY*)NULL,
&source_size, level_0_filter, (D3DCOLOR)0x0);
if (FAILED(hr)) {
dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for " << _tex->get_name() << ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
if (_has_mipmaps) {
if (!dx_use_triangle_mipgen_filter) {
mip_filter_flags = D3DX_FILTER_BOX;
} else {
mip_filter_flags = D3DX_FILTER_TRIANGLE;
}
// mip_filter_flags| = D3DX_FILTER_DITHER;
hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0, mip_filter_flags);
hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
mip_filter_flags);
if (FAILED(hr)) {
dxgsg8_cat.error()
<< "FillDDSurfaceTexturePixels failed for " << _tex->get_name() << ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
<< "FillDDSurfaceTexturePixels failed for " << _texture->get_name()
<< ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
goto exit_FillDDSurf;
}
}
exit_FillDDSurf:
if (using_temp_buffer) {
SAFE_DELETE_ARRAY(pixels);

View File

@ -32,23 +32,29 @@ public:
DXTextureContext8(Texture *tex);
virtual ~DXTextureContext8();
IDirect3DTexture8 *create_texture(DXScreenData &scrn);
bool create_texture(DXScreenData &scrn);
void delete_texture();
INLINE bool has_mipmaps() const;
INLINE IDirect3DTexture8 *get_d3d_texture() const;
INLINE IDirect3DBaseTexture8 *get_d3d_texture() const;
INLINE IDirect3DTexture8 *get_d3d_2d_texture() const;
INLINE IDirect3DVolumeTexture8 *get_d3d_volume_texture() const;
INLINE IDirect3DCubeTexture8 *get_d3d_cube_texture() const;
static HRESULT d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, Texture *result);
private:
HRESULT fill_d3d_texture_pixels();
HRESULT fill_d3d_volume_texture_pixels();
static int down_to_power_2(int value);
unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits);
private:
Texture *_tex; // ptr to parent, primarily for access to namestr
D3DFORMAT _d3d_format; // the 'D3DFORMAT' the Panda TextureBuffer fmt corresponds to
IDirect3DTexture8 *_d3d_texture;
IDirect3DBaseTexture8 *_d3d_texture;
IDirect3DTexture8 *_d3d_2d_texture;
IDirect3DVolumeTexture8 *_d3d_volume_texture;
IDirect3DCubeTexture8 *_d3d_cube_texture;
bool _has_mipmaps;

View File

@ -1114,7 +1114,7 @@ search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info) {
////////////////////////////////////////////////////////////////////
bool wdxGraphicsWindow8::
reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
assert((new_xsize > 0) && (new_ysize > 0));
nassertr((new_xsize > 0) && (new_ysize > 0), false);
bool retval = true;
DXScreenData *screen = NULL;

View File

@ -836,9 +836,6 @@ string_tex_gen(const string &string) {
} else if (cmp_nocase_uh(string, "world_position") == 0) {
return TG_world_position;
} else if (cmp_nocase_uh(string, "object_position") == 0) {
return TG_object_position;
} else if (cmp_nocase_uh(string, "eye_position") == 0) {
return TG_eye_position;
@ -1161,9 +1158,6 @@ operator << (ostream &out, EggTexture::TexGen tex_gen) {
case EggTexture::TG_world_position:
return out << "world_position";
case EggTexture::TG_object_position:
return out << "object_position";
case EggTexture::TG_eye_position:
return out << "eye_position";

View File

@ -140,7 +140,6 @@ PUBLISHED:
TG_eye_normal,
TG_world_position,
TG_object_position,
TG_eye_position,
TG_point_sprite,

View File

@ -515,9 +515,6 @@ get_tex_gen(const EggTexture *egg_tex) {
case EggTexture::TG_world_position:
return TexGenAttrib::M_world_position;
case EggTexture::TG_object_position:
return TexGenAttrib::M_object_position;
case EggTexture::TG_eye_position:
return TexGenAttrib::M_eye_position;

View File

@ -4300,23 +4300,6 @@ finish_modify_state() {
}
break;
case TexGenAttrib::M_object_position:
GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
GLP(TexGenfv)(GL_S, GL_OBJECT_PLANE, s_data);
GLP(TexGenfv)(GL_T, GL_OBJECT_PLANE, t_data);
GLP(TexGenfv)(GL_R, GL_OBJECT_PLANE, r_data);
GLP(TexGenfv)(GL_Q, GL_OBJECT_PLANE, q_data);
GLP(Enable)(GL_TEXTURE_GEN_S);
GLP(Enable)(GL_TEXTURE_GEN_T);
GLP(Enable)(GL_TEXTURE_GEN_R);
GLP(Enable)(GL_TEXTURE_GEN_Q);
break;
case TexGenAttrib::M_eye_position:
// To represent eye position correctly, we need to temporarily
// load the coordinate-system transform.

View File

@ -330,12 +330,9 @@ public:
bool _supports_draw_range_elements;
PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;
bool _supports_3d_texture;
PFNGLTEXIMAGE3DPROC _glTexImage3D;
PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;
bool _supports_cube_map;
bool _supports_bgr;
bool _supports_rescale_normal;

View File

@ -1008,7 +1008,11 @@ release(PreparedGraphicsObjects *prepared_objects) {
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
TextureContext *tc = (*ci).second;
prepared_objects->release_texture(tc);
if (tc != (TextureContext *)NULL) {
prepared_objects->release_texture(tc);
} else {
_contexts.erase(ci);
}
return true;
}
@ -1036,12 +1040,14 @@ release_all() {
for (ci = temp.begin(); ci != temp.end(); ++ci) {
PreparedGraphicsObjects *prepared_objects = (*ci).first;
TextureContext *tc = (*ci).second;
prepared_objects->release_texture(tc);
if (tc != (TextureContext *)NULL) {
prepared_objects->release_texture(tc);
}
}
// Now that we've called release_texture() on every known context,
// the _contexts list should have completely emptied itself.
nassertr(_contexts.empty(), num_freed);
// There might still be some outstanding contexts in the map, if
// there were any NULL pointers there. Eliminate them.
_contexts.clear();
return num_freed;
}
@ -1163,9 +1169,9 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
}
TextureContext *tc = prepared_objects->prepare_texture_now(this, gsg);
if (tc != (TextureContext *)NULL) {
_contexts[prepared_objects] = tc;
_contexts[prepared_objects] = tc;
if (tc != (TextureContext *)NULL) {
// Now that we have a new TextureContext with zero dirty flags, our
// intersection of all dirty flags must be zero. This doesn't mean
// that some other contexts aren't still dirty, but at least one
@ -1213,7 +1219,10 @@ mark_dirty(int flags_to_set) {
// Otherwise, iterate through the contexts and mark them all dirty.
Contexts::iterator ci;
for (ci = _contexts.begin(); ci != _contexts.end(); ++ci) {
(*ci).second->mark_dirty(flags_to_set);
TextureContext *tc = (*ci).second;
if (tc != (TextureContext *)NULL) {
tc->mark_dirty(flags_to_set);
}
}
_all_dirty_flags |= flags_to_set;

View File

@ -99,8 +99,7 @@ PUBLISHED:
M_off,
// In the types below, "eye" means the coordinate space of the
// observing camera, "object" means the local coordinate space of
// the object, and "world" means world coordinates, e.g. the
// observing camera, and "world" means world coordinates, e.g. the
// coordinate space of the root of the graph.
// Sphere maps are classic static reflection maps. They are
@ -114,9 +113,8 @@ PUBLISHED:
// texture images. They can also be generated dynamically for
// real-time reflections (see GraphicsOutput::make_cube_map()).
// Typically, a statically-generated cube map will be in eye
// space, while a dynamically-generated map will be in world space
// or object space (depending on where the camera rig that
// generates the map is parented).
// space, while a dynamically-generated map will be in world
// space.
// Cube mapping is not supported on all hardware.
M_world_cube_map,
@ -131,7 +129,7 @@ PUBLISHED:
// coordinates. This is particularly useful for implementing
// projective texturing (see NodePath::project_texture()).
M_world_position,
M_object_position,
M_unused, // formerly M_object_position, now deprecated.
M_eye_position,
// With M_point_sprite, texture coordinates will be generated for

View File

@ -283,9 +283,6 @@ output(ostream &out) const {
case M_world_position:
out << "world_position";
break;
case M_object_position:
out << "object_position";
break;
case M_eye_position:
out << "eye_position";
break;
@ -298,6 +295,9 @@ output(ostream &out) const {
out << "light_vector: \"" << mode_def._source_name << "\", "
<< mode_def._light;
break;
case M_unused:
break;
}
out << ")";
}