24#define DEBUG_SURFACES false
25#define DEBUG_TEXTURES true
33static const DWORD g_LowByteMask = 0x000000FF;
42 if (dxgsg9_cat.is_spam()) {
47 _d3d_texture =
nullptr;
48 _d3d_2d_texture =
nullptr;
49 _d3d_volume_texture =
nullptr;
50 _d3d_cube_texture =
nullptr;
52 _is_render_target =
false;
81 if (dxgsg9_cat.is_debug()) {
104 if (_d3d_2d_texture || _d3d_cube_texture || _d3d_volume_texture) {
111 D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
112 bool needs_luminance =
false;
113 bool needs_depth =
false;
114 bool needs_stencil =
false;
115 bool compress_texture =
false;
118 nassertr(IS_VALID_PTR(tex),
false);
128 bool texture_wants_compressed =
false;
130 bool texture_stored_compressed = compression_mode != Texture::CM_off;
132 if (texture_stored_compressed) {
133 texture_wants_compressed =
true;
140 if (compressed_textures) {
141 texture_wants_compressed =
true;
144 texture_wants_compressed =
true;
150 case Texture::TT_1d_texture:
151 case Texture::TT_2d_texture:
152 case Texture::TT_cube_map:
155 orig_width >= 4 && orig_height >= 4) {
156 if (texture_wants_compressed){
157 compress_texture =
true;
161 case Texture::TT_3d_texture:
166 if (texture_stored_compressed && !compress_texture) {
181 DWORD target_bpp = get_bits_per_pixel(tex->
get_format(), &num_alpha_bits);
187 case Texture::F_depth_stencil:
188 _d3d_format = D3DFMT_D24S8;
190 needs_stencil =
true;
193 case Texture::F_depth_component:
194 case Texture::F_depth_component16:
195 _d3d_format = D3DFMT_D16;
199 case Texture::F_depth_component24:
200 _d3d_format = D3DFMT_D24X8;
204 case Texture::F_depth_component32:
205 _d3d_format = D3DFMT_D32;
209 case Texture::F_luminance:
210 case Texture::F_sluminance:
211 _d3d_format = D3DFMT_L8;
212 needs_luminance =
true;
215 case Texture::F_luminance_alpha:
216 case Texture::F_luminance_alphamask:
217 case Texture::F_sluminance_alpha:
218 _d3d_format = D3DFMT_A8L8;
219 needs_luminance =
true;
223 if (num_alpha_bits > 0) {
224 if (num_color_channels == 3) {
226 <<
"texture " << tex->get_name()
227 <<
" has no inherent alpha channel, but alpha format is requested!\n";
231 _d3d_format = D3DFMT_UNKNOWN;
233 switch (num_color_channels) {
235 if (num_alpha_bits > 0) {
236 _d3d_format = D3DFMT_A8;
238 _d3d_format = D3DFMT_R32F;
240 _d3d_format = D3DFMT_L8;
244 _d3d_format = D3DFMT_A8L8;
247 _d3d_format = D3DFMT_R8G8B8;
251 _d3d_format = D3DFMT_A32B32G32R32F;
253 _d3d_format = D3DFMT_A8R8G8B8;
259 nassertr(_d3d_format != D3DFMT_UNKNOWN,
false);
262 DWORD target_width = orig_width;
263 DWORD target_height = orig_height;
264 DWORD target_depth = orig_depth;
269 case Texture::TT_1d_texture:
270 case Texture::TT_2d_texture:
271 filter_caps = scrn._d3dcaps.TextureFilterCaps;
273 if (target_width > scrn._d3dcaps.MaxTextureWidth) {
274 target_width = scrn._d3dcaps.MaxTextureWidth;
276 if (target_height > scrn._d3dcaps.MaxTextureHeight) {
277 target_height = scrn._d3dcaps.MaxTextureHeight;
280 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_POW2) {
281 if (!ISPOW2(target_width)) {
282 target_width = down_to_power_2(target_width);
284 if (!ISPOW2(target_height)) {
285 target_height = down_to_power_2(target_height);
290 case Texture::TT_3d_texture:
291 if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0) {
293 <<
"3-d textures are not supported by this graphics driver.\n";
297 filter_caps = scrn._d3dcaps.VolumeTextureFilterCaps;
299 if (target_width > scrn._d3dcaps.MaxVolumeExtent) {
300 target_width = scrn._d3dcaps.MaxVolumeExtent;
302 if (target_height > scrn._d3dcaps.MaxVolumeExtent) {
303 target_height = scrn._d3dcaps.MaxVolumeExtent;
305 if (target_depth > scrn._d3dcaps.MaxVolumeExtent) {
306 target_depth = scrn._d3dcaps.MaxVolumeExtent;
309 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) {
310 if (!ISPOW2(target_width)) {
311 target_width = down_to_power_2(target_width);
313 if (!ISPOW2(target_height)) {
314 target_height = down_to_power_2(target_height);
316 if (!ISPOW2(target_depth)) {
317 target_depth = down_to_power_2(target_depth);
322 case Texture::TT_cube_map:
323 if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0) {
325 <<
"Cube map textures are not supported by this graphics driver.\n";
329 filter_caps = scrn._d3dcaps.CubeTextureFilterCaps;
331 if (target_width > scrn._d3dcaps.MaxTextureWidth) {
332 target_width = scrn._d3dcaps.MaxTextureWidth;
335 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) {
336 if (!ISPOW2(target_width)) {
337 target_width = down_to_power_2(target_width);
341 target_height = target_width;
346 if ((target_width != target_height) &&
347 (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0) {
350 int i, width_exp, height_exp;
351 for (i = target_width, width_exp = 0; i > 1; width_exp++, i >>= 1) {
353 for (i = target_height, height_exp = 0; i > 1; height_exp++, i >>= 1) {
355 target_height = target_width = 1<<((width_exp+height_exp)>>1);
358 bool shrink_original =
false;
360 if (orig_width != target_width || orig_height != target_height ||
361 orig_depth != target_depth) {
364 <<
"Reducing size of " << tex->get_name()
365 <<
" from " << orig_width <<
"x" << orig_height <<
"x" << orig_depth
366 <<
" to " << target_width <<
"x" << target_height
367 <<
"x" << target_depth <<
"\n";
370 <<
"Reducing size of " << tex->get_name()
371 <<
" from " << orig_width <<
"x" << orig_height
372 <<
" to " << target_width <<
"x" << target_height <<
"\n";
375 shrink_original =
true;
378 if (target_width == 0 || target_height == 0) {
384 const char *error_message;
386 error_message =
"create_texture failed: couldn't find compatible device Texture Pixel Format for input texture";
388 if (dxgsg9_cat.is_spam()) {
390 <<
"create_texture handling target bitdepth: " << target_bpp
391 <<
" alphabits: " << num_alpha_bits << endl;
398#define CHECK_FOR_FMT(FMT) \
399 if (scrn._supported_tex_formats_mask & FMT##_FLAG) { \
400 target_pixel_format = D3DFMT_##FMT; \
401 goto found_matching_format; }
403 if (texture_stored_compressed && compress_texture) {
407 switch (compression_mode){
408 case Texture::CM_dxt1:
411 case Texture::CM_dxt2:
414 case Texture::CM_dxt3:
417 case Texture::CM_dxt4:
420 case Texture::CM_dxt5:
423 case Texture::CM_rgtc:
424 if (num_color_channels == 1) {
435 if (compress_texture) {
440 if (num_alpha_bits == 0 && !needs_luminance) {
441 if (num_color_channels == 1) {
442 if (scrn._supported_tex_formats_mask & ATI1_FLAG) {
444 target_pixel_format = D3DFMT_ATI1;
445 goto found_matching_format;
448 }
else if (num_color_channels == 2) {
449 if (scrn._supported_tex_formats_mask & ATI2_FLAG) {
451 target_pixel_format = D3DFMT_ATI2;
452 goto found_matching_format;
457 if (num_alpha_bits <= 1) {
459 }
else if (num_alpha_bits <= 4) {
468 if (texture_stored_compressed) {
471 texture_stored_compressed = compression_mode != Texture::CM_off;
472 compress_texture =
false;
477 switch (target_bpp) {
484 if (scrn._supports_rgba32_texture_format) {
485 target_pixel_format = D3DFMT_A32B32G32R32F;
488 target_pixel_format = scrn._render_to_texture_d3d_format;
490 goto found_matching_format;
494 if (scrn._supports_rgba16f_texture_format) {
495 target_pixel_format = D3DFMT_A16B16G16R16F;
498 target_pixel_format = scrn._render_to_texture_d3d_format;
500 goto found_matching_format;
504 nassertr(num_alpha_bits == 0,
false);
505 nassertr(num_color_channels == 1,
false);
511 if (num_color_channels == 1) {
513 CHECK_FOR_FMT(X8R8G8B8);
514 CHECK_FOR_FMT(R8G8B8);
518 if (!((num_color_channels == 3) || (num_color_channels == 4)))
521 CHECK_FOR_FMT(A8R8G8B8);
523 if (num_alpha_bits>0) {
524 nassertr(num_color_channels == 4,
false);
540 if (num_alpha_bits == 1) {
541 CHECK_FOR_FMT(A1R5G5B5);
545 CHECK_FOR_FMT(A4R4G4B4);
546 CHECK_FOR_FMT(A1R5G5B5);
550 error_message =
"create_texture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!";
554 if (num_color_channels == 3) {
555 CHECK_FOR_FMT(R5G6B5);
556 CHECK_FOR_FMT(X1R5G5B5);
558 CHECK_FOR_FMT(R5G6B5);
559 CHECK_FOR_FMT(X1R5G5B5);
566 nassertr(num_alpha_bits == 0,
false);
567 nassertr(num_color_channels == 1,
false);
574 CHECK_FOR_FMT(D24S8);
576 CHECK_FOR_FMT(D24X8);
580 if (scrn._supported_tex_formats_mask & INTZ_FLAG) {
581 target_pixel_format = D3DFMT_INTZ;
582 goto found_matching_format;
588 CHECK_FOR_FMT(D24X8);
591 nassertr(num_color_channels == 3,
false);
593 CHECK_FOR_FMT(R8G8B8);
598 CHECK_FOR_FMT(X8R8G8B8);
599 CHECK_FOR_FMT(A8R8G8B8);
602 CHECK_FOR_FMT(R5G6B5);
603 CHECK_FOR_FMT(X1R5G5B5);
604 CHECK_FOR_FMT(A1R5G5B5);
610 nassertr(num_alpha_bits == 0,
false);
611 nassertr(num_color_channels == 1,
false);
618 CHECK_FOR_FMT(D24S8);
621 CHECK_FOR_FMT(D24X8);
624 if (scrn._supported_tex_formats_mask & INTZ_FLAG) {
625 target_pixel_format = D3DFMT_INTZ;
626 goto found_matching_format;
632 CHECK_FOR_FMT(D24X8);
635 }
else if (needs_luminance) {
636 nassertr(num_alpha_bits > 0,
false);
637 nassertr(num_color_channels == 2,
false);
640 CHECK_FOR_FMT(A8R8G8B8);
642 if (num_alpha_bits == 1) {
643 CHECK_FOR_FMT(A1R5G5B5);
647 CHECK_FOR_FMT(A4R4G4B4);
648 CHECK_FOR_FMT(A1R5G5B5);
650 nassertr((num_color_channels == 3)||(num_color_channels == 4),
false);
653 switch(num_alpha_bits) {
655 if (num_color_channels == 3) {
656 CHECK_FOR_FMT(R5G6B5);
657 CHECK_FOR_FMT(X1R5G5B5);
659 nassertr(num_color_channels == 4,
false);
661 CHECK_FOR_FMT(R5G6B5);
662 CHECK_FOR_FMT(X1R5G5B5);
669 nassertr(num_color_channels == 4,
false);
670 CHECK_FOR_FMT(X1R5G5B5);
675 nassertr(num_color_channels == 4,
false);
676 CHECK_FOR_FMT(A4R4G4B4);
679 nassertr(
false,
false);
683 if (num_alpha_bits == 8) {
692 CHECK_FOR_FMT(A8R8G8B8);
693 CHECK_FOR_FMT(A4R4G4B4);
695 if (needs_luminance) {
698 nassertr(num_color_channels == 1,
false);
704 CHECK_FOR_FMT(R8G8B8);
705 CHECK_FOR_FMT(X8R8G8B8);
707 CHECK_FOR_FMT(R5G6B5);
708 CHECK_FOR_FMT(X1R5G5B5);
713 error_message =
"create_texture failed: unhandled pixel bitdepth in DX loader";
718 << error_message <<
": " << tex->get_name() << endl
719 <<
"NumColorChannels: " << num_color_channels <<
"; NumAlphaBits: "
720 << num_alpha_bits <<
"; targetbpp: " <<target_bpp
721 <<
"; _supported_tex_formats_mask: 0x"
722 << std::hex << scrn._supported_tex_formats_mask << std::dec
723 <<
"; NeedLuminance: " << needs_luminance << endl;
727 found_matching_format:
734 IDirect3DSurface9 *render_target;
737 hr = scrn._d3d_device->GetDepthStencilSurface(&render_target);
739 hr = scrn._d3d_device->GetRenderTarget(0, &render_target);
743 <<
"GetRenderTgt failed in create_texture: " << D3DERRORSTRING(hr);
745 D3DSURFACE_DESC surface_desc;
746 hr = render_target->GetDesc(&surface_desc);
749 <<
"GetDesc failed in create_texture: " << D3DERRORSTRING(hr);
751 if (target_pixel_format != surface_desc.Format &&
752 target_pixel_format != D3DFMT_INTZ) {
753 if (dxgsg9_cat.is_debug()) {
755 <<
"Chose format " << D3DFormatStr(surface_desc.Format)
756 <<
" instead of " << D3DFormatStr(target_pixel_format)
757 <<
" for texture to match framebuffer.\n";
759 target_pixel_format = surface_desc.Format;
762 SAFE_RELEASE(render_target);
768 SamplerState::FilterType ft;
771 if ((ft != SamplerState::FT_linear) && ft != SamplerState::FT_nearest) {
773 if (ft == SamplerState::FT_nearest_mipmap_nearest) {
774 ft = SamplerState::FT_nearest;
776 ft = SamplerState::FT_linear;
780 if (ft == SamplerState::FT_linear &&
781 (filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) {
782 ft = SamplerState::FT_nearest;
788 _has_mipmaps =
false;
790 if (!dx_ignore_mipmaps) {
792 case SamplerState::FT_nearest_mipmap_nearest:
793 case SamplerState::FT_linear_mipmap_nearest:
794 case SamplerState::FT_nearest_mipmap_linear:
795 case SamplerState::FT_linear_mipmap_linear:
799 if (dx_mipmap_everything) {
801 if (dxgsg9_cat.is_spam()) {
802 if (ft != SamplerState::FT_linear_mipmap_linear) {
804 <<
"Forcing trilinear mipmapping on DX texture ["
805 << tex->get_name() <<
"]\n";
808 ft = SamplerState::FT_linear_mipmap_linear;
812 }
else if ((ft == SamplerState::FT_nearest_mipmap_nearest) ||
813 (ft == SamplerState::FT_nearest_mipmap_linear)) {
814 ft = SamplerState::FT_nearest;
816 }
else if ((ft == SamplerState::FT_linear_mipmap_nearest) ||
817 (ft == SamplerState::FT_linear_mipmap_linear)) {
818 ft = SamplerState::FT_linear;
821 nassertr((filter_caps & D3DPTFILTERCAPS_MINFPOINT) != 0,
false);
823#define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR)
827 case SamplerState::FT_linear_mipmap_linear:
828 if ((filter_caps & TRILINEAR_MIPMAP_TEXFILTERCAPS) != TRILINEAR_MIPMAP_TEXFILTERCAPS) {
829 if (filter_caps & D3DPTFILTERCAPS_MINFLINEAR) {
830 ft = SamplerState::FT_linear_mipmap_nearest;
834 ft = SamplerState::FT_nearest_mipmap_nearest;
839 case SamplerState::FT_nearest_mipmap_linear:
841 if (!((filter_caps & D3DPTFILTERCAPS_MIPFPOINT) &&
842 (filter_caps & D3DPTFILTERCAPS_MINFLINEAR))) {
843 ft = SamplerState::FT_nearest_mipmap_nearest;
847 case SamplerState::FT_linear_mipmap_nearest:
849 if (!(filter_caps & D3DPTFILTERCAPS_MIPFLINEAR)) {
850 ft = SamplerState::FT_nearest_mipmap_nearest;
854 case SamplerState::FT_linear:
855 if (!(filter_caps & D3DPTFILTERCAPS_MINFLINEAR)) {
856 ft = SamplerState::FT_nearest;
866 if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
868 if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) ||
869 dx_force_anisotropic_filtering) {
870 aniso_degree = scrn._d3dcaps.MaxAnisotropy;
877 <<
"create_texture: setting aniso degree for " << tex->get_name()
878 <<
" to: " << aniso_degree << endl;
881 UINT mip_level_count;
886 if (mip_level_count < 2) {
890 if (dxgsg9_cat.is_debug()) {
892 <<
"create_texture: generating mipmaps for " << tex->get_name()
899 if (target_pixel_format == D3DFMT_ATI1 ||
900 target_pixel_format == D3DFMT_ATI2) {
902 UINT dimension = min(target_height, target_width);
904 while (dimension >= 4) {
925 _is_render_target =
true;
927 pool = D3DPOOL_DEFAULT;
929 usage = D3DUSAGE_DEPTHSTENCIL;
931 usage = D3DUSAGE_RENDERTARGET;
937 <<
"*** RENDER TO TEXTURE ***: format "
938 << D3DFormatStr(target_pixel_format)
940 << target_pixel_format
944 _managed = scrn._managed_textures;
946 pool = D3DPOOL_MANAGED;
950 if (scrn._supports_automatic_mipmap_generation) {
951 pool = D3DPOOL_DEFAULT;
952 usage = D3DUSAGE_AUTOGENMIPMAP;
955 if (dx_use_dynamic_textures) {
956 if (scrn._supports_dynamic_textures) {
957 pool = D3DPOOL_DEFAULT;
958 usage = D3DUSAGE_DYNAMIC;
964 pool = D3DPOOL_MANAGED;
969 pool = D3DPOOL_DEFAULT;
976 PN_stdfloat bytes_per_texel;
978 bytes_per_texel =
this -> d3d_format_to_bytes_per_pixel (target_pixel_format);
979 if (bytes_per_texel == 0.0f) {
981 <<
"D3D create_texture ( ) unknown texture format\n";
986 data_size = target_width * target_height * target_depth;
988 data_size = (int) ((PN_stdfloat) data_size * 1.3333333);
990 data_size = (int) ((PN_stdfloat) data_size * bytes_per_texel);
998 if (dxgsg9_cat.is_debug()) {
1000 <<
"Creating " << *tex <<
", " << data_size <<
" bytes, "
1001 << scrn._d3d_device->GetAvailableTextureMem()
1002 <<
" reported available.\n";
1004 <<
" size is " << target_width <<
" w * " << target_height <<
" h * "
1005 << target_depth <<
" d";
1007 dxgsg9_cat.debug(
false)
1008 <<
" * 1.3333333 mipmaps";
1010 dxgsg9_cat.debug(
false)
1011 <<
" * " << bytes_per_texel <<
" bpt";
1013 dxgsg9_cat.debug(
false)
1016 dxgsg9_cat.debug(
false)
1024 case Texture::TT_1d_texture:
1025 case Texture::TT_2d_texture:
1026 hr = scrn._d3d_device->CreateTexture
1027 (target_width, target_height, mip_level_count, usage,
1028 target_pixel_format, pool, &_d3d_2d_texture,
nullptr);
1029 _d3d_texture = _d3d_2d_texture;
1032 case Texture::TT_3d_texture:
1033 hr = scrn._d3d_device->CreateVolumeTexture
1034 (target_width, target_height, target_depth, mip_level_count, usage,
1035 target_pixel_format, pool, &_d3d_volume_texture,
nullptr);
1036 _d3d_texture = _d3d_volume_texture;
1039 case Texture::TT_cube_map:
1040 hr = scrn._d3d_device->CreateCubeTexture
1041 (target_width, mip_level_count, usage,
1042 target_pixel_format, pool, &_d3d_cube_texture,
nullptr);
1043 _d3d_texture = _d3d_cube_texture;
1045 target_height = target_width;
1050 }
while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
1054 <<
"D3D create_texture failed!" << D3DERRORSTRING(hr);
1056 <<
" width = " << target_width <<
" height = " << target_height <<
" target_pixel_format = " << target_pixel_format <<
"\n";
1061 if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
1063 <<
"create_texture: " << tex->get_name()
1064 <<
" converting panda equivalent of " << D3DFormatStr(_d3d_format)
1065 <<
" => " << D3DFormatStr(target_pixel_format) << endl;
1068 hr = fill_d3d_texture_pixels(scrn, compress_texture);
1072 <<
"*** fill_d3d_texture_pixels failed ***: format "
1073 << target_pixel_format
1086 if (record !=
nullptr) {
1088 cache->
store(record);
1104 RELEASE(_d3d_texture, dxgsg9,
"texture", RELEASE_ONCE);
1105 _d3d_2d_texture =
nullptr;
1106 _d3d_volume_texture =
nullptr;
1107 _d3d_cube_texture =
nullptr;
1114bool DXTextureContext9::
1122 _d3d_format = D3DFMT_A8R8G8B8;
1123 D3DFORMAT target_pixel_format = D3DFMT_A8R8G8B8;
1124 DWORD target_bpp = 32;
1125 DWORD num_color_channels = 4;
1129 DWORD mip_level_count = 1;
1131 D3DPOOL pool = D3DPOOL_MANAGED;
1133 int data_size = target_width * target_height * 4;
1135 hr = scrn._d3d_device->CreateTexture
1136 (target_width, target_height, mip_level_count, usage,
1137 target_pixel_format, pool, &_d3d_2d_texture,
nullptr);
1138 _d3d_texture = _d3d_2d_texture;
1141 <<
"D3D create_simple_texture failed!" << D3DERRORSTRING(hr);
1143 <<
" width = " << target_width <<
" height = " << target_height <<
" target_pixel_format = " << target_pixel_format <<
"\n";
1148 if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
1150 <<
"create_simple_texture: " <<
get_texture()->get_name()
1160 IDirect3DSurface9 *surface =
nullptr;
1161 _d3d_2d_texture->GetSurfaceLevel(0, &surface);
1164 source_size.left = source_size.top = 0;
1165 source_size.right = target_width;
1166 source_size.bottom = target_height;
1168 DWORD mip_filter = D3DX_FILTER_LINEAR;
1170 hr = D3DXLoadSurfaceFromMemory
1171 (surface,
nullptr,
nullptr, (LPCVOID)image.
p(),
1172 target_pixel_format, target_width * 4,
nullptr,
1173 &source_size, mip_filter, (D3DCOLOR)0x0);
1175 RELEASE(surface, dxgsg9,
"create_simple_texture Surface", RELEASE_ONCE);
1180 <<
"*** fill_d3d_texture_pixels failed ***: format "
1181 << target_pixel_format
1191 RELEASE(_d3d_texture, dxgsg9,
"texture", RELEASE_ONCE);
1192 _d3d_2d_texture =
nullptr;
1193 _d3d_volume_texture =
nullptr;
1194 _d3d_cube_texture =
nullptr;
1204 if (_d3d_texture ==
nullptr) {
1209 RELEASE(_d3d_texture, dxgsg9,
"texture", RELEASE_ONCE);
1210 _d3d_2d_texture =
nullptr;
1211 _d3d_volume_texture =
nullptr;
1212 _d3d_cube_texture =
nullptr;
1233 nassertr(IS_VALID_PTR(_d3d_2d_texture),
false);
1235 D3DSURFACE_DESC desc;
1236 hr = _d3d_2d_texture->GetLevelDesc(0, &desc);
1239 <<
"Texture::GetLevelDesc() failed!" << D3DERRORSTRING(hr);
1244 Texture::Format format = Texture::F_rgba;
1245 Texture::CompressionMode compression = Texture::CM_off;
1247 switch (desc.Format) {
1249 format = Texture::F_rgb;
1252 case D3DFMT_A8R8G8B8:
1253 case D3DFMT_X8R8G8B8:
1257 format = Texture::F_luminance;
1261 format = Texture::F_luminance_alpha;
1265 format = Texture::F_depth_stencil;
1269 format = Texture::F_depth_component16;
1273 format = Texture::F_depth_component24;
1277 format = Texture::F_depth_component32;
1281 compression = Texture::CM_dxt1;
1285 compression = Texture::CM_dxt2;
1289 compression = Texture::CM_dxt3;
1293 compression = Texture::CM_dxt4;
1297 compression = Texture::CM_dxt5;
1302 compression = Texture::CM_rgtc;
1308 <<
"Cannot extract texture data: unhandled surface format "
1309 << desc.Format <<
"\n";
1313 int num_levels = _d3d_2d_texture->GetLevelCount();
1322 if (_is_render_target) {
1323 IDirect3DSurface9* source_surface;
1324 IDirect3DSurface9* destination_surface;
1327 destination_surface = 0;
1329 hr = _d3d_2d_texture -> GetSurfaceLevel (0, &source_surface);
1333 D3DSURFACE_DESC surface_description;
1335 pool = D3DPOOL_SYSTEMMEM;
1336 source_surface -> GetDesc (&surface_description);
1338 hr = screen._d3d_device->CreateOffscreenPlainSurface (
1339 surface_description.Width,
1340 surface_description.Height,
1341 surface_description.Format,
1343 &destination_surface,
1346 if (source_surface && destination_surface) {
1347 hr = screen._d3d_device -> GetRenderTargetData (source_surface, destination_surface);
1350 D3DLOCKED_RECT rect;
1352 hr = destination_surface -> LockRect (&rect,
nullptr, D3DLOCK_READONLY);
1359 int surface_bytes_per_line;
1360 unsigned char *surface_pointer;
1362 bytes_per_line = surface_description.Width *
this -> d3d_format_to_bytes_per_pixel (surface_description.Format);
1363 size = bytes_per_line * surface_description.Height;
1365 surface_bytes_per_line = rect.Pitch;
1366 surface_pointer = (
unsigned char *) rect.pBits;
1368 PTA_uchar image = PTA_uchar::empty_array(size);
1373 for (y = 0; y < surface_description.Height; y++)
1375 memcpy (&image [offset], surface_pointer, bytes_per_line);
1377 offset += bytes_per_line;
1378 surface_pointer += surface_bytes_per_line;
1385 destination_surface -> UnlockRect();
1390 destination_surface -> Release ( );
1394 <<
"CreateImageSurface failed in extract_texture_data()"
1395 << D3DERRORSTRING(hr);
1397 source_surface -> Release ( );
1401 for (
int n = 0; n < num_levels; ++n) {
1402 D3DLOCKED_RECT rect;
1403 hr = _d3d_2d_texture->LockRect(n, &rect,
nullptr, D3DLOCK_READONLY);
1406 <<
"Texture::LockRect() failed! level = " << n <<
" " << D3DERRORSTRING(hr);
1414 if (compression == Texture::CM_off) {
1417 pitch = min(pitch, (
int)rect.Pitch);
1418 int size = pitch * y_size;
1419 image = PTA_uchar::empty_array(size);
1420 if (pitch == rect.Pitch) {
1422 memcpy(image.p(), rect.pBits, size);
1426 unsigned char *dest = image.p();
1427 unsigned char *source = (
unsigned char *)rect.pBits;
1428 for (
int yi = 0; yi < y_size; ++yi) {
1429 memcpy(dest, source, pitch);
1431 source += rect.Pitch;
1437 int size = rect.Pitch * (y_size / div);
1438 image = PTA_uchar::empty_array(size);
1439 memcpy(image.p(), rect.pBits, size);
1442 _d3d_2d_texture->UnlockRect(n);
1461 bool inverted,
Texture *result,
int view,
int z) {
1471 nassertr((num_components == 3) || (num_components == 4), E_FAIL);
1472 nassertr(IS_VALID_PTR(d3d_surface), E_FAIL);
1476 nassertr(z < result->get_z_size(), E_FAIL);
1483 if (IsBadWritePtr(d3d_surface,
sizeof(DWORD))) {
1485 <<
"d3d_surface_to_texture failed: bad pD3DSurf ptr value ("
1486 << ((
void*)d3d_surface) <<
")\n";
1490 DWORD x_window_offset, y_window_offset;
1491 DWORD copy_width, copy_height;
1493 D3DLOCKED_RECT locked_rect;
1494 D3DSURFACE_DESC surface_desc;
1496 hr = d3d_surface->GetDesc(&surface_desc);
1498 x_window_offset = source_rect.left, y_window_offset = source_rect.top;
1499 copy_width = RECT_XSIZE(source_rect);
1500 copy_height = RECT_YSIZE(source_rect);
1507 <<
"d3d_surface_to_texture, Texture size (" << result->
get_x_size()
1509 <<
") too small to hold display surface ("
1510 << copy_width <<
", " << copy_height <<
")\n";
1511 nassertr(
false, E_FAIL);
1515 hr = d3d_surface->LockRect(&locked_rect,
nullptr, (D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE));
1518 <<
"d3d_surface_to_texture LockRect() failed!" << D3DERRORSTRING(hr);
1523 nassertr((surface_desc.Format == D3DFMT_A8R8G8B8) ||
1524 (surface_desc.Format == D3DFMT_X8R8G8B8) ||
1525 (surface_desc.Format == D3DFMT_R8G8B8) ||
1526 (surface_desc.Format == D3DFMT_R5G6B5) ||
1527 (surface_desc.Format == D3DFMT_X1R5G5B5) ||
1528 (surface_desc.Format == D3DFMT_A1R5G5B5) ||
1529 (surface_desc.Format == D3DFMT_A4R4G4B4), E_FAIL);
1533 int byte_pitch = locked_rect.Pitch;
1534 BYTE *surface_bytes = (BYTE *)locked_rect.pBits;
1537 surface_bytes += byte_pitch * (y_window_offset + copy_height - 1);
1538 byte_pitch = -byte_pitch;
1540 surface_bytes += byte_pitch * y_window_offset;
1546 if (DEBUG_SURFACES && dxgsg9_cat.is_debug()) {
1548 <<
"d3d_surface_to_texture converting "
1549 << D3DFormatStr(surface_desc.Format)
1550 <<
" DDSurf to " << num_components <<
"-channel panda Texture\n";
1553 DWORD *dest_word = (DWORD *)buf;
1554 BYTE *dest_byte = (BYTE *)buf;
1556 switch(surface_desc.Format) {
1557 case D3DFMT_A8R8G8B8:
1558 case D3DFMT_X8R8G8B8: {
1559 if (num_components == 4) {
1561 BYTE *dest_line = (BYTE*)dest_word;
1563 for (DWORD y = 0; y < copy_height; y++) {
1564 source_word = ((DWORD*)surface_bytes) + x_window_offset;
1565 memcpy(dest_line, source_word, copy_width * 4);
1566 dest_line += copy_width * 4;
1567 surface_bytes += byte_pitch;
1572 for (DWORD y = 0; y < copy_height; y++) {
1573 source_word = ((DWORD*)surface_bytes) + x_window_offset;
1575 for (DWORD x = 0; x < copy_width; x++) {
1577 DWORD
pixel = *source_word;
1579 r = (BYTE)((
pixel>>16) & g_LowByteMask);
1580 g = (BYTE)((
pixel>> 8) & g_LowByteMask);
1581 b = (BYTE)((
pixel ) & g_LowByteMask);
1588 surface_bytes += byte_pitch;
1594 case D3DFMT_R8G8B8: {
1597 if (num_components == 4) {
1598 for (DWORD y = 0; y < copy_height; y++) {
1599 source_byte = surface_bytes + x_window_offset * 3 *
sizeof(BYTE);
1600 for (DWORD x = 0; x < copy_width; x++) {
1607 *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b;
1610 surface_bytes += byte_pitch;
1614 for (DWORD y = 0; y < copy_height; y++) {
1615 source_byte = surface_bytes + x_window_offset * 3 *
sizeof(BYTE);
1616 memcpy(dest_byte, source_byte, copy_width * 3);
1617 dest_byte += copy_width * 3;
1618 surface_bytes += byte_pitch;
1625 case D3DFMT_X1R5G5B5:
1626 case D3DFMT_A1R5G5B5:
1627 case D3DFMT_A4R4G4B4: {
1631 BYTE redshift, greenshift, blueshift;
1632 DWORD redmask, greenmask, bluemask;
1634 if (surface_desc.Format == D3DFMT_R5G6B5) {
1641 }
else if (surface_desc.Format == D3DFMT_A4R4G4B4) {
1657 if (num_components == 4) {
1664 for (DWORD y = 0; y < copy_height; y++) {
1665 source_word = ((WORD*)surface_bytes) + x_window_offset;
1666 for (DWORD x = 0; x < copy_width; x++) {
1667 WORD
pixel = *source_word;
1670 b = (
pixel & bluemask) << blueshift;
1671 g = (
pixel & greenmask) >> greenshift;
1672 r = (
pixel & redmask) >> redshift;
1676 *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b;
1680 surface_bytes += byte_pitch;
1684 for (DWORD y = 0; y < copy_height; y++) {
1685 source_word = ((WORD*)surface_bytes) + x_window_offset;
1686 for (DWORD x = 0; x < copy_width; x++) {
1687 WORD
pixel = *source_word;
1690 b = (
pixel & bluemask) << blueshift;
1691 g = (
pixel & greenmask) >> greenshift;
1692 r = (
pixel & redmask) >> redshift;
1700 surface_bytes += byte_pitch;
1708 <<
"d3d_surface_to_texture: unsupported D3DFORMAT!\n";
1711 d3d_surface->UnlockRect();
1720static UINT calculate_row_byte_length (
int width,
int num_color_channels, D3DFORMAT tex_format)
1722 UINT source_row_byte_length = 0;
1726 switch (tex_format) {
1732 source_row_byte_length = max(1,width / 4)*8;
1740 source_row_byte_length = max(1,width / 4)*16;
1744 source_row_byte_length = width*num_color_channels;
1747 return source_row_byte_length;
1755HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(
int mip_level,
int depth_index, D3DFORMAT source_format)
1759 IDirect3DSurface9 *mip_surface =
nullptr;
1760 bool using_temp_buffer =
false;
1761 HRESULT hr = E_FAIL;
1763 BYTE *pixels = (BYTE*) image.
p();
1770 vector_uchar clear_data;
1771 if (page_size > 0) {
1775 nassertr(!image.
is_null(), E_FAIL);
1776 pixels = (BYTE *)image.
p();
1778 view_size = image.size();
1780 pixels += page_size * depth_index;
1786 pixels = clear_data.data();
1787 view_size = clear_data.size();
1790 if (
get_texture()->get_texture_type() == Texture::TT_cube_map) {
1791 nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
1792 hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)depth_index, mip_level, &mip_surface);
1794 nassertr(IS_VALID_PTR(_d3d_2d_texture), E_FAIL);
1795 hr = _d3d_2d_texture->GetSurfaceLevel(mip_level, &mip_surface);
1800 <<
"FillDDTextureMipmapPixels failed for " <<
get_texture()->get_name()
1801 <<
", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
1806 source_size.left = source_size.top = 0;
1807 source_size.right = width;
1808 source_size.bottom = height;
1810 UINT source_row_byte_length = calculate_row_byte_length(width,
get_texture()->get_num_components(), source_format);
1815 mip_filter = D3DX_FILTER_LINEAR ;
1818 mip_filter |= D3DX_FILTER_SRGB;
1823 if (_d3d_format == D3DFMT_A8) {
1825 USHORT *temp_buffer =
new USHORT[width * height];
1826 if (!IS_VALID_PTR(temp_buffer)) {
1828 <<
"FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
1829 goto exit_FillMipmapSurf;
1831 using_temp_buffer =
true;
1833 USHORT *out_pixels = temp_buffer;
1834 BYTE *source_pixels = pixels + component_width - 1;
1835 for (UINT y = 0; y < height; y++) {
1836 for (UINT x = 0; x < width; x++, source_pixels += component_width, out_pixels++) {
1839 *out_pixels = ((*source_pixels) << 8 ) | 0xFF;
1843 source_format = D3DFMT_A8L8;
1844 source_row_byte_length = width *
sizeof(USHORT);
1845 pixels = (BYTE*)temp_buffer;
1847 else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) {
1848 size_t total_components = (size_t)width * (
size_t)height * 4;
1849 float *temp_buffer =
new float[total_components];
1850 if (!IS_VALID_PTR(temp_buffer)) {
1852 <<
"FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
1853 goto exit_FillMipmapSurf;
1855 using_temp_buffer =
true;
1858 float *out_pixels = (
float *)temp_buffer;
1859 const float *source_pixels = (
const float *)pixels;
1860 for (
size_t i = 0; i < total_components; i += 4) {
1861 out_pixels[i] = source_pixels[i + 2];
1862 out_pixels[i + 1] = source_pixels[i + 1];
1863 out_pixels[i + 2] = source_pixels[i + 0];
1864 out_pixels[i + 3] = source_pixels[i + 3];
1866 pixels = (BYTE*)temp_buffer;
1868 else if (component_width != 1 && _d3d_format != D3DFMT_R32F) {
1874 int num_pixels = width * height * num_components;
1875 BYTE *temp_buffer =
new BYTE[num_pixels];
1876 if (!IS_VALID_PTR(temp_buffer)) {
1877 dxgsg9_cat.error() <<
"FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
1878 goto exit_FillMipmapSurf;
1880 using_temp_buffer =
true;
1882 BYTE *source_pixels = pixels + component_width - 1;
1883 for (
int i = 0; i < num_pixels; i++) {
1884 temp_buffer[i] = *source_pixels;
1885 source_pixels += component_width;
1887 pixels = (BYTE*)temp_buffer;
1892 GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_row_byte_length * height);
1894 if (source_format == D3DFMT_ATI1 || source_format == D3DFMT_ATI2) {
1896 D3DLOCKED_RECT rect;
1897 _d3d_2d_texture->LockRect(mip_level, &rect, 0, D3DLOCK_DISCARD);
1899 unsigned char *dest = (
unsigned char *)rect.pBits;
1900 memcpy(dest, pixels, view_size);
1902 _d3d_2d_texture->UnlockRect(mip_level);
1905 hr = D3DXLoadSurfaceFromMemory
1906 (mip_surface,
nullptr,
nullptr, (LPCVOID)pixels,
1907 source_format, source_row_byte_length,
nullptr,
1908 &source_size, mip_filter, (D3DCOLOR)0x0);
1911 <<
"FillDDTextureMipmapPixels failed for " <<
get_texture()->get_name()
1912 <<
", mip_level " << mip_level
1913 <<
", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
1918 if (using_temp_buffer) {
1919 SAFE_DELETE_ARRAY(pixels);
1922 RELEASE(mip_surface, dxgsg9,
"FillDDTextureMipmapPixels MipSurface texture ptr", RELEASE_ONCE);
1929HRESULT DXTextureContext9::
1930fill_d3d_texture_pixels(
DXScreenData &scrn,
bool compress_texture) {
1931 IDirect3DDevice9 *device = scrn._d3d_device;
1933 nassertr(IS_VALID_PTR(tex), E_FAIL);
1935 return fill_d3d_volume_texture_pixels(scrn);
1938 HRESULT hr = E_FAIL;
1941 Texture::CompressionMode image_compression = Texture::CM_off;
1942 if (compress_texture) {
1962 if (_d3d_2d_texture) {
1964 IDirect3DSurface9 *surface;
1966 result = _d3d_2d_texture -> GetSurfaceLevel (0, &surface);
1967 if (result == D3D_OK) {
1968 D3DSURFACE_DESC surface_description;
1970 if (surface -> GetDesc (&surface_description) == D3D_OK) {
1971 IDirect3DSurface9 *current_render_target;
1973 if (device -> GetRenderTarget (0, ¤t_render_target) == D3D_OK) {
1974 IDirect3DSurface9 *depth_stencil_surface;
1977 depth_stencil_surface = 0;
1978 if (device -> GetDepthStencilSurface (&depth_stencil_surface) == D3D_OK) {
1979 if (device -> SetDepthStencilSurface (
nullptr) == D3D_OK) {
1984 if (device -> SetRenderTarget (0, surface) == D3D_OK) {
1988 LColor scaled = tex->
get_clear_color().fmin(LColor(1)).fmax(LColor::zero());
1990 color = D3DCOLOR_RGBA((
int)scaled[0], (
int)scaled[1], (
int)scaled[2], (
int)scaled[3]);
1991 flags = D3DCLEAR_TARGET;
1992 if (device -> Clear (0,
nullptr, flags, color, 0.0f, 0) == D3D_OK) {
1997 if (depth_stencil_surface) {
1998 device -> SetDepthStencilSurface (depth_stencil_surface);
1999 depth_stencil_surface -> Release();
2003 device -> SetRenderTarget (0, current_render_target);
2004 current_render_target -> Release();
2008 surface -> Release();
2016 nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
2018 PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
2020 DWORD orig_depth = (DWORD) tex->
get_z_size();
2021 D3DFORMAT source_format = _d3d_format;
2024 switch (image_compression) {
2025 case Texture::CM_dxt1:
2026 source_format = D3DFMT_DXT1;
2028 case Texture::CM_dxt2:
2029 source_format = D3DFMT_DXT2;
2031 case Texture::CM_dxt3:
2032 source_format = D3DFMT_DXT3;
2034 case Texture::CM_dxt4:
2035 source_format = D3DFMT_DXT4;
2037 case Texture::CM_dxt5:
2038 source_format = D3DFMT_DXT5;
2040 case Texture::CM_rgtc:
2042 source_format = D3DFMT_ATI1;
2044 source_format = D3DFMT_ATI2;
2052 for (
unsigned int di = 0; di < orig_depth; di++) {
2055 hr = fill_d3d_texture_mipmap_pixels(0, di, source_format);
2063 int miplevel_count = _d3d_texture->GetLevelCount();
2064 if (miplevel_count <= tex->get_num_loadable_ram_mipmap_images()) {
2066 <<
"Using pre-calculated mipmap levels for texture " << tex->get_name() <<
"\n";
2068 for (
int mip_level = 1; mip_level < miplevel_count; ++mip_level) {
2069 hr = fill_d3d_texture_mipmap_pixels(mip_level, di, source_format);
2078 if (_managed ==
false && scrn._supports_automatic_mipmap_generation) {
2085 hr = _d3d_texture -> SetAutoGenFilterType (D3DTEXF_LINEAR);
2087 dxgsg9_cat.error() <<
"SetAutoGenFilterType failed " << D3DERRORSTRING(hr);
2090 _d3d_texture -> GenerateMipSubLevels ( );
2094 DWORD mip_filter_flags;
2095 if (!dx_use_triangle_mipgen_filter) {
2096 mip_filter_flags = D3DX_FILTER_BOX;
2098 mip_filter_flags = D3DX_FILTER_TRIANGLE;
2102 mip_filter_flags |= D3DX_FILTER_SRGB;
2106 hr = D3DXFilterTexture(_d3d_texture,
nullptr, 0,
2111 <<
"FillDDSurfaceTexturePixels failed for " << tex->get_name()
2112 <<
", D3DXFilterTex failed" << D3DERRORSTRING(hr);
2126HRESULT DXTextureContext9::
2129 HRESULT hr = E_FAIL;
2130 nassertr(IS_VALID_PTR(tex), E_FAIL);
2139 Texture::CompressionMode image_compression;
2141 image_compression = Texture::CM_off;
2148 image_compression = Texture::CM_off;
2157 PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
2159 nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
2162 DWORD orig_width = (DWORD) tex->
get_x_size();
2163 DWORD orig_height = (DWORD) tex->
get_y_size();
2164 DWORD orig_depth = (DWORD) tex->
get_z_size();
2166 D3DFORMAT source_format = _d3d_format;
2167 BYTE *image_pixels = (BYTE*)image.
p();
2170 nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
2173 image_pixels += view_size *
get_view();
2175 IDirect3DVolume9 *mip_level_0 =
nullptr;
2176 bool using_temp_buffer =
false;
2177 BYTE *pixels = image_pixels;
2179 nassertr(IS_VALID_PTR(_d3d_volume_texture), E_FAIL);
2180 hr = _d3d_volume_texture->GetVolumeLevel(0, &mip_level_0);
2184 <<
"FillDDSurfaceTexturePixels failed for " << tex->get_name()
2185 <<
", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
2190 source_size.Left = source_size.Top = source_size.Front = 0;
2191 source_size.Right = orig_width;
2192 source_size.Bottom = orig_height;
2193 source_size.Back = orig_depth;
2195 UINT source_row_byte_length = orig_width * num_color_channels;
2196 UINT source_page_byte_length = orig_height * source_row_byte_length;
2198 DWORD level_0_filter, mip_filter_flags;
2199 using_temp_buffer =
false;
2203 level_0_filter = D3DX_FILTER_LINEAR ;
2206 level_0_filter |= D3DX_FILTER_SRGB;
2211 if (_d3d_format == D3DFMT_A8) {
2213 USHORT *temp_buffer =
new USHORT[orig_width * orig_height * orig_depth];
2214 if (!IS_VALID_PTR(temp_buffer)) {
2216 <<
"FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
2217 goto exit_FillDDSurf;
2219 using_temp_buffer =
true;
2221 USHORT *out_pixels = temp_buffer;
2222 BYTE *source_pixels = pixels + component_width - 1;
2223 for (UINT z = 0; z < orig_depth; z++) {
2224 for (UINT y = 0; y < orig_height; y++) {
2227 x++, source_pixels += component_width, out_pixels++) {
2231 *out_pixels = ((*source_pixels) << 8 ) | 0xFF;
2236 source_format = D3DFMT_A8L8;
2237 source_row_byte_length = orig_width *
sizeof(USHORT);
2238 source_page_byte_length = orig_height * source_row_byte_length;
2239 pixels = (BYTE*)temp_buffer;
2241 else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) {
2242 size_t total_components = (size_t)orig_width * (
size_t)orig_height * (size_t)orig_depth * 4;
2243 float *temp_buffer =
new float[total_components];
2244 if (!IS_VALID_PTR(temp_buffer)) {
2246 <<
"FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
2247 goto exit_FillDDSurf;
2249 using_temp_buffer =
true;
2252 float *out_pixels = (
float *)temp_buffer;
2253 const float *source_pixels = (
const float *)pixels;
2254 for (
size_t i = 0; i < total_components; i += 4) {
2255 out_pixels[i] = source_pixels[i + 2];
2256 out_pixels[i + 1] = source_pixels[i + 1];
2257 out_pixels[i + 2] = source_pixels[i + 0];
2258 out_pixels[i + 3] = source_pixels[i + 3];
2260 pixels = (BYTE*)temp_buffer;
2262 else if (component_width != 1 && _d3d_format != D3DFMT_R32F) {
2268 int num_pixels = orig_width * orig_height * orig_depth * num_components;
2269 BYTE *temp_buffer =
new BYTE[num_pixels];
2270 if (!IS_VALID_PTR(temp_buffer)) {
2271 dxgsg9_cat.error() <<
"FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
2272 goto exit_FillDDSurf;
2274 using_temp_buffer =
true;
2276 BYTE *source_pixels = pixels + component_width - 1;
2277 for (
int i = 0; i < num_pixels; i++) {
2278 temp_buffer[i] = *source_pixels;
2279 source_pixels += component_width;
2281 pixels = (BYTE*)temp_buffer;
2287 GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_page_byte_length * orig_depth);
2289 hr = D3DXLoadVolumeFromMemory
2290 (mip_level_0,
nullptr,
nullptr, (LPCVOID)pixels,
2291 source_format, source_row_byte_length, source_page_byte_length,
2293 &source_size, level_0_filter, (D3DCOLOR)0x0);
2296 <<
"FillDDSurfaceTexturePixels failed for " << tex->get_name()
2297 <<
", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr);
2298 goto exit_FillDDSurf;
2302 if (!dx_use_triangle_mipgen_filter) {
2303 mip_filter_flags = D3DX_FILTER_BOX;
2305 mip_filter_flags = D3DX_FILTER_TRIANGLE;
2309 mip_filter_flags |= D3DX_FILTER_SRGB;
2314 hr = D3DXFilterTexture(_d3d_texture,
nullptr, 0,
2318 <<
"FillDDSurfaceTexturePixels failed for " << tex->get_name()
2319 <<
", D3DXFilterTex failed" << D3DERRORSTRING(hr);
2320 goto exit_FillDDSurf;
2325 if (using_temp_buffer) {
2326 SAFE_DELETE_ARRAY(pixels);
2328 RELEASE(mip_level_0, dxgsg9,
"FillDDSurf MipLev0 texture ptr", RELEASE_ONCE);
2336int DXTextureContext9::
2337down_to_power_2(
int value) {
2339 while ((x << 1) <= value) {
2350unsigned int DXTextureContext9::
2351get_bits_per_pixel(Texture::Format format,
int *alphbits) {
2354 case Texture::F_alpha:
2356 case Texture::F_color_index:
2357 case Texture::F_red:
2358 case Texture::F_green:
2359 case Texture::F_blue:
2360 case Texture::F_rgb332:
2362 case Texture::F_luminance_alphamask:
2365 case Texture::F_luminance_alpha:
2368 case Texture::F_luminance:
2370 case Texture::F_rgba4:
2373 case Texture::F_rgba5:
2376 case Texture::F_depth_component:
2377 case Texture::F_depth_component16:
2379 case Texture::F_depth_stencil:
2380 case Texture::F_depth_component24:
2382 case Texture::F_depth_component32:
2384 case Texture::F_rgb5:
2386 case Texture::F_rgb8:
2387 case Texture::F_rgb:
2389 case Texture::F_rgba8:
2390 case Texture::F_rgba:
2393 case Texture::F_rgbm:
2396 case Texture::F_rgb12:
2398 case Texture::F_rgba12:
2401 case Texture::F_rgba16:
2404 case Texture::F_rgba32:
2408 case Texture::F_r32:
2411 case Texture::F_srgb:
2413 case Texture::F_srgb_alpha:
2416 case Texture::F_sluminance:
2418 case Texture::F_sluminance_alpha:
2428PN_stdfloat DXTextureContext9::
2429d3d_format_to_bytes_per_pixel (D3DFORMAT format)
2431 PN_stdfloat bytes_per_pixel;
2433 bytes_per_pixel = 0.0f;
2442 bytes_per_pixel = 1.0f;
2449 case D3DFMT_X1R5G5B5:
2450 case D3DFMT_A1R5G5B5:
2451 case D3DFMT_A4R4G4B4:
2454 case D3DFMT_A8R3G3B2:
2455 case D3DFMT_X4R4G4B4:
2457 case (D3DFORMAT)MAKEFOURCC(
'D',
'F',
'1',
'6'):
2458 bytes_per_pixel = 2.0f;
2462 bytes_per_pixel = 3.0f;
2465 case D3DFMT_G16R16F:
2466 case D3DFMT_Q8W8V8U8:
2469 case D3DFMT_A8R8G8B8:
2470 case D3DFMT_X8R8G8B8:
2471 case D3DFMT_A2B10G10R10:
2472 case D3DFMT_A8B8G8R8:
2473 case D3DFMT_X8B8G8R8:
2475 case D3DFMT_A2R10G10B10:
2479 case (D3DFORMAT)MAKEFOURCC(
'D',
'F',
'2',
'4'):
2481 bytes_per_pixel = 4.0f;
2484 case D3DFMT_G32R32F:
2485 case D3DFMT_A16B16G16R16F:
2486 case D3DFMT_Q16W16V16U16:
2487 case D3DFMT_A16B16G16R16:
2488 bytes_per_pixel = 8.0f;
2491 case D3DFMT_A32B32G32R32F:
2492 bytes_per_pixel = 16.0f;
2497 bytes_per_pixel = 0.5f;
2504 bytes_per_pixel = 1.0f;
2508 return bytes_per_pixel;
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void mark_used_lru() const
To be called when the page is used; this will move it to the tail of the AdaptiveLru queue it is alre...
void dequeue_lru()
Removes the page from its AdaptiveLru.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
set_data
Stores a new data object on the record.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
const Element * p() const
Function p() is similar to the function from ConstPointerTo.
bool create_texture(DXScreenData &scrn)
Use panda texture's pixelbuffer to create a texture for the specified device.
virtual void evict_lru()
Evicts the page from the LRU.
bool extract_texture_data(DXScreenData &scrn)
This method will be called in the draw thread to download the texture memory's image into its ram_ima...
void delete_texture()
Release the surface used to store the texture.
static HRESULT d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, bool inverted, Texture *result, int view, int z)
copies source_rect in pD3DSurf to upper left of texture
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
virtual bool get_supports_compressed_texture_format(int compression_mode) const
Returns true if this GSG can accept textures pre-compressed in the indicated format.
get_supports_compressed_texture
Returns true if this GSG can compress textures as it loads them into texture memory,...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
constexpr bool is_null() const
Returns true if the PointerTo is a NULL pointer, false otherwise.
A table of objects that are saved within the graphics context for reference by handle later.
This is a special class object that holds all the information returned by a particular GSG to indicat...
void update_data_size_bytes(size_t new_data_size_bytes)
Should be called (usually by a derived class) when the on-card size of this object has changed.
Texture * get_texture() const
Returns the pointer to the associated Texture object.
void mark_simple_loaded()
Should be called after the texture's "simple" image has been loaded into graphics memory.
void mark_unloaded()
Should be called after the texture has been forced out of texture memory.
void mark_loaded()
Should be called after the texture has been loaded into graphics memory, this updates the internal fl...
int get_view() const
Returns the specific view of a multiview texture this context represents.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
get_post_load_store_cache
Returns the setting of the post_load_store_cache flag.
CPTA_uchar get_uncompressed_ram_image()
Returns the system-RAM image associated with the texture, in an uncompressed form if at all possible.
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
get_minfilter
Returns the filter mode of the texture for minification.
void generate_ram_mipmap_images()
Automatically fills in the n mipmap levels of the Texture, based on the texture's source image.
PTA_uchar modify_ram_image()
Returns a modifiable pointer to the system-RAM image.
set_z_size
Changes the z size indicated for the texture.
get_render_to_texture
Returns a flag on the texture that indicates whether the texture is intended to be used as a direct-r...
get_compression
Returns the compression mode requested for this particular texture, or CM_off if the texture is not t...
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
get_texture_type
Returns the overall interpretation of the texture.
CPTA_uchar get_ram_image()
Returns the system-RAM image data associated with the texture.
get_simple_ram_image
Returns the image data associated with the "simple" texture image.
static bool is_srgb(Format format)
Returns true if the indicated format is in the sRGB color space, false otherwise.
get_ram_image_compression
Returns the compression mode in which the ram image is already stored pre- compressed.
set_format
Changes the format value for the texture components.
get_component_width
Returns the number of bytes stored for each color component of a texel.
vector_uchar get_clear_data() const
Returns the raw image data for a single pixel if it were set to the clear color.
set_anisotropic_degree
Specifies the level of anisotropic filtering to apply to the texture.
get_anisotropic_degree
Returns the degree of anisotropic filtering that should be applied to the texture.
get_match_framebuffer_format
Returns true if the special flag was set that indicates to the GSG that the Texture's format should b...
get_y_size
Returns the height of the texture image in texels.
bool compress_ram_image(CompressionMode compression=CM_on, QualityLevel quality_level=QL_default, GraphicsStateGuardianBase *gsg=nullptr)
Attempts to compress the texture's RAM image internally, to a format supported by the indicated GSG.
size_t get_ram_mipmap_view_size(int n) const
Returns the number of bytes used by the in-memory image per view for mipmap level n,...
get_magfilter
Returns the filter mode of the texture for magnification.
get_z_size
Returns the depth of the texture image in texels.
set_x_size
Changes the x size indicated for the texture.
void set_ram_mipmap_image(int n, CPTA_uchar image, size_t page_size=0)
Replaces the current system-RAM image for the indicated mipmap level with the new data.
size_t get_expected_ram_mipmap_page_size(int n) const
Returns the number of bytes that should be used per each Z page of the 3-d texture,...
set_minfilter
Sets the filtering method that should be used when viewing the texture from a distance.
set_magfilter
Sets the filtering method that should be used when viewing the texture up close.
PTA_uchar make_ram_mipmap_image(int n)
Discards the current system-RAM image for the nth mipmap level, if any, and allocates a new buffer of...
int get_expected_mipmap_x_size(int n) const
Returns the x_size that the nth mipmap level should have, based on the texture's size.
get_num_components
Returns the number of color components for each texel of the texture image.
void clear_ram_image()
Discards the current system-RAM image.
get_fullpath
Returns the fullpath that has been set.
get_x_size
Returns the width of the texture image in texels.
get_simple_y_size
Returns the height of the "simple" image in texels.
get_expected_ram_page_size
Returns the number of bytes that should be used per each Z page of the 3-d texture.
int get_expected_mipmap_y_size(int n) const
Returns the y_size that the nth mipmap level should have, based on the texture's size.
set_y_size
Changes the y size indicated for the texture.
set_post_load_store_cache
Sets the post_load_store_cache flag.
get_component_type
Returns the numeric interpretation of each component of the texture.
void set_ram_image(CPTA_uchar image, CompressionMode compression=CM_off, size_t page_size=0)
Replaces the current system-RAM image with the new data.
get_simple_x_size
Returns the width of the "simple" image in texels.
get_num_loadable_ram_mipmap_images
Returns the number of contiguous mipmap levels that exist in RAM, up until the first gap in the seque...
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
get_clear_color
Returns the color that was previously set using set_clear_color.
set_component_type
Changes the data value for the texture components.
get_num_ram_mipmap_images
Returns the maximum number of mipmap level images available in system memory.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.