From af49897d5e72adb259edb067c2bef6024000f663 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 20 Jul 2005 12:45:44 +0000 Subject: [PATCH] fix dx resize crash some more; first pass at dx cube map support --- panda/src/display/graphicsStateGuardian.I | 32 + panda/src/display/graphicsStateGuardian.cxx | 8 + panda/src/display/graphicsStateGuardian.h | 8 + panda/src/doc/eggSyntax.txt | 1 - panda/src/dxgsg8/dxGeomMunger8.cxx | 2 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 128 +++- panda/src/dxgsg8/dxTextureContext8.I | 37 +- panda/src/dxgsg8/dxTextureContext8.cxx | 563 ++++++++++++++---- panda/src/dxgsg8/dxTextureContext8.h | 14 +- panda/src/dxgsg8/wdxGraphicsWindow8.cxx | 2 +- panda/src/egg/eggTexture.cxx | 6 - panda/src/egg/eggTexture.h | 1 - panda/src/egg2pg/eggRenderState.cxx | 3 - .../glstuff/glGraphicsStateGuardian_src.cxx | 17 - .../src/glstuff/glGraphicsStateGuardian_src.h | 3 - panda/src/gobj/texture.cxx | 25 +- panda/src/pgraph/renderAttrib.h | 10 +- panda/src/pgraph/texGenAttrib.cxx | 6 +- 18 files changed, 653 insertions(+), 213 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 42c1574b05..5f7c54090b 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -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 diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index e99dbc2d66..08291a491a 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -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); } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 3137b7dcbe..2bc03746d4 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -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; diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index 7623d0c77a..d8464da0fb 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -295,7 +295,6 @@ appear before they are referenced. WORLD_NORMAL EYE_NORMAL WORLD_POSITION - OBJECT_POSITION EYE_POSITION POINT_SPRITE diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx index cfd398d455..e87a66bdbd 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ b/panda/src/dxgsg8/dxGeomMunger8.cxx @@ -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. diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index a2de9e56bd..9942a90b95 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -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 diff --git a/panda/src/dxgsg8/dxTextureContext8.I b/panda/src/dxgsg8/dxTextureContext8.I index f926378c41..791b5c3561 100644 --- a/panda/src/dxgsg8/dxTextureContext8.I +++ b/panda/src/dxgsg8/dxTextureContext8.I @@ -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; +} diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index eb12475f31..f053e3165d 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -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: " <get_name() << endl + << "NumColorChannels: " << num_color_channels << "; NumAlphaBits: " + << num_alpha_bits << "; targetbpp: " <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); diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index 17d7a57842..c6c5bdc2e1 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -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; diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx index a51f50cce0..34aa7fd029 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx @@ -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; diff --git a/panda/src/egg/eggTexture.cxx b/panda/src/egg/eggTexture.cxx index 9e843741f6..926e13a93e 100644 --- a/panda/src/egg/eggTexture.cxx +++ b/panda/src/egg/eggTexture.cxx @@ -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"; diff --git a/panda/src/egg/eggTexture.h b/panda/src/egg/eggTexture.h index 568d666191..ff56489140 100644 --- a/panda/src/egg/eggTexture.h +++ b/panda/src/egg/eggTexture.h @@ -140,7 +140,6 @@ PUBLISHED: TG_eye_normal, TG_world_position, - TG_object_position, TG_eye_position, TG_point_sprite, diff --git a/panda/src/egg2pg/eggRenderState.cxx b/panda/src/egg2pg/eggRenderState.cxx index 36d73bbf46..0716534edf 100644 --- a/panda/src/egg2pg/eggRenderState.cxx +++ b/panda/src/egg2pg/eggRenderState.cxx @@ -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; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 36a7882ebe..269f242ab0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -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. diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 131ef85429..40a44559bd 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -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; diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 035af2edfe..038718af74 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -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; diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 0bec58454a..c4781086b7 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -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 diff --git a/panda/src/pgraph/texGenAttrib.cxx b/panda/src/pgraph/texGenAttrib.cxx index 7c9a7ab2df..a51f9bfba2 100755 --- a/panda/src/pgraph/texGenAttrib.cxx +++ b/panda/src/pgraph/texGenAttrib.cxx @@ -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 << ")"; }