00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "config_dxgsg9.h"
00016 #include "dxGraphicsStateGuardian9.h"
00017 #include "pStatTimer.h"
00018 #include "dxTextureContext9.h"
00019 #include "bamCache.h"
00020 #include "graphicsEngine.h"
00021 #include <d3dx9tex.h>
00022 #include <assert.h>
00023 #include <time.h>
00024
00025 #define DEBUG_SURFACES false
00026 #define DEBUG_TEXTURES true
00027
00028 TypeHandle DXTextureContext9::_type_handle;
00029
00030 static const DWORD g_LowByteMask = 0x000000FF;
00031
00032
00033
00034
00035
00036
00037 DXTextureContext9::
00038 DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
00039 TextureContext(pgo, tex, view) {
00040
00041 if (dxgsg9_cat.is_spam()) {
00042 dxgsg9_cat.spam()
00043 << "Creating DX texture [" << tex->get_name() << "], minfilter(" << tex->get_minfilter() << "), magfilter(" << tex->get_magfilter() << "), anisodeg(" << tex->get_anisotropic_degree() << ")\n";
00044 }
00045
00046 _d3d_texture = NULL;
00047 _d3d_2d_texture = NULL;
00048 _d3d_volume_texture = NULL;
00049 _d3d_cube_texture = NULL;
00050 _has_mipmaps = false;
00051 _is_render_target = false;
00052 _managed = -1;
00053 }
00054
00055
00056
00057
00058
00059
00060 DXTextureContext9::
00061 ~DXTextureContext9() {
00062 delete_texture();
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 void DXTextureContext9::
00081 evict_lru() {
00082 if (get_texture()->get_render_to_texture()) {
00083
00084 mark_used_lru();
00085 return;
00086 }
00087 if (dxgsg9_cat.is_debug()) {
00088 dxgsg9_cat.debug()
00089 << "Evicting " << *get_texture() << "\n";
00090 }
00091
00092 dequeue_lru();
00093 delete_texture();
00094
00095 update_data_size_bytes(0);
00096 mark_unloaded();
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 bool DXTextureContext9::
00110 create_texture(DXScreenData &scrn) {
00111
00112
00113 if (_d3d_2d_texture || _d3d_cube_texture || _d3d_volume_texture) {
00114
00115 return true;
00116 }
00117
00118 HRESULT hr;
00119 int num_alpha_bits;
00120 D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
00121 bool needs_luminance = false;
00122 bool compress_texture = false;
00123
00124 Texture *tex = get_texture();
00125 nassertr(IS_VALID_PTR(tex), false);
00126
00127
00128 tex->get_ram_image();
00129
00130 DWORD orig_width = (DWORD)tex->get_x_size();
00131 DWORD orig_height = (DWORD)tex->get_y_size();
00132 DWORD orig_depth = (DWORD)tex->get_z_size();
00133
00134
00135 bool texture_wants_compressed = false;
00136 Texture::CompressionMode compression_mode = tex->get_ram_image_compression();
00137 bool texture_stored_compressed = compression_mode != Texture::CM_off;
00138
00139 if (texture_stored_compressed) {
00140 texture_wants_compressed = true;
00141 } else {
00142 if (tex->get_compression() == Texture::CM_off) {
00143
00144 } else {
00145 if (tex->get_compression() == Texture::CM_default) {
00146
00147 if (compressed_textures) {
00148 texture_wants_compressed = true;
00149 }
00150 } else {
00151 texture_wants_compressed = true;
00152 }
00153 }
00154 }
00155
00156 switch (tex->get_texture_type()) {
00157 case Texture::TT_1d_texture:
00158 case Texture::TT_2d_texture:
00159 case Texture::TT_cube_map:
00160
00161
00162 if (!tex->get_render_to_texture() &&
00163 orig_width >= 4 && orig_height >= 4) {
00164 if (texture_wants_compressed){
00165 compress_texture = true;
00166 }
00167 }
00168 break;
00169 case Texture::TT_3d_texture:
00170
00171 break;
00172 }
00173
00174 if (texture_stored_compressed && !compress_texture) {
00175
00176
00177
00178
00179
00180
00181
00182 tex->get_uncompressed_ram_image();
00183
00184 orig_width = (DWORD)tex->get_x_size();
00185 orig_height = (DWORD)tex->get_y_size();
00186 orig_depth = (DWORD)tex->get_z_size();
00187 }
00188
00189
00190 DWORD target_bpp = get_bits_per_pixel(tex->get_format(), &num_alpha_bits);
00191 DWORD num_color_channels = tex->get_num_components();
00192
00193
00194
00195
00196
00197
00198 if ((tex->get_format() == Texture::F_luminance_alpha)||
00199 (tex->get_format() == Texture::F_luminance_alphamask) ||
00200 (tex->get_format() == Texture::F_luminance)) {
00201 needs_luminance = true;
00202 }
00203
00204 if (num_alpha_bits > 0) {
00205 if (num_color_channels == 3) {
00206 dxgsg9_cat.error()
00207 << "texture " << tex->get_name()
00208 << " has no inherent alpha channel, but alpha format is requested!\n";
00209 }
00210 }
00211
00212 _d3d_format = D3DFMT_UNKNOWN;
00213
00214
00215
00216 switch (num_color_channels) {
00217 case 1:
00218 if (num_alpha_bits > 0) {
00219 _d3d_format = D3DFMT_A8;
00220 } else if (needs_luminance) {
00221 _d3d_format = D3DFMT_L8;
00222 }
00223 break;
00224 case 2:
00225 nassertr(needs_luminance && (num_alpha_bits > 0), false);
00226 _d3d_format = D3DFMT_A8L8;
00227 break;
00228 case 3:
00229 _d3d_format = D3DFMT_R8G8B8;
00230 break;
00231 case 4:
00232 _d3d_format = D3DFMT_A8R8G8B8;
00233 break;
00234 }
00235
00236
00237 nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
00238
00239 DWORD target_width = orig_width;
00240 DWORD target_height = orig_height;
00241 DWORD target_depth = orig_depth;
00242
00243 DWORD filter_caps;
00244
00245 switch (tex->get_texture_type()) {
00246 case Texture::TT_1d_texture:
00247 case Texture::TT_2d_texture:
00248 filter_caps = scrn._d3dcaps.TextureFilterCaps;
00249
00250 if (target_width > scrn._d3dcaps.MaxTextureWidth) {
00251 target_width = scrn._d3dcaps.MaxTextureWidth;
00252 }
00253 if (target_height > scrn._d3dcaps.MaxTextureHeight) {
00254 target_height = scrn._d3dcaps.MaxTextureHeight;
00255 }
00256
00257 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_POW2) {
00258 if (!ISPOW2(target_width)) {
00259 target_width = down_to_power_2(target_width);
00260 }
00261 if (!ISPOW2(target_height)) {
00262 target_height = down_to_power_2(target_height);
00263 }
00264 }
00265 break;
00266
00267 case Texture::TT_3d_texture:
00268 if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0) {
00269 dxgsg9_cat.warning()
00270 << "3-d textures are not supported by this graphics driver.\n";
00271 return false;
00272 }
00273
00274 filter_caps = scrn._d3dcaps.VolumeTextureFilterCaps;
00275
00276 if (target_width > scrn._d3dcaps.MaxVolumeExtent) {
00277 target_width = scrn._d3dcaps.MaxVolumeExtent;
00278 }
00279 if (target_height > scrn._d3dcaps.MaxVolumeExtent) {
00280 target_height = scrn._d3dcaps.MaxVolumeExtent;
00281 }
00282 if (target_depth > scrn._d3dcaps.MaxVolumeExtent) {
00283 target_depth = scrn._d3dcaps.MaxVolumeExtent;
00284 }
00285
00286 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) {
00287 if (!ISPOW2(target_width)) {
00288 target_width = down_to_power_2(target_width);
00289 }
00290 if (!ISPOW2(target_height)) {
00291 target_height = down_to_power_2(target_height);
00292 }
00293 if (!ISPOW2(target_depth)) {
00294 target_depth = down_to_power_2(target_depth);
00295 }
00296 }
00297 break;
00298
00299 case Texture::TT_cube_map:
00300 if ((scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0) {
00301 dxgsg9_cat.warning()
00302 << "Cube map textures are not supported by this graphics driver.\n";
00303 return false;
00304 }
00305
00306 filter_caps = scrn._d3dcaps.CubeTextureFilterCaps;
00307
00308 if (target_width > scrn._d3dcaps.MaxTextureWidth) {
00309 target_width = scrn._d3dcaps.MaxTextureWidth;
00310 }
00311
00312 if (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) {
00313 if (!ISPOW2(target_width)) {
00314 target_width = down_to_power_2(target_width);
00315 }
00316 }
00317
00318 target_height = target_width;
00319 break;
00320 }
00321
00322
00323 if ((target_width != target_height) &&
00324 (scrn._d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0) {
00325
00326
00327 int i, width_exp, height_exp;
00328 for (i = target_width, width_exp = 0; i > 1; width_exp++, i >>= 1) {
00329 }
00330 for (i = target_height, height_exp = 0; i > 1; height_exp++, i >>= 1) {
00331 }
00332 target_height = target_width = 1<<((width_exp+height_exp)>>1);
00333 }
00334
00335 bool shrink_original = false;
00336
00337 if (orig_width != target_width || orig_height != target_height ||
00338 orig_depth != target_depth) {
00339 if (tex->get_texture_type() == Texture::TT_3d_texture) {
00340 dxgsg9_cat.info()
00341 << "Reducing size of " << tex->get_name()
00342 << " from " << orig_width << "x" << orig_height << "x" << orig_depth
00343 << " to " << target_width << "x" << target_height
00344 << "x" << target_depth << "\n";
00345 } else {
00346 dxgsg9_cat.info()
00347 << "Reducing size of " << tex->get_name()
00348 << " from " << orig_width << "x" << orig_height
00349 << " to " << target_width << "x" << target_height << "\n";
00350 }
00351
00352 shrink_original = true;
00353 }
00354
00355 const char *error_message;
00356
00357 error_message = "create_texture failed: couldn't find compatible device Texture Pixel Format for input texture";
00358
00359 if (dxgsg9_cat.is_spam()) {
00360 dxgsg9_cat.spam()
00361 << "create_texture handling target bitdepth: " << target_bpp
00362 << " alphabits: " << num_alpha_bits << endl;
00363 }
00364
00365
00366
00367
00368
00369 #define CHECK_FOR_FMT(FMT) \
00370 if (scrn._supported_tex_formats_mask & FMT##_FLAG) { \
00371 target_pixel_format = D3DFMT_##FMT; \
00372 goto found_matching_format; }
00373
00374 if (texture_stored_compressed && compress_texture) {
00375
00376
00377
00378 switch (compression_mode){
00379 case Texture::CM_dxt1:
00380 CHECK_FOR_FMT(DXT1);
00381 break;
00382 case Texture::CM_dxt2:
00383 CHECK_FOR_FMT(DXT2);
00384 break;
00385 case Texture::CM_dxt3:
00386 CHECK_FOR_FMT(DXT3);
00387 break;
00388 case Texture::CM_dxt4:
00389 CHECK_FOR_FMT(DXT4);
00390 break;
00391 case Texture::CM_dxt5:
00392 CHECK_FOR_FMT(DXT5);
00393 break;
00394 }
00395
00396
00397 }
00398
00399 if (compress_texture) {
00400 if (num_alpha_bits <= 1) {
00401 CHECK_FOR_FMT(DXT1);
00402 } else if (num_alpha_bits <= 4) {
00403 CHECK_FOR_FMT(DXT3);
00404 } else {
00405 CHECK_FOR_FMT(DXT5);
00406 }
00407 }
00408
00409
00410
00411 if (texture_stored_compressed) {
00412 tex->get_uncompressed_ram_image();
00413 compression_mode = tex->get_ram_image_compression();
00414 texture_stored_compressed = compression_mode != Texture::CM_off;
00415 compress_texture = false;
00416 }
00417
00418
00419
00420
00421 switch (target_bpp) {
00422
00423
00424
00425
00426
00427 case 128:
00428
00429 if (scrn._supports_rgba32_texture_format) {
00430 target_pixel_format = D3DFMT_A32B32G32R32F;
00431 }
00432 else {
00433 target_pixel_format = scrn._render_to_texture_d3d_format;
00434 }
00435 goto found_matching_format;
00436
00437 case 64:
00438
00439 if (scrn._supports_rgba16f_texture_format) {
00440 target_pixel_format = D3DFMT_A16B16G16R16F;
00441 }
00442 else {
00443 target_pixel_format = scrn._render_to_texture_d3d_format;
00444 }
00445 goto found_matching_format;
00446
00447 case 32:
00448 if (!((num_color_channels == 3) || (num_color_channels == 4)))
00449 break;
00450
00451 CHECK_FOR_FMT(A8R8G8B8);
00452
00453 if (num_alpha_bits>0) {
00454 nassertr(num_color_channels == 4, false);
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 if (num_alpha_bits == 1) {
00471 CHECK_FOR_FMT(A1R5G5B5);
00472 }
00473
00474
00475 CHECK_FOR_FMT(A4R4G4B4);
00476 CHECK_FOR_FMT(A1R5G5B5);
00477
00478
00479
00480 error_message = "create_texture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!";
00481 } else {
00482
00483
00484 if (num_color_channels == 3) {
00485 CHECK_FOR_FMT(R5G6B5);
00486 CHECK_FOR_FMT(X1R5G5B5);
00487 } else {
00488 CHECK_FOR_FMT(R5G6B5);
00489 CHECK_FOR_FMT(X1R5G5B5);
00490 }
00491 }
00492 break;
00493
00494 case 24:
00495 nassertr(num_color_channels == 3, false);
00496
00497 CHECK_FOR_FMT(R8G8B8);
00498
00499
00500
00501
00502
00503 CHECK_FOR_FMT(X8R8G8B8);
00504 CHECK_FOR_FMT(A8R8G8B8);
00505
00506
00507 CHECK_FOR_FMT(R5G6B5);
00508 CHECK_FOR_FMT(X1R5G5B5);
00509 CHECK_FOR_FMT(A1R5G5B5);
00510 break;
00511
00512 case 16:
00513 if (needs_luminance) {
00514 nassertr(num_alpha_bits > 0, false);
00515 nassertr(num_color_channels == 2, false);
00516
00517 CHECK_FOR_FMT(A8L8);
00518 CHECK_FOR_FMT(A8R8G8B8);
00519
00520 if (num_alpha_bits == 1) {
00521 CHECK_FOR_FMT(A1R5G5B5);
00522 }
00523
00524
00525 CHECK_FOR_FMT(A4R4G4B4);
00526 CHECK_FOR_FMT(A1R5G5B5);
00527 } else {
00528 nassertr((num_color_channels == 3)||(num_color_channels == 4), false);
00529
00530
00531 switch(num_alpha_bits) {
00532 case 0:
00533 if (num_color_channels == 3) {
00534 CHECK_FOR_FMT(R5G6B5);
00535 CHECK_FOR_FMT(X1R5G5B5);
00536 } else {
00537 nassertr(num_color_channels == 4, false);
00538
00539 CHECK_FOR_FMT(R5G6B5);
00540 CHECK_FOR_FMT(X1R5G5B5);
00541 }
00542 break;
00543 case 1:
00544
00545
00546
00547
00548 nassertr(num_color_channels == 4, false);
00549 CHECK_FOR_FMT(X1R5G5B5);
00550 break;
00551 case 4:
00552
00553
00554 nassertr(num_color_channels == 4, false);
00555 CHECK_FOR_FMT(A4R4G4B4);
00556 break;
00557 default:
00558 nassertr(false, false);
00559 }
00560 }
00561 case 8:
00562 if (needs_luminance) {
00563
00564
00565 nassertr(num_color_channels == 1, false);
00566
00567
00568 CHECK_FOR_FMT(L8);
00569 CHECK_FOR_FMT(L8);
00570
00571 CHECK_FOR_FMT(R8G8B8);
00572 CHECK_FOR_FMT(X8R8G8B8);
00573
00574 CHECK_FOR_FMT(R5G6B5);
00575 CHECK_FOR_FMT(X1R5G5B5);
00576
00577 } else if (num_alpha_bits == 8) {
00578
00579
00580
00581
00582
00583
00584
00585 CHECK_FOR_FMT(A8L8);
00586 CHECK_FOR_FMT(A8R8G8B8);
00587 CHECK_FOR_FMT(A4R4G4B4);
00588 }
00589 break;
00590
00591 default:
00592 error_message = "create_texture failed: unhandled pixel bitdepth in DX loader";
00593 }
00594
00595
00596 dxgsg9_cat.error()
00597 << error_message << ": " << tex->get_name() << endl
00598 << "NumColorChannels: " << num_color_channels << "; NumAlphaBits: "
00599 << num_alpha_bits << "; targetbpp: " <<target_bpp
00600 << "; _supported_tex_formats_mask: 0x"
00601 << (void*)scrn._supported_tex_formats_mask
00602 << "; NeedLuminance: " << needs_luminance << endl;
00603 goto error_exit;
00604
00605
00606
00607 found_matching_format:
00608
00609
00610 if (tex->get_match_framebuffer_format()) {
00611
00612
00613
00614 DWORD render_target_index;
00615 IDirect3DSurface9 *render_target;
00616
00617 render_target_index = 0;
00618 hr = scrn._d3d_device->GetRenderTarget(render_target_index, &render_target);
00619 if (FAILED(hr)) {
00620 dxgsg9_cat.error()
00621 << "GetRenderTgt failed in create_texture: " << D3DERRORSTRING(hr);
00622 } else {
00623 D3DSURFACE_DESC surface_desc;
00624 hr = render_target->GetDesc(&surface_desc);
00625 if (FAILED(hr)) {
00626 dxgsg9_cat.error()
00627 << "GetDesc failed in create_texture: " << D3DERRORSTRING(hr);
00628 } else {
00629 if (target_pixel_format != surface_desc.Format) {
00630 if (dxgsg9_cat.is_debug()) {
00631 dxgsg9_cat.debug()
00632 << "Chose format " << D3DFormatStr(surface_desc.Format)
00633 << " instead of " << D3DFormatStr(target_pixel_format)
00634 << " for texture to match framebuffer.\n";
00635 }
00636 target_pixel_format = surface_desc.Format;
00637 }
00638 }
00639 SAFE_RELEASE(render_target);
00640 }
00641 }
00642
00643
00644
00645
00646 Texture::FilterType ft;
00647
00648 ft = tex->get_magfilter();
00649 if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) {
00650
00651 if (ft == Texture::FT_nearest_mipmap_nearest) {
00652 ft = Texture::FT_nearest;
00653 } else {
00654 ft = Texture::FT_linear;
00655 }
00656 }
00657
00658 if (ft == Texture::FT_linear &&
00659 (filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) {
00660 ft = Texture::FT_nearest;
00661 }
00662 tex->set_magfilter(ft);
00663
00664
00665 ft = tex->get_minfilter();
00666 _has_mipmaps = false;
00667
00668 if (!dx_ignore_mipmaps) {
00669 switch(ft) {
00670 case Texture::FT_nearest_mipmap_nearest:
00671 case Texture::FT_linear_mipmap_nearest:
00672 case Texture::FT_nearest_mipmap_linear:
00673 case Texture::FT_linear_mipmap_linear:
00674 _has_mipmaps = true;
00675 }
00676
00677 if (dx_mipmap_everything) {
00678 _has_mipmaps = true;
00679 if (dxgsg9_cat.is_spam()) {
00680 if (ft != Texture::FT_linear_mipmap_linear) {
00681 dxgsg9_cat.spam()
00682 << "Forcing trilinear mipmapping on DX texture ["
00683 << tex->get_name() << "]\n";
00684 }
00685 }
00686 ft = Texture::FT_linear_mipmap_linear;
00687 tex->set_minfilter(ft);
00688 }
00689
00690 } else if ((ft == Texture::FT_nearest_mipmap_nearest) ||
00691 (ft == Texture::FT_nearest_mipmap_linear)) {
00692 ft = Texture::FT_nearest;
00693
00694 } else if ((ft == Texture::FT_linear_mipmap_nearest) ||
00695 (ft == Texture::FT_linear_mipmap_linear)) {
00696 ft = Texture::FT_linear;
00697 }
00698
00699 nassertr((filter_caps & D3DPTFILTERCAPS_MINFPOINT) != 0, false);
00700
00701 #define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR)
00702
00703
00704 switch(ft) {
00705 case Texture::FT_linear_mipmap_linear:
00706 if ((filter_caps & TRILINEAR_MIPMAP_TEXFILTERCAPS) != TRILINEAR_MIPMAP_TEXFILTERCAPS) {
00707 if (filter_caps & D3DPTFILTERCAPS_MINFLINEAR) {
00708 ft = Texture::FT_linear_mipmap_nearest;
00709 } else {
00710
00711
00712 ft = Texture::FT_nearest_mipmap_nearest;
00713 }
00714 }
00715 break;
00716
00717 case Texture::FT_nearest_mipmap_linear:
00718
00719 if (!((filter_caps & D3DPTFILTERCAPS_MIPFPOINT) &&
00720 (filter_caps & D3DPTFILTERCAPS_MINFLINEAR))) {
00721 ft = Texture::FT_nearest_mipmap_nearest;
00722 }
00723 break;
00724
00725 case Texture::FT_linear_mipmap_nearest:
00726
00727 if (!(filter_caps & D3DPTFILTERCAPS_MIPFLINEAR)) {
00728 ft = Texture::FT_nearest_mipmap_nearest;
00729 }
00730 break;
00731
00732 case Texture::FT_linear:
00733 if (!(filter_caps & D3DPTFILTERCAPS_MINFLINEAR)) {
00734 ft = Texture::FT_nearest;
00735 }
00736 break;
00737 }
00738
00739 tex->set_minfilter(ft);
00740
00741 uint aniso_degree;
00742
00743 aniso_degree = 1;
00744 if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) {
00745 aniso_degree = tex->get_anisotropic_degree();
00746 if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) ||
00747 dx_force_anisotropic_filtering) {
00748 aniso_degree = scrn._d3dcaps.MaxAnisotropy;
00749 }
00750 }
00751 tex->set_anisotropic_degree(aniso_degree);
00752
00753 #ifdef _DEBUG
00754 dxgsg9_cat.spam()
00755 << "create_texture: setting aniso degree for " << tex->get_name()
00756 << " to: " << aniso_degree << endl;
00757 #endif
00758
00759 UINT mip_level_count;
00760
00761 if (_has_mipmaps) {
00762 tex->get_ram_image();
00763 mip_level_count = tex->get_num_loadable_ram_mipmap_images();
00764 if (mip_level_count < 2) {
00765
00766 mip_level_count = 0;
00767
00768 if (dxgsg9_cat.is_debug()) {
00769 dxgsg9_cat.debug()
00770 << "create_texture: generating mipmaps for " << tex->get_name()
00771 << endl;
00772 }
00773 }
00774 } else {
00775 mip_level_count = 1;
00776 }
00777
00778 DWORD usage;
00779 D3DPOOL pool;
00780
00781 usage = 0;
00782 if (tex->get_render_to_texture ( )) {
00783
00784 _managed = false;
00785 _is_render_target = true;
00786
00787 pool = D3DPOOL_DEFAULT;
00788 usage = D3DUSAGE_RENDERTARGET;
00789 if (target_bpp <= 32 ) {
00790 target_pixel_format = scrn._render_to_texture_d3d_format;
00791 }
00792
00793 dxgsg9_cat.debug ()
00794 << "*** RENDER TO TEXTURE ***: format "
00795 << D3DFormatStr(target_pixel_format)
00796 << " "
00797 << target_pixel_format
00798 << "\n";
00799 }
00800 else {
00801 _managed = scrn._managed_textures;
00802 if (_managed) {
00803 pool = D3DPOOL_MANAGED;
00804 }
00805 else {
00806 if (scrn._supports_automatic_mipmap_generation) {
00807 pool = D3DPOOL_DEFAULT;
00808 usage = D3DUSAGE_AUTOGENMIPMAP;
00809 }
00810 else {
00811 if (dx_use_dynamic_textures) {
00812 if (scrn._supports_dynamic_textures) {
00813 pool = D3DPOOL_DEFAULT;
00814 usage = D3DUSAGE_DYNAMIC;
00815 }
00816 else {
00817
00818
00819 _managed = true;
00820 pool = D3DPOOL_MANAGED;
00821 }
00822 }
00823 else {
00824 pool = D3DPOOL_DEFAULT;
00825 }
00826 }
00827 }
00828 }
00829
00830 PN_stdfloat bytes_per_texel;
00831
00832 bytes_per_texel = this -> d3d_format_to_bytes_per_pixel (target_pixel_format);
00833 if (bytes_per_texel == 0.0f) {
00834 dxgsg9_cat.error()
00835 << "D3D create_texture ( ) unknown texture format\n";
00836 }
00837
00838 int data_size;
00839
00840 data_size = target_width * target_height * target_depth;
00841 if (_has_mipmaps) {
00842 data_size = (int) ((PN_stdfloat) data_size * 1.3333333);
00843 }
00844 data_size = (int) ((PN_stdfloat) data_size * bytes_per_texel);
00845 if (tex->get_texture_type() == Texture::TT_cube_map) {
00846 data_size *= 6;
00847 }
00848 update_data_size_bytes(data_size);
00849
00850 int attempts;
00851
00852 if (dxgsg9_cat.is_debug()) {
00853 dxgsg9_cat.debug()
00854 << "Creating " << *tex << ", " << data_size << " bytes, "
00855 << scrn._d3d_device->GetAvailableTextureMem()
00856 << " reported available.\n";
00857 dxgsg9_cat.debug()
00858 << " size is " << target_width << " w * " << target_height << " h * "
00859 << target_depth << " d";
00860 if (_has_mipmaps) {
00861 dxgsg9_cat.debug(false)
00862 << " * 1.3333333 mipmaps";
00863 }
00864 dxgsg9_cat.debug(false)
00865 << " * " << bytes_per_texel << " bpt";
00866 if (tex->get_texture_type() == Texture::TT_cube_map) {
00867 dxgsg9_cat.debug(false)
00868 << " * 6 faces";
00869 }
00870 dxgsg9_cat.debug(false)
00871 << "\n";
00872 }
00873
00874 attempts = 0;
00875 do
00876 {
00877 switch (tex->get_texture_type()) {
00878 case Texture::TT_1d_texture:
00879 case Texture::TT_2d_texture:
00880 hr = scrn._d3d_device->CreateTexture
00881 (target_width, target_height, mip_level_count, usage,
00882 target_pixel_format, pool, &_d3d_2d_texture, NULL);
00883 _d3d_texture = _d3d_2d_texture;
00884 break;
00885
00886 case Texture::TT_3d_texture:
00887 hr = scrn._d3d_device->CreateVolumeTexture
00888 (target_width, target_height, target_depth, mip_level_count, usage,
00889 target_pixel_format, pool, &_d3d_volume_texture, NULL);
00890 _d3d_texture = _d3d_volume_texture;
00891 break;
00892
00893 case Texture::TT_cube_map:
00894 hr = scrn._d3d_device->CreateCubeTexture
00895 (target_width, mip_level_count, usage,
00896 target_pixel_format, pool, &_d3d_cube_texture, NULL);
00897 _d3d_texture = _d3d_cube_texture;
00898
00899 target_height = target_width;
00900 break;
00901 }
00902
00903 attempts++;
00904 } while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
00905
00906 if (FAILED(hr)) {
00907 dxgsg9_cat.error()
00908 << "D3D create_texture failed!" << D3DERRORSTRING(hr);
00909 dxgsg9_cat.error()
00910 << " width = " << target_width << " height = " << target_height << " target_pixel_format = " << target_pixel_format << "\n";
00911
00912 goto error_exit;
00913 }
00914
00915 if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
00916 dxgsg9_cat.debug()
00917 << "create_texture: " << tex->get_name()
00918 << " converting panda equivalent of " << D3DFormatStr(_d3d_format)
00919 << " => " << D3DFormatStr(target_pixel_format) << endl;
00920 }
00921
00922 hr = fill_d3d_texture_pixels(scrn, compress_texture);
00923 if (FAILED(hr)) {
00924
00925 dxgsg9_cat.debug ()
00926 << "*** fill_d3d_texture_pixels failed ***: format "
00927 << target_pixel_format
00928 << "\n";
00929
00930 goto error_exit;
00931 }
00932
00933 if (tex->get_post_load_store_cache()) {
00934 tex->set_post_load_store_cache(false);
00935
00936 if (extract_texture_data(scrn)) {
00937 if (tex->has_ram_image()) {
00938 BamCache *cache = BamCache::get_global_ptr();
00939 PT(BamCacheRecord) record = cache->lookup(tex->get_fullpath(), "txo");
00940 if (record != (BamCacheRecord *)NULL) {
00941 record->set_data(tex, tex);
00942 cache->store(record);
00943 }
00944 }
00945 }
00946 }
00947
00948
00949 if (!_managed && !tex->get_render_to_texture()) {
00950 scrn._dxgsg9->get_engine()->texture_uploaded(tex);
00951 }
00952 mark_loaded();
00953
00954 return true;
00955
00956 error_exit:
00957
00958 RELEASE(_d3d_texture, dxgsg9, "texture", RELEASE_ONCE);
00959 _d3d_2d_texture = NULL;
00960 _d3d_volume_texture = NULL;
00961 _d3d_cube_texture = NULL;
00962 return false;
00963 }
00964
00965
00966
00967
00968
00969
00970 bool DXTextureContext9::
00971 create_simple_texture(DXScreenData &scrn) {
00972 nassertr(IS_VALID_PTR(get_texture()), false);
00973
00974 HRESULT hr;
00975
00976 delete_texture();
00977
00978 _d3d_format = D3DFMT_A8R8G8B8;
00979 D3DFORMAT target_pixel_format = D3DFMT_A8R8G8B8;
00980 DWORD target_bpp = 32;
00981 DWORD num_color_channels = 4;
00982
00983 DWORD target_width = (DWORD)get_texture()->get_simple_x_size();
00984 DWORD target_height = (DWORD)get_texture()->get_simple_y_size();
00985 DWORD mip_level_count = 1;
00986 DWORD usage = 0;
00987 D3DPOOL pool = D3DPOOL_MANAGED;
00988
00989 int data_size = target_width * target_height * 4;
00990
00991 hr = scrn._d3d_device->CreateTexture
00992 (target_width, target_height, mip_level_count, usage,
00993 target_pixel_format, pool, &_d3d_2d_texture, NULL);
00994 _d3d_texture = _d3d_2d_texture;
00995 if (FAILED(hr)) {
00996 dxgsg9_cat.error()
00997 << "D3D create_simple_texture failed!" << D3DERRORSTRING(hr);
00998 dxgsg9_cat.error()
00999 << " width = " << target_width << " height = " << target_height << " target_pixel_format = " << target_pixel_format << "\n";
01000
01001 goto error_exit;
01002 }
01003
01004 if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
01005 dxgsg9_cat.debug()
01006 << "create_simple_texture: " << get_texture()->get_name()
01007 << "\n";
01008 }
01009
01010 {
01011 CPTA_uchar image = get_texture()->get_simple_ram_image();
01012
01013 hr = -1;
01014
01015
01016 IDirect3DSurface9 *surface = NULL;
01017 _d3d_2d_texture->GetSurfaceLevel(0, &surface);
01018
01019 RECT source_size;
01020 source_size.left = source_size.top = 0;
01021 source_size.right = target_width;
01022 source_size.bottom = target_height;
01023
01024 DWORD mip_filter = D3DX_FILTER_LINEAR;
01025
01026 hr = D3DXLoadSurfaceFromMemory
01027 (surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)image.p(),
01028 target_pixel_format, target_width * 4, (PALETTEENTRY*)NULL,
01029 &source_size, mip_filter, (D3DCOLOR)0x0);
01030
01031 RELEASE(surface, dxgsg9, "create_simple_texture Surface", RELEASE_ONCE);
01032 }
01033
01034 if (FAILED(hr)) {
01035 dxgsg9_cat.debug ()
01036 << "*** fill_d3d_texture_pixels failed ***: format "
01037 << target_pixel_format
01038 << "\n";
01039
01040 goto error_exit;
01041 }
01042
01043 mark_simple_loaded();
01044 return true;
01045
01046 error_exit:
01047 RELEASE(_d3d_texture, dxgsg9, "texture", RELEASE_ONCE);
01048 _d3d_2d_texture = NULL;
01049 _d3d_volume_texture = NULL;
01050 _d3d_cube_texture = NULL;
01051 return false;
01052 }
01053
01054
01055
01056
01057
01058
01059 void DXTextureContext9::
01060 delete_texture() {
01061
01062 if (_d3d_texture == NULL) {
01063
01064 return;
01065 }
01066
01067 RELEASE(_d3d_texture, dxgsg9, "texture", RELEASE_ONCE);
01068 _d3d_2d_texture = NULL;
01069 _d3d_volume_texture = NULL;
01070 _d3d_cube_texture = NULL;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 bool DXTextureContext9::
01082 extract_texture_data(DXScreenData &screen) {
01083 bool state;
01084 HRESULT hr;
01085
01086 state = false;
01087 Texture *tex = get_texture();
01088 if (tex->get_texture_type() != Texture::TT_2d_texture) {
01089 dxgsg9_cat.error()
01090 << "Not supported: extract_texture_data for " << tex->get_texture_type()
01091 << "\n";
01092 return state;
01093 }
01094 nassertr(IS_VALID_PTR(_d3d_2d_texture), false);
01095
01096 D3DSURFACE_DESC desc;
01097 hr = _d3d_2d_texture->GetLevelDesc(0, &desc);
01098 if (FAILED(hr)) {
01099 dxgsg9_cat.error()
01100 << "Texture::GetLevelDesc() failed!" << D3DERRORSTRING(hr);
01101 return state;
01102 }
01103
01104 int div = 1;
01105 Texture::Format format = Texture::F_rgba;
01106 Texture::CompressionMode compression = Texture::CM_off;
01107
01108 switch (desc.Format) {
01109 case D3DFMT_R8G8B8:
01110 format = Texture::F_rgb;
01111 break;
01112
01113 case D3DFMT_A8R8G8B8:
01114 case D3DFMT_X8R8G8B8:
01115 break;
01116
01117 case D3DFMT_L8:
01118 format = Texture::F_luminance;
01119 break;
01120
01121 case D3DFMT_A8L8:
01122 format = Texture::F_luminance_alpha;
01123 break;
01124
01125 case D3DFMT_DXT1:
01126 compression = Texture::CM_dxt1;
01127 div = 4;
01128 break;
01129 case D3DFMT_DXT2:
01130 compression = Texture::CM_dxt2;
01131 div = 4;
01132 break;
01133 case D3DFMT_DXT3:
01134 compression = Texture::CM_dxt3;
01135 div = 4;
01136 break;
01137 case D3DFMT_DXT4:
01138 compression = Texture::CM_dxt4;
01139 div = 4;
01140 break;
01141 case D3DFMT_DXT5:
01142 compression = Texture::CM_dxt5;
01143 div = 4;
01144 break;
01145
01146 default:
01147 dxgsg9_cat.error()
01148 << "Cannot extract texture data: unhandled surface format "
01149 << desc.Format << "\n";
01150 return state;
01151 }
01152
01153 int num_levels = _d3d_2d_texture->GetLevelCount();
01154
01155 tex->set_x_size(desc.Width);
01156 tex->set_y_size(desc.Height);
01157 tex->set_z_size(1);
01158 tex->set_component_type(Texture::T_unsigned_byte);
01159 tex->set_format(format);
01160 tex->clear_ram_image();
01161
01162 if (_is_render_target) {
01163 IDirect3DSurface9* source_surface;
01164 IDirect3DSurface9* destination_surface;
01165
01166 source_surface = 0;
01167 destination_surface = 0;
01168
01169 hr = _d3d_2d_texture -> GetSurfaceLevel (0, &source_surface);
01170 if (hr == D3D_OK) {
01171
01172 D3DPOOL pool;
01173 D3DSURFACE_DESC surface_description;
01174
01175 pool = D3DPOOL_SYSTEMMEM;
01176 source_surface -> GetDesc (&surface_description);
01177
01178 hr = screen._d3d_device->CreateOffscreenPlainSurface (
01179 surface_description.Width,
01180 surface_description.Height,
01181 surface_description.Format,
01182 pool,
01183 &destination_surface,
01184 NULL);
01185 if (hr == D3D_OK) {
01186 if (source_surface && destination_surface) {
01187 hr = screen._d3d_device -> GetRenderTargetData (source_surface, destination_surface);
01188 if (hr == D3D_OK) {
01189
01190 D3DLOCKED_RECT rect;
01191
01192 hr = destination_surface -> LockRect (&rect, NULL, D3DLOCK_READONLY);
01193 if (hr == D3D_OK) {
01194
01195 unsigned int y;
01196 int size;
01197 int bytes_per_line;
01198
01199 int surface_bytes_per_line;
01200 unsigned char *surface_pointer;
01201
01202 bytes_per_line = surface_description.Width * this -> d3d_format_to_bytes_per_pixel (surface_description.Format);
01203 size = bytes_per_line * surface_description.Height;
01204
01205 surface_bytes_per_line = rect.Pitch;
01206 surface_pointer = (unsigned char *) rect.pBits;
01207
01208 PTA_uchar image = PTA_uchar::empty_array(size);
01209
01210 int offset;
01211
01212 offset = 0;
01213 for (y = 0; y < surface_description.Height; y++)
01214 {
01215 memcpy (&image [offset], surface_pointer, bytes_per_line);
01216
01217 offset += bytes_per_line;
01218 surface_pointer += surface_bytes_per_line;
01219 }
01220
01221 tex->set_ram_image(image, Texture::CM_off);
01222
01223 state = true;
01224
01225 destination_surface -> UnlockRect();
01226 }
01227 }
01228 }
01229
01230 destination_surface -> Release ( );
01231 }
01232 else {
01233 dxgsg9_cat.error()
01234 << "CreateImageSurface failed in extract_texture_data()"
01235 << D3DERRORSTRING(hr);
01236 }
01237 source_surface -> Release ( );
01238 }
01239 }
01240 else {
01241 for (int n = 0; n < num_levels; ++n) {
01242 D3DLOCKED_RECT rect;
01243 hr = _d3d_2d_texture->LockRect(n, &rect, NULL, D3DLOCK_READONLY);
01244 if (FAILED(hr)) {
01245 dxgsg9_cat.error()
01246 << "Texture::LockRect() failed! level = " << n << " " << D3DERRORSTRING(hr);
01247 return state;
01248 }
01249
01250 int x_size = tex->get_expected_mipmap_x_size(n);
01251 int y_size = tex->get_expected_mipmap_y_size(n);
01252 PTA_uchar image;
01253
01254 if (compression == Texture::CM_off) {
01255
01256 int pitch = x_size * tex->get_num_components() * tex->get_component_width();
01257 pitch = min(pitch, (int)rect.Pitch);
01258 int size = pitch * y_size;
01259 image = PTA_uchar::empty_array(size);
01260 if (pitch == rect.Pitch) {
01261
01262 memcpy(image.p(), rect.pBits, size);
01263 } else {
01264
01265
01266 unsigned char *dest = image.p();
01267 unsigned char *source = (unsigned char *)rect.pBits;
01268 for (int yi = 0; yi < y_size; ++yi) {
01269 memcpy(dest, source, pitch);
01270 dest += pitch;
01271 source += rect.Pitch;
01272 }
01273 }
01274
01275 } else {
01276
01277 int size = rect.Pitch * (y_size / div);
01278 image = PTA_uchar::empty_array(size);
01279 memcpy(image.p(), rect.pBits, size);
01280 }
01281
01282 _d3d_2d_texture->UnlockRect(n);
01283 if (n == 0) {
01284 tex->set_ram_image(image, compression);
01285 } else {
01286 tex->set_ram_mipmap_image(n, image);
01287 }
01288 }
01289
01290 state = true;
01291 }
01292
01293 return state;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302 HRESULT DXTextureContext9::
01303 d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface,
01304 bool inverted, Texture *result, int z) {
01305
01306
01307
01308 HRESULT hr;
01309 DWORD num_components = result->get_num_components();
01310
01311 nassertr(result->get_component_width() == sizeof(BYTE), E_FAIL);
01312 nassertr(result->get_component_type() == Texture::T_unsigned_byte, E_FAIL);
01313 nassertr((num_components == 3) || (num_components == 4), E_FAIL);
01314 nassertr(IS_VALID_PTR(d3d_surface), E_FAIL);
01315
01316 BYTE *buf = result->modify_ram_image();
01317 if (z >= 0) {
01318 nassertr(z < result->get_z_size(), E_FAIL);
01319 buf += z * result->get_expected_ram_page_size();
01320 }
01321
01322 if (IsBadWritePtr(d3d_surface, sizeof(DWORD))) {
01323 dxgsg9_cat.error()
01324 << "d3d_surface_to_texture failed: bad pD3DSurf ptr value ("
01325 << ((void*)d3d_surface) << ")\n";
01326 exit(1);
01327 }
01328
01329 DWORD x_window_offset, y_window_offset;
01330 DWORD copy_width, copy_height;
01331
01332 D3DLOCKED_RECT locked_rect;
01333 D3DSURFACE_DESC surface_desc;
01334
01335 hr = d3d_surface->GetDesc(&surface_desc);
01336
01337 x_window_offset = source_rect.left, y_window_offset = source_rect.top;
01338 copy_width = RECT_XSIZE(source_rect);
01339 copy_height = RECT_YSIZE(source_rect);
01340
01341
01342
01343
01344 if (!((copy_width == result->get_x_size()) && (copy_height <= (DWORD)result->get_y_size()))) {
01345 dxgsg9_cat.error()
01346 << "d3d_surface_to_texture, Texture size (" << result->get_x_size()
01347 << ", " << result->get_y_size()
01348 << ") too small to hold display surface ("
01349 << copy_width << ", " << copy_height << ")\n";
01350 nassertr(false, E_FAIL);
01351 return E_FAIL;
01352 }
01353
01354 hr = d3d_surface->LockRect(&locked_rect, (CONST RECT*)NULL, (D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE));
01355 if (FAILED(hr)) {
01356 dxgsg9_cat.error()
01357 << "d3d_surface_to_texture LockRect() failed!" << D3DERRORSTRING(hr);
01358 return hr;
01359 }
01360
01361
01362 nassertr((surface_desc.Format == D3DFMT_A8R8G8B8) ||
01363 (surface_desc.Format == D3DFMT_X8R8G8B8) ||
01364 (surface_desc.Format == D3DFMT_R8G8B8) ||
01365 (surface_desc.Format == D3DFMT_R5G6B5) ||
01366 (surface_desc.Format == D3DFMT_X1R5G5B5) ||
01367 (surface_desc.Format == D3DFMT_A1R5G5B5) ||
01368 (surface_desc.Format == D3DFMT_A4R4G4B4), E_FAIL);
01369
01370
01371
01372 int byte_pitch = locked_rect.Pitch;
01373 BYTE *surface_bytes = (BYTE *)locked_rect.pBits;
01374
01375 if (inverted) {
01376 surface_bytes += byte_pitch * (y_window_offset + copy_height - 1);
01377 byte_pitch = -byte_pitch;
01378 } else {
01379 surface_bytes += byte_pitch * y_window_offset;
01380 }
01381
01382
01383
01384
01385 if (DEBUG_SURFACES && dxgsg9_cat.is_debug()) {
01386 dxgsg9_cat.debug()
01387 << "d3d_surface_to_texture converting "
01388 << D3DFormatStr(surface_desc.Format)
01389 << " DDSurf to " << num_components << "-channel panda Texture\n";
01390 }
01391
01392 DWORD *dest_word = (DWORD *)buf;
01393 BYTE *dest_byte = (BYTE *)buf;
01394
01395 switch(surface_desc.Format) {
01396 case D3DFMT_A8R8G8B8:
01397 case D3DFMT_X8R8G8B8: {
01398 if (num_components == 4) {
01399 DWORD *source_word;
01400 BYTE *dest_line = (BYTE*)dest_word;
01401
01402 for (DWORD y = 0; y < copy_height; y++) {
01403 source_word = ((DWORD*)surface_bytes) + x_window_offset;
01404 memcpy(dest_line, source_word, byte_pitch);
01405 dest_line += byte_pitch;
01406 surface_bytes += byte_pitch;
01407 }
01408 } else {
01409
01410 DWORD *source_word;
01411 for (DWORD y = 0; y < copy_height; y++) {
01412 source_word = ((DWORD*)surface_bytes) + x_window_offset;
01413
01414 for (DWORD x = 0; x < copy_width; x++) {
01415 BYTE r, g, b;
01416 DWORD pixel = *source_word;
01417
01418 r = (BYTE)((pixel>>16) & g_LowByteMask);
01419 g = (BYTE)((pixel>> 8) & g_LowByteMask);
01420 b = (BYTE)((pixel ) & g_LowByteMask);
01421
01422 *dest_byte++ = b;
01423 *dest_byte++ = g;
01424 *dest_byte++ = r;
01425 source_word++;
01426 }
01427 surface_bytes += byte_pitch;
01428 }
01429 }
01430 break;
01431 }
01432
01433 case D3DFMT_R8G8B8: {
01434 BYTE *source_byte;
01435
01436 if (num_components == 4) {
01437 for (DWORD y = 0; y < copy_height; y++) {
01438 source_byte = surface_bytes + x_window_offset * 3 * sizeof(BYTE);
01439 for (DWORD x = 0; x < copy_width; x++) {
01440 DWORD r, g, b;
01441
01442 b = *source_byte++;
01443 g = *source_byte++;
01444 r = *source_byte++;
01445
01446 *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b;
01447 dest_word++;
01448 }
01449 surface_bytes += byte_pitch;
01450 }
01451 } else {
01452
01453 for (DWORD y = 0; y < copy_height; y++) {
01454 source_byte = surface_bytes + x_window_offset * 3 * sizeof(BYTE);
01455 memcpy(dest_byte, source_byte, byte_pitch);
01456 dest_byte += byte_pitch;
01457 surface_bytes += byte_pitch;
01458 }
01459 }
01460 break;
01461 }
01462
01463 case D3DFMT_R5G6B5:
01464 case D3DFMT_X1R5G5B5:
01465 case D3DFMT_A1R5G5B5:
01466 case D3DFMT_A4R4G4B4: {
01467 WORD *source_word;
01468
01469
01470 BYTE redshift, greenshift, blueshift;
01471 DWORD redmask, greenmask, bluemask;
01472
01473 if (surface_desc.Format == D3DFMT_R5G6B5) {
01474 redshift = (11-3);
01475 redmask = 0xF800;
01476 greenmask = 0x07E0;
01477 greenshift = (5-2);
01478 bluemask = 0x001F;
01479 blueshift = 3;
01480 } else if (surface_desc.Format == D3DFMT_A4R4G4B4) {
01481 redmask = 0x0F00;
01482 redshift = 4;
01483 greenmask = 0x00F0;
01484 greenshift = 0;
01485 bluemask = 0x000F;
01486 blueshift = 4;
01487 } else {
01488 redmask = 0x7C00;
01489 redshift = (10-3);
01490 greenmask = 0x03E0;
01491 greenshift = (5-3);
01492 bluemask = 0x001F;
01493 blueshift = 3;
01494 }
01495
01496 if (num_components == 4) {
01497
01498
01499
01500
01501
01502
01503 for (DWORD y = 0; y < copy_height; y++) {
01504 source_word = ((WORD*)surface_bytes) + x_window_offset;
01505 for (DWORD x = 0; x < copy_width; x++) {
01506 WORD pixel = *source_word;
01507 BYTE r, g, b;
01508
01509 b = (pixel & bluemask) << blueshift;
01510 g = (pixel & greenmask) >> greenshift;
01511 r = (pixel & redmask) >> redshift;
01512
01513
01514
01515 *dest_word = 0xFF000000 | (r << 16) | (g << 8) | b;
01516 source_word++;
01517 dest_word++;
01518 }
01519 surface_bytes += byte_pitch;
01520 }
01521 } else {
01522
01523 for (DWORD y = 0; y < copy_height; y++) {
01524 source_word = ((WORD*)surface_bytes) + x_window_offset;
01525 for (DWORD x = 0; x < copy_width; x++) {
01526 WORD pixel = *source_word;
01527 BYTE r, g, b;
01528
01529 b = (pixel & bluemask) << blueshift;
01530 g = (pixel & greenmask) >> greenshift;
01531 r = (pixel & redmask) >> redshift;
01532
01533 *dest_byte++ = b;
01534 *dest_byte++ = g;
01535 *dest_byte++ = r;
01536
01537 source_word++;
01538 }
01539 surface_bytes += byte_pitch;
01540 }
01541 }
01542 break;
01543 }
01544
01545 default:
01546 dxgsg9_cat.error()
01547 << "d3d_surface_to_texture: unsupported D3DFORMAT!\n";
01548 }
01549
01550 d3d_surface->UnlockRect();
01551 return S_OK;
01552 }
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 static UINT calculate_row_byte_length (int width, int num_color_channels, D3DFORMAT tex_format)
01563 {
01564 UINT source_row_byte_length = 0;
01565
01566
01567 switch (tex_format) {
01568 case D3DFMT_DXT1:
01569
01570
01571 source_row_byte_length = max(1,width / 4)*8;
01572 break;
01573 case D3DFMT_DXT2:
01574 case D3DFMT_DXT3:
01575 case D3DFMT_DXT4:
01576 case D3DFMT_DXT5:
01577
01578 source_row_byte_length = max(1,width / 4)*16;
01579 break;
01580 default:
01581
01582 source_row_byte_length = width*num_color_channels;
01583 break;
01584 }
01585 return source_row_byte_length;
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format)
01597 {
01598
01599
01600 IDirect3DSurface9 *mip_surface = NULL;
01601 bool using_temp_buffer = false;
01602 HRESULT hr = E_FAIL;
01603 CPTA_uchar image = get_texture()->get_ram_mipmap_image(mip_level);
01604 nassertr(!image.is_null(), E_FAIL);
01605 BYTE *pixels = (BYTE*) image.p();
01606 DWORD width = (DWORD) get_texture()->get_expected_mipmap_x_size(mip_level);
01607 DWORD height = (DWORD) get_texture()->get_expected_mipmap_y_size(mip_level);
01608 int component_width = get_texture()->get_component_width();
01609
01610 size_t view_size = get_texture()->get_ram_mipmap_view_size(mip_level);
01611 pixels += view_size * get_view();
01612 size_t page_size = get_texture()->get_expected_ram_mipmap_page_size(mip_level);
01613 pixels += page_size * depth_index;
01614
01615 if (get_texture()->get_texture_type() == Texture::TT_cube_map) {
01616 nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
01617 hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)depth_index, mip_level, &mip_surface);
01618 } else {
01619 nassertr(IS_VALID_PTR(_d3d_2d_texture), E_FAIL);
01620 hr = _d3d_2d_texture->GetSurfaceLevel(mip_level, &mip_surface);
01621 }
01622
01623 if (FAILED(hr)) {
01624 dxgsg9_cat.error()
01625 << "FillDDTextureMipmapPixels failed for " << get_texture()->get_name()
01626 << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
01627 return E_FAIL;
01628 }
01629
01630 RECT source_size;
01631 source_size.left = source_size.top = 0;
01632 source_size.right = width;
01633 source_size.bottom = height;
01634
01635 UINT source_row_byte_length = calculate_row_byte_length(width, get_texture()->get_num_components(), source_format);
01636
01637 DWORD mip_filter;
01638
01639
01640 mip_filter = D3DX_FILTER_LINEAR ;
01641
01642
01643
01644 if (_d3d_format == D3DFMT_A8) {
01645
01646 USHORT *temp_buffer = new USHORT[width * height];
01647 if (!IS_VALID_PTR(temp_buffer)) {
01648 dxgsg9_cat.error()
01649 << "FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
01650 goto exit_FillMipmapSurf;
01651 }
01652 using_temp_buffer = true;
01653
01654 USHORT *out_pixels = temp_buffer;
01655 BYTE *source_pixels = pixels + component_width - 1;
01656 for (UINT y = 0; y < height; y++) {
01657 for (UINT x = 0; x < width; x++, source_pixels += component_width, out_pixels++) {
01658
01659
01660
01661 *out_pixels = ((*source_pixels) << 8 ) | 0xFF;
01662 }
01663 }
01664
01665 source_format = D3DFMT_A8L8;
01666 source_row_byte_length = width * sizeof(USHORT);
01667 pixels = (BYTE*)temp_buffer;
01668 }
01669 else if (component_width != 1) {
01670
01671
01672
01673
01674
01675 int num_components = get_texture()->get_num_components();
01676 int num_pixels = width * height * num_components;
01677 BYTE *temp_buffer = new BYTE[num_pixels];
01678 if (!IS_VALID_PTR(temp_buffer)) {
01679 dxgsg9_cat.error() << "FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
01680 goto exit_FillMipmapSurf;
01681 }
01682 using_temp_buffer = true;
01683
01684 BYTE *source_pixels = pixels + component_width - 1;
01685 for (int i = 0; i < num_pixels; i++) {
01686 temp_buffer[i] = *source_pixels;
01687 source_pixels += component_width;
01688 }
01689 pixels = (BYTE*)temp_buffer;
01690 }
01691
01692
01693 #ifdef DO_PSTATS
01694 GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_row_byte_length * height);
01695 #endif
01696 hr = D3DXLoadSurfaceFromMemory
01697 (mip_surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)pixels,
01698 source_format, source_row_byte_length, (PALETTEENTRY*)NULL,
01699 &source_size, mip_filter, (D3DCOLOR)0x0);
01700 if (FAILED(hr)) {
01701 dxgsg9_cat.error()
01702 << "FillDDTextureMipmapPixels failed for " << get_texture()->get_name()
01703 << ", mip_level " << mip_level
01704 << ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
01705 }
01706
01707 exit_FillMipmapSurf:
01708 if (using_temp_buffer) {
01709 SAFE_DELETE_ARRAY(pixels);
01710 }
01711
01712 RELEASE(mip_surface, dxgsg9, "FillDDTextureMipmapPixels MipSurface texture ptr", RELEASE_ONCE);
01713 return hr;
01714 }
01715
01716
01717
01718
01719
01720
01721 HRESULT DXTextureContext9::
01722 fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
01723 IDirect3DDevice9 *device = scrn._d3d_device;
01724 Texture *tex = get_texture();
01725 nassertr(IS_VALID_PTR(tex), E_FAIL);
01726 if (tex->get_texture_type() == Texture::TT_3d_texture) {
01727 return fill_d3d_volume_texture_pixels(scrn);
01728 }
01729
01730 HRESULT hr = E_FAIL;
01731
01732 CPTA_uchar image;
01733 Texture::CompressionMode image_compression = Texture::CM_off;
01734 if (compress_texture) {
01735
01736
01737 image = tex->get_ram_image();
01738 if (!image.is_null()) {
01739 image_compression = tex->get_ram_image_compression();
01740 }
01741 } else {
01742
01743
01744
01745
01746 image = tex->get_uncompressed_ram_image();
01747 }
01748
01749 if (image.is_null()) {
01750
01751
01752
01753 if (tex->get_render_to_texture()) {
01754 HRESULT result;
01755
01756 if (_d3d_2d_texture) {
01757
01758 IDirect3DSurface9 *surface;
01759
01760 result = _d3d_2d_texture -> GetSurfaceLevel (0, &surface);
01761 if (result == D3D_OK) {
01762 D3DSURFACE_DESC surface_description;
01763
01764 if (surface -> GetDesc (&surface_description) == D3D_OK) {
01765 IDirect3DSurface9 *current_render_target;
01766
01767 if (device -> GetRenderTarget (0, ¤t_render_target) == D3D_OK) {
01768 IDirect3DSurface9 *depth_stencil_surface;
01769
01770
01771 depth_stencil_surface = 0;
01772 if (device -> GetDepthStencilSurface (&depth_stencil_surface) == D3D_OK) {
01773 if (device -> SetDepthStencilSurface (NULL) == D3D_OK) {
01774
01775 }
01776 }
01777
01778 if (device -> SetRenderTarget (0, surface) == D3D_OK) {
01779 DWORD flags;
01780 D3DCOLOR color;
01781
01782 color = 0xFF000000;
01783 flags = D3DCLEAR_TARGET;
01784 if (device -> Clear (NULL, NULL, flags, color, 0.0f, 0) == D3D_OK) {
01785 }
01786 }
01787
01788
01789 if (depth_stencil_surface) {
01790 device -> SetDepthStencilSurface (depth_stencil_surface);
01791 depth_stencil_surface -> Release();
01792 }
01793
01794
01795 device -> SetRenderTarget (0, current_render_target);
01796 current_render_target -> Release();
01797 }
01798 }
01799
01800 surface -> Release();
01801 }
01802 }
01803
01804 return S_OK;
01805 }
01806 return E_FAIL;
01807 }
01808 nassertr(IS_VALID_PTR((BYTE*)image.p()), E_FAIL);
01809 nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
01810
01811 PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
01812
01813 DWORD orig_depth = (DWORD) tex->get_z_size();
01814 D3DFORMAT source_format = _d3d_format;
01815
01816
01817 switch (image_compression) {
01818 case Texture::CM_dxt1:
01819 source_format = D3DFMT_DXT1;
01820 break;
01821 case Texture::CM_dxt2:
01822 source_format = D3DFMT_DXT2;
01823 break;
01824 case Texture::CM_dxt3:
01825 source_format = D3DFMT_DXT3;
01826 break;
01827 case Texture::CM_dxt4:
01828 source_format = D3DFMT_DXT4;
01829 break;
01830 case Texture::CM_dxt5:
01831 source_format = D3DFMT_DXT5;
01832 break;
01833 default:
01834
01835 break;
01836 }
01837
01838 for (unsigned int di = 0; di < orig_depth; di++) {
01839
01840
01841 hr = fill_d3d_texture_mipmap_pixels(0, di, source_format);
01842 if (FAILED(hr)) {
01843 return hr;
01844 }
01845
01846 if (_has_mipmaps) {
01847
01848 int miplevel_count = _d3d_texture->GetLevelCount();
01849 if (miplevel_count <= tex->get_num_loadable_ram_mipmap_images()) {
01850 dxgsg9_cat.debug()
01851 << "Using pre-calculated mipmap levels for texture " << tex->get_name() << "\n";
01852
01853 for (int mip_level = 1; mip_level < miplevel_count; ++mip_level) {
01854 hr = fill_d3d_texture_mipmap_pixels(mip_level, di, source_format);
01855 if (FAILED(hr)) {
01856 return hr;
01857 }
01858 }
01859 }
01860 else {
01861
01862
01863 if (_managed == false && scrn._supports_automatic_mipmap_generation) {
01864 if (false)
01865 {
01866
01867
01868
01869 hr = _d3d_texture -> SetAutoGenFilterType (D3DTEXF_LINEAR);
01870 if (FAILED(hr)) {
01871 dxgsg9_cat.error() << "SetAutoGenFilterType failed " << D3DERRORSTRING(hr);
01872 }
01873
01874 _d3d_texture -> GenerateMipSubLevels ( );
01875 }
01876 }
01877 else {
01878 DWORD mip_filter_flags;
01879 if (!dx_use_triangle_mipgen_filter) {
01880 mip_filter_flags = D3DX_FILTER_BOX;
01881 } else {
01882 mip_filter_flags = D3DX_FILTER_TRIANGLE;
01883 }
01884
01885
01886 hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
01887 mip_filter_flags);
01888
01889 if (FAILED(hr)) {
01890 dxgsg9_cat.error()
01891 << "FillDDSurfaceTexturePixels failed for " << tex->get_name()
01892 << ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
01893 }
01894 }
01895 }
01896 }
01897 }
01898
01899 return hr;
01900 }
01901
01902
01903
01904
01905
01906
01907
01908 HRESULT DXTextureContext9::
01909 fill_d3d_volume_texture_pixels(DXScreenData &scrn) {
01910 Texture *tex = get_texture();
01911 HRESULT hr = E_FAIL;
01912 nassertr(IS_VALID_PTR(tex), E_FAIL);
01913
01914 CPTA_uchar image;
01915 if (scrn._dxgsg9->get_supports_compressed_texture()) {
01916 image = tex->get_ram_image();
01917 } else {
01918 image = tex->get_uncompressed_ram_image();
01919 }
01920
01921 Texture::CompressionMode image_compression;
01922 if (image.is_null()) {
01923 image_compression = Texture::CM_off;
01924 } else {
01925 image_compression = tex->get_ram_image_compression();
01926 }
01927
01928 if (!scrn._dxgsg9->get_supports_compressed_texture_format(image_compression)) {
01929 image = tex->get_uncompressed_ram_image();
01930 image_compression = Texture::CM_off;
01931 }
01932
01933 if (image.is_null()) {
01934
01935
01936
01937 return S_OK;
01938 }
01939
01940 PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
01941
01942 nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL);
01943 nassertr(tex->get_texture_type() == Texture::TT_3d_texture, E_FAIL);
01944
01945 DWORD orig_width = (DWORD) tex->get_x_size();
01946 DWORD orig_height = (DWORD) tex->get_y_size();
01947 DWORD orig_depth = (DWORD) tex->get_z_size();
01948 DWORD num_color_channels = tex->get_num_components();
01949 D3DFORMAT source_format = _d3d_format;
01950 BYTE *image_pixels = (BYTE*)image.p();
01951 int component_width = tex->get_component_width();
01952
01953 nassertr(IS_VALID_PTR(image_pixels), E_FAIL);
01954
01955 size_t view_size = tex->get_ram_mipmap_view_size(0);
01956 image_pixels += view_size * get_view();
01957
01958 IDirect3DVolume9 *mip_level_0 = NULL;
01959 bool using_temp_buffer = false;
01960 BYTE *pixels = image_pixels;
01961
01962 nassertr(IS_VALID_PTR(_d3d_volume_texture), E_FAIL);
01963 hr = _d3d_volume_texture->GetVolumeLevel(0, &mip_level_0);
01964
01965 if (FAILED(hr)) {
01966 dxgsg9_cat.error()
01967 << "FillDDSurfaceTexturePixels failed for " << tex->get_name()
01968 << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
01969 return E_FAIL;
01970 }
01971
01972 D3DBOX source_size;
01973 source_size.Left = source_size.Top = source_size.Front = 0;
01974 source_size.Right = orig_width;
01975 source_size.Bottom = orig_height;
01976 source_size.Back = orig_depth;
01977
01978 UINT source_row_byte_length = orig_width * num_color_channels;
01979 UINT source_page_byte_length = orig_height * source_row_byte_length;
01980
01981 DWORD level_0_filter, mip_filter_flags;
01982 using_temp_buffer = false;
01983
01984
01985
01986 level_0_filter = D3DX_FILTER_LINEAR ;
01987
01988
01989
01990 if (_d3d_format == D3DFMT_A8) {
01991
01992 USHORT *temp_buffer = new USHORT[orig_width * orig_height * orig_depth];
01993 if (!IS_VALID_PTR(temp_buffer)) {
01994 dxgsg9_cat.error()
01995 << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
01996 goto exit_FillDDSurf;
01997 }
01998 using_temp_buffer = true;
01999
02000 USHORT *out_pixels = temp_buffer;
02001 BYTE *source_pixels = pixels + component_width - 1;
02002 for (UINT z = 0; z < orig_depth; z++) {
02003 for (UINT y = 0; y < orig_height; y++) {
02004 for (UINT x = 0;
02005 x < orig_width;
02006 x++, source_pixels += component_width, out_pixels++) {
02007
02008
02009
02010 *out_pixels = ((*source_pixels) << 8 ) | 0xFF;
02011 }
02012 }
02013 }
02014
02015 source_format = D3DFMT_A8L8;
02016 source_row_byte_length = orig_width * sizeof(USHORT);
02017 source_page_byte_length = orig_height * source_row_byte_length;
02018 pixels = (BYTE*)temp_buffer;
02019
02020 } else if (component_width != 1) {
02021
02022
02023
02024
02025
02026 int num_components = tex->get_num_components();
02027 int num_pixels = orig_width * orig_height * orig_depth * num_components;
02028 BYTE *temp_buffer = new BYTE[num_pixels];
02029 if (!IS_VALID_PTR(temp_buffer)) {
02030 dxgsg9_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
02031 goto exit_FillDDSurf;
02032 }
02033 using_temp_buffer = true;
02034
02035 BYTE *source_pixels = pixels + component_width - 1;
02036 for (int i = 0; i < num_pixels; i++) {
02037 temp_buffer[i] = *source_pixels;
02038 source_pixels += component_width;
02039 }
02040 pixels = (BYTE*)temp_buffer;
02041 }
02042
02043
02044
02045 #ifdef DO_PSTATS
02046 GraphicsStateGuardian::_data_transferred_pcollector.add_level(source_page_byte_length * orig_depth);
02047 #endif
02048 hr = D3DXLoadVolumeFromMemory
02049 (mip_level_0, (PALETTEENTRY*)NULL, (D3DBOX*)NULL, (LPCVOID)pixels,
02050 source_format, source_row_byte_length, source_page_byte_length,
02051 (PALETTEENTRY*)NULL,
02052 &source_size, level_0_filter, (D3DCOLOR)0x0);
02053 if (FAILED(hr)) {
02054 dxgsg9_cat.error()
02055 << "FillDDSurfaceTexturePixels failed for " << tex->get_name()
02056 << ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr);
02057 goto exit_FillDDSurf;
02058 }
02059
02060 if (_has_mipmaps) {
02061 if (!dx_use_triangle_mipgen_filter) {
02062 mip_filter_flags = D3DX_FILTER_BOX;
02063 } else {
02064 mip_filter_flags = D3DX_FILTER_TRIANGLE;
02065 }
02066
02067
02068
02069 hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
02070 mip_filter_flags);
02071 if (FAILED(hr)) {
02072 dxgsg9_cat.error()
02073 << "FillDDSurfaceTexturePixels failed for " << tex->get_name()
02074 << ", D3DXFilterTex failed" << D3DERRORSTRING(hr);
02075 goto exit_FillDDSurf;
02076 }
02077 }
02078
02079 exit_FillDDSurf:
02080 if (using_temp_buffer) {
02081 SAFE_DELETE_ARRAY(pixels);
02082 }
02083 RELEASE(mip_level_0, dxgsg9, "FillDDSurf MipLev0 texture ptr", RELEASE_ONCE);
02084 return hr;
02085 }
02086
02087
02088
02089
02090
02091
02092
02093
02094 int DXTextureContext9::
02095 down_to_power_2(int value) {
02096 int x = 1;
02097 while ((x << 1) <= value) {
02098 x = (x << 1);
02099 }
02100 return x;
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111 unsigned int DXTextureContext9::
02112 get_bits_per_pixel(Texture::Format format, int *alphbits) {
02113 *alphbits = 0;
02114 switch(format) {
02115 case Texture::F_alpha:
02116 *alphbits = 8;
02117 case Texture::F_color_index:
02118 case Texture::F_red:
02119 case Texture::F_green:
02120 case Texture::F_blue:
02121 case Texture::F_rgb332:
02122 return 8;
02123 case Texture::F_luminance_alphamask:
02124 *alphbits = 1;
02125 return 16;
02126 case Texture::F_luminance_alpha:
02127 *alphbits = 8;
02128 return 16;
02129 case Texture::F_luminance:
02130 return 8;
02131 case Texture::F_rgba4:
02132 *alphbits = 4;
02133 return 16;
02134 case Texture::F_rgba5:
02135 *alphbits = 1;
02136 return 16;
02137 case Texture::F_depth_component:
02138 return 16;
02139 case Texture::F_depth_stencil:
02140 return 32;
02141 case Texture::F_rgb5:
02142 return 16;
02143 case Texture::F_rgb8:
02144 case Texture::F_rgb:
02145 return 24;
02146 case Texture::F_rgba8:
02147 case Texture::F_rgba:
02148 *alphbits = 8;
02149 return 32;
02150 case Texture::F_rgbm:
02151 *alphbits = 1;
02152 return 32;
02153 case Texture::F_rgb12:
02154 return 36;
02155 case Texture::F_rgba12:
02156 *alphbits = 12;
02157 return 48;
02158 case Texture::F_rgba16:
02159 *alphbits = 16;
02160 return 64;
02161 case Texture::F_rgba32:
02162 *alphbits = 32;
02163 return 128;
02164 }
02165 return 8;
02166 }
02167
02168
02169
02170
02171
02172
02173 PN_stdfloat DXTextureContext9::
02174 d3d_format_to_bytes_per_pixel (D3DFORMAT format)
02175 {
02176 PN_stdfloat bytes_per_pixel;
02177
02178 bytes_per_pixel = 0.0f;
02179 switch (format)
02180 {
02181 case D3DFMT_R3G3B2:
02182 case D3DFMT_A8:
02183 case D3DFMT_A8P8:
02184 case D3DFMT_P8:
02185 case D3DFMT_L8:
02186 case D3DFMT_A4L4:
02187 bytes_per_pixel = 1.0f;
02188 break;
02189
02190 case D3DFMT_R16F:
02191 case D3DFMT_CxV8U8:
02192 case D3DFMT_V8U8:
02193 case D3DFMT_R5G6B5:
02194 case D3DFMT_X1R5G5B5:
02195 case D3DFMT_A1R5G5B5:
02196 case D3DFMT_A4R4G4B4:
02197 case D3DFMT_L16:
02198 case D3DFMT_A8L8:
02199 case D3DFMT_A8R3G3B2:
02200 case D3DFMT_X4R4G4B4:
02201 bytes_per_pixel = 2.0f;
02202 break;
02203
02204 case D3DFMT_R8G8B8:
02205 bytes_per_pixel = 3.0f;
02206 break;
02207
02208 case D3DFMT_G16R16F:
02209 case D3DFMT_Q8W8V8U8:
02210 case D3DFMT_V16U16:
02211 case D3DFMT_R32F:
02212 case D3DFMT_A8R8G8B8:
02213 case D3DFMT_X8R8G8B8:
02214 case D3DFMT_A2B10G10R10:
02215 case D3DFMT_A8B8G8R8:
02216 case D3DFMT_X8B8G8R8:
02217 case D3DFMT_G16R16:
02218 case D3DFMT_A2R10G10B10:
02219 bytes_per_pixel = 4.0f;
02220 break;
02221
02222 case D3DFMT_G32R32F:
02223 case D3DFMT_A16B16G16R16F:
02224 case D3DFMT_Q16W16V16U16:
02225 case D3DFMT_A16B16G16R16:
02226 bytes_per_pixel = 8.0f;
02227 break;
02228
02229 case D3DFMT_A32B32G32R32F:
02230 bytes_per_pixel = 16.0f;
02231 break;
02232
02233 case D3DFMT_DXT1:
02234 bytes_per_pixel = 0.5f;
02235 break;
02236 case D3DFMT_DXT2:
02237 case D3DFMT_DXT3:
02238 case D3DFMT_DXT4:
02239 case D3DFMT_DXT5:
02240 bytes_per_pixel = 1.0f;
02241 break;
02242 }
02243
02244 return bytes_per_pixel;
02245 }