29
29
/* *************************************************************************/
30
30
31
31
#include " texture_loader_dds.h"
32
+ #include " image_loader_dds.h"
32
33
33
34
#include " core/io/file_access.h"
34
35
#include " scene/resources/image_texture.h"
35
36
36
- #define PF_FOURCC (s ) ((uint32_t )(((s)[3 ] << 24U ) | ((s)[2 ] << 16U ) | ((s)[1 ] << 8U ) | ((s)[0 ])))
37
-
38
- // Reference: https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
39
-
40
- enum {
41
- DDS_MAGIC = 0x20534444 ,
42
- DDSD_PITCH = 0x00000008 ,
43
- DDSD_LINEARSIZE = 0x00080000 ,
44
- DDSD_MIPMAPCOUNT = 0x00020000 ,
45
- DDPF_FOURCC = 0x00000004 ,
46
- DDPF_ALPHAPIXELS = 0x00000001 ,
47
- DDPF_INDEXED = 0x00000020 ,
48
- DDPF_RGB = 0x00000040 ,
49
- };
50
-
51
- enum DDSFormat {
52
- DDS_DXT1,
53
- DDS_DXT3,
54
- DDS_DXT5,
55
- DDS_ATI1,
56
- DDS_ATI2,
57
- DDS_A2XY,
58
- DDS_BGRA8,
59
- DDS_BGR8,
60
- DDS_RGBA8, // flipped in dds
61
- DDS_RGB8, // flipped in dds
62
- DDS_BGR5A1,
63
- DDS_BGR565,
64
- DDS_BGR10A2,
65
- DDS_INDEXED,
66
- DDS_LUMINANCE,
67
- DDS_LUMINANCE_ALPHA,
68
- DDS_MAX
69
- };
70
-
71
- struct DDSFormatInfo {
72
- const char *name = nullptr ;
73
- bool compressed = false ;
74
- bool palette = false ;
75
- uint32_t divisor = 0 ;
76
- uint32_t block_size = 0 ;
77
- Image::Format format = Image::Format::FORMAT_BPTC_RGBA;
78
- };
79
-
80
- static const DDSFormatInfo dds_format_info[DDS_MAX] = {
81
- { " DXT1/BC1" , true , false , 4 , 8 , Image::FORMAT_DXT1 },
82
- { " DXT3/BC2" , true , false , 4 , 16 , Image::FORMAT_DXT3 },
83
- { " DXT5/BC3" , true , false , 4 , 16 , Image::FORMAT_DXT5 },
84
- { " ATI1/BC4" , true , false , 4 , 8 , Image::FORMAT_RGTC_R },
85
- { " ATI2/3DC/BC5" , true , false , 4 , 16 , Image::FORMAT_RGTC_RG },
86
- { " A2XY/DXN/BC5" , true , false , 4 , 16 , Image::FORMAT_RGTC_RG },
87
- { " BGRA8" , false , false , 1 , 4 , Image::FORMAT_RGBA8 },
88
- { " BGR8" , false , false , 1 , 3 , Image::FORMAT_RGB8 },
89
- { " RGBA8" , false , false , 1 , 4 , Image::FORMAT_RGBA8 },
90
- { " RGB8" , false , false , 1 , 3 , Image::FORMAT_RGB8 },
91
- { " BGR5A1" , false , false , 1 , 2 , Image::FORMAT_RGBA8 },
92
- { " BGR565" , false , false , 1 , 2 , Image::FORMAT_RGB8 },
93
- { " BGR10A2" , false , false , 1 , 4 , Image::FORMAT_RGBA8 },
94
- { " GRAYSCALE" , false , false , 1 , 1 , Image::FORMAT_L8 },
95
- { " GRAYSCALE_ALPHA" , false , false , 1 , 2 , Image::FORMAT_LA8 }
96
- };
97
-
98
37
Ref<Resource> ResourceFormatDDS::load (const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
99
38
if (r_error) {
100
39
*r_error = ERR_CANT_OPEN;
@@ -113,303 +52,12 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig
113
52
114
53
ERR_FAIL_COND_V_MSG (err != OK, Ref<Resource>(), " Unable to open DDS texture file '" + p_path + " '." );
115
54
116
- uint32_t magic = f->get_32 ();
117
- uint32_t hsize = f->get_32 ();
118
- uint32_t flags = f->get_32 ();
119
- uint32_t height = f->get_32 ();
120
- uint32_t width = f->get_32 ();
121
- uint32_t pitch = f->get_32 ();
122
- /* uint32_t depth = */ f->get_32 ();
123
- uint32_t mipmaps = f->get_32 ();
124
-
125
- // skip 11
126
- for (int i = 0 ; i < 11 ; i++) {
127
- f->get_32 ();
128
- }
129
-
130
- // validate
131
-
132
- // We don't check DDSD_CAPS or DDSD_PIXELFORMAT, as they're mandatory when writing,
133
- // but non-mandatory when reading (as some writers don't set them)...
134
- if (magic != DDS_MAGIC || hsize != 124 ) {
135
- ERR_FAIL_V_MSG (Ref<Resource>(), " Invalid or unsupported DDS texture file '" + p_path + " '." );
136
- }
137
-
138
- /* uint32_t format_size = */ f->get_32 ();
139
- uint32_t format_flags = f->get_32 ();
140
- uint32_t format_fourcc = f->get_32 ();
141
- uint32_t format_rgb_bits = f->get_32 ();
142
- uint32_t format_red_mask = f->get_32 ();
143
- uint32_t format_green_mask = f->get_32 ();
144
- uint32_t format_blue_mask = f->get_32 ();
145
- uint32_t format_alpha_mask = f->get_32 ();
146
-
147
- /* uint32_t caps_1 = */ f->get_32 ();
148
- /* uint32_t caps_2 = */ f->get_32 ();
149
- /* uint32_t caps_ddsx = */ f->get_32 ();
150
-
151
- // reserved skip
152
- f->get_32 ();
153
- f->get_32 ();
154
-
155
- /*
156
- print_line("DDS width: "+itos(width));
157
- print_line("DDS height: "+itos(height));
158
- print_line("DDS mipmaps: "+itos(mipmaps));
159
-
160
- printf("fourcc: %x fflags: %x, rgbbits: %x, fsize: %x\n",format_fourcc,format_flags,format_rgb_bits,format_size);
161
- printf("rmask: %x gmask: %x, bmask: %x, amask: %x\n",format_red_mask,format_green_mask,format_blue_mask,format_alpha_mask);
162
- */
163
-
164
- // must avoid this later
165
- while (f->get_position () < 128 ) {
166
- f->get_8 ();
167
- }
168
-
169
- DDSFormat dds_format;
170
-
171
- if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" DXT1" )) {
172
- dds_format = DDS_DXT1;
173
- } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" DXT3" )) {
174
- dds_format = DDS_DXT3;
175
-
176
- } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" DXT5" )) {
177
- dds_format = DDS_DXT5;
178
- } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" ATI1" )) {
179
- dds_format = DDS_ATI1;
180
- } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" ATI2" )) {
181
- dds_format = DDS_ATI2;
182
- } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC (" A2XY" )) {
183
- dds_format = DDS_A2XY;
184
-
185
- } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff && format_alpha_mask == 0xff000000 ) {
186
- dds_format = DDS_BGRA8;
187
- } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 24 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff ) {
188
- dds_format = DDS_BGR8;
189
- } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000 && format_alpha_mask == 0xff000000 ) {
190
- dds_format = DDS_RGBA8;
191
- } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 24 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000 ) {
192
- dds_format = DDS_RGB8;
193
-
194
- } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 16 && format_red_mask == 0x00007c00 && format_green_mask == 0x000003e0 && format_blue_mask == 0x0000001f && format_alpha_mask == 0x00008000 ) {
195
- dds_format = DDS_BGR5A1;
196
- } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0x3ff00000 && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff && format_alpha_mask == 0xc0000000 ) {
197
- dds_format = DDS_BGR10A2;
198
- } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 16 && format_red_mask == 0x0000f800 && format_green_mask == 0x000007e0 && format_blue_mask == 0x0000001f ) {
199
- dds_format = DDS_BGR565;
200
- } else if (!(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 8 && format_red_mask == 0xff && format_green_mask == 0xff && format_blue_mask == 0xff ) {
201
- dds_format = DDS_LUMINANCE;
202
- } else if ((format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 16 && format_red_mask == 0xff && format_green_mask == 0xff && format_blue_mask == 0xff && format_alpha_mask == 0xff00 ) {
203
- dds_format = DDS_LUMINANCE_ALPHA;
204
- } else if (format_flags & DDPF_INDEXED && format_rgb_bits == 8 ) {
205
- dds_format = DDS_BGR565;
206
- } else {
207
- // printf("unrecognized fourcc %x format_flags: %x - rgbbits %i - red_mask %x green mask %x blue mask %x alpha mask %x\n", format_fourcc, format_flags, format_rgb_bits, format_red_mask, format_green_mask, format_blue_mask, format_alpha_mask);
208
- ERR_FAIL_V_MSG (Ref<Resource>(), " Unrecognized or unsupported color layout in DDS '" + p_path + " '." );
209
- }
210
-
211
- if (!(flags & DDSD_MIPMAPCOUNT)) {
212
- mipmaps = 1 ;
213
- }
214
-
215
- Vector<uint8_t > src_data;
216
-
217
- const DDSFormatInfo &info = dds_format_info[dds_format];
218
- uint32_t w = width;
219
- uint32_t h = height;
220
-
221
- if (info.compressed ) {
222
- // compressed bc
223
-
224
- uint32_t size = MAX (info.divisor , w) / info.divisor * MAX (info.divisor , h) / info.divisor * info.block_size ;
225
- ERR_FAIL_COND_V (size != pitch, Ref<Resource>());
226
- ERR_FAIL_COND_V (!(flags & DDSD_LINEARSIZE), Ref<Resource>());
227
-
228
- for (uint32_t i = 1 ; i < mipmaps; i++) {
229
- w = MAX (1u , w >> 1 );
230
- h = MAX (1u , h >> 1 );
231
- uint32_t bsize = MAX (info.divisor , w) / info.divisor * MAX (info.divisor , h) / info.divisor * info.block_size ;
232
- // printf("%i x %i - block: %i\n",w,h,bsize);
233
- size += bsize;
234
- }
235
-
236
- src_data.resize (size);
237
- uint8_t *wb = src_data.ptrw ();
238
- f->get_buffer (wb, size);
239
-
240
- } else if (info.palette ) {
241
- // indexed
242
- ERR_FAIL_COND_V (!(flags & DDSD_PITCH), Ref<Resource>());
243
- ERR_FAIL_COND_V (format_rgb_bits != 8 , Ref<Resource>());
244
-
245
- uint32_t size = pitch * height;
246
- ERR_FAIL_COND_V (size != width * height * info.block_size , Ref<Resource>());
247
-
248
- uint8_t palette[256 * 4 ];
249
- f->get_buffer (palette, 256 * 4 );
250
-
251
- int colsize = 3 ;
252
- for (int i = 0 ; i < 256 ; i++) {
253
- if (palette[i * 4 + 3 ] < 255 ) {
254
- colsize = 4 ;
255
- }
256
- }
257
-
258
- int w2 = width;
259
- int h2 = height;
260
-
261
- for (uint32_t i = 1 ; i < mipmaps; i++) {
262
- w2 = (w2 + 1 ) >> 1 ;
263
- h2 = (h2 + 1 ) >> 1 ;
264
- size += w2 * h2 * info.block_size ;
265
- }
266
-
267
- src_data.resize (size + 256 * colsize);
268
- uint8_t *wb = src_data.ptrw ();
269
- f->get_buffer (wb, size);
270
-
271
- for (int i = 0 ; i < 256 ; i++) {
272
- int dst_ofs = size + i * colsize;
273
- int src_ofs = i * 4 ;
274
- wb[dst_ofs + 0 ] = palette[src_ofs + 2 ];
275
- wb[dst_ofs + 1 ] = palette[src_ofs + 1 ];
276
- wb[dst_ofs + 2 ] = palette[src_ofs + 0 ];
277
- if (colsize == 4 ) {
278
- wb[dst_ofs + 3 ] = palette[src_ofs + 3 ];
279
- }
280
- }
281
- } else {
282
- // uncompressed generic...
283
-
284
- uint32_t size = width * height * info.block_size ;
285
-
286
- for (uint32_t i = 1 ; i < mipmaps; i++) {
287
- w = (w + 1 ) >> 1 ;
288
- h = (h + 1 ) >> 1 ;
289
- size += w * h * info.block_size ;
290
- }
291
-
292
- if (dds_format == DDS_BGR565) {
293
- size = size * 3 / 2 ;
294
- } else if (dds_format == DDS_BGR5A1) {
295
- size = size * 2 ;
296
- }
297
-
298
- src_data.resize (size);
299
- uint8_t *wb = src_data.ptrw ();
300
- f->get_buffer (wb, size);
301
-
302
- switch (dds_format) {
303
- case DDS_BGR5A1: {
304
- // TO RGBA
305
- int colcount = size / 4 ;
306
-
307
- for (int i = colcount - 1 ; i >= 0 ; i--) {
308
- int src_ofs = i * 2 ;
309
- int dst_ofs = i * 4 ;
310
-
311
- uint8_t a = wb[src_ofs + 1 ] & 0x80 ;
312
- uint8_t b = wb[src_ofs] & 0x1F ;
313
- uint8_t g = (wb[src_ofs] >> 5 ) | ((wb[src_ofs + 1 ] & 0x3 ) << 3 );
314
- uint8_t r = (wb[src_ofs + 1 ] >> 2 ) & 0x1F ;
315
- wb[dst_ofs + 0 ] = r << 3 ;
316
- wb[dst_ofs + 1 ] = g << 3 ;
317
- wb[dst_ofs + 2 ] = b << 3 ;
318
- wb[dst_ofs + 3 ] = a ? 255 : 0 ;
319
- }
320
- } break ;
321
- case DDS_BGR565: {
322
- int colcount = size / 3 ;
323
-
324
- for (int i = colcount - 1 ; i >= 0 ; i--) {
325
- int src_ofs = i * 2 ;
326
- int dst_ofs = i * 3 ;
327
-
328
- uint8_t b = wb[src_ofs] & 0x1F ;
329
- uint8_t g = (wb[src_ofs] >> 5 ) | ((wb[src_ofs + 1 ] & 0x7 ) << 3 );
330
- uint8_t r = wb[src_ofs + 1 ] >> 3 ;
331
- wb[dst_ofs + 0 ] = r << 3 ;
332
- wb[dst_ofs + 1 ] = g << 2 ;
333
- wb[dst_ofs + 2 ] = b << 3 ; // b<<3;
334
- }
335
-
336
- } break ;
337
- case DDS_BGR10A2: {
338
- // TO RGBA
339
- int colcount = size / 4 ;
340
-
341
- for (int i = colcount - 1 ; i >= 0 ; i--) {
342
- int ofs = i * 4 ;
343
-
344
- uint32_t w32 = uint32_t (wb[ofs + 0 ]) | (uint32_t (wb[ofs + 1 ]) << 8 ) | (uint32_t (wb[ofs + 2 ]) << 16 ) | (uint32_t (wb[ofs + 3 ]) << 24 );
345
-
346
- uint8_t a = (w32 & 0xc0000000 ) >> 24 ;
347
- uint8_t r = (w32 & 0x3ff00000 ) >> 22 ;
348
- uint8_t g = (w32 & 0xffc00 ) >> 12 ;
349
- uint8_t b = (w32 & 0x3ff ) >> 2 ;
350
-
351
- wb[ofs + 0 ] = r;
352
- wb[ofs + 1 ] = g;
353
- wb[ofs + 2 ] = b;
354
- wb[ofs + 3 ] = a == 0xc0 ? 255 : a; // 0xc0 should be opaque
355
- }
356
- } break ;
357
- case DDS_BGRA8: {
358
- int colcount = size / 4 ;
359
-
360
- for (int i = 0 ; i < colcount; i++) {
361
- SWAP (wb[i * 4 + 0 ], wb[i * 4 + 2 ]);
362
- }
363
-
364
- } break ;
365
- case DDS_BGR8: {
366
- int colcount = size / 3 ;
367
-
368
- for (int i = 0 ; i < colcount; i++) {
369
- SWAP (wb[i * 3 + 0 ], wb[i * 3 + 2 ]);
370
- }
371
- } break ;
372
- case DDS_RGBA8: {
373
- /* do nothing either
374
- int colcount = size/4;
375
-
376
- for(int i=0;i<colcount;i++) {
377
- uint8_t r = wb[i*4+1];
378
- uint8_t g = wb[i*4+2];
379
- uint8_t b = wb[i*4+3];
380
- uint8_t a = wb[i*4+0];
381
-
382
- wb[i*4+0]=r;
383
- wb[i*4+1]=g;
384
- wb[i*4+2]=b;
385
- wb[i*4+3]=a;
386
- }
387
- */
388
- } break ;
389
- case DDS_RGB8: {
390
- // do nothing
391
- /*
392
- int colcount = size/3;
393
-
394
- for(int i=0;i<colcount;i++) {
395
- SWAP( wb[i*3+0],wb[i*3+2] );
396
- }*/
397
- } break ;
398
- case DDS_LUMINANCE: {
399
- // do nothing i guess?
400
-
401
- } break ;
402
- case DDS_LUMINANCE_ALPHA: {
403
- // do nothing i guess?
404
-
405
- } break ;
406
-
407
- default : {
408
- }
409
- }
55
+ Ref<Image> img = memnew (Image);
56
+ Error i_error = ImageLoaderDDS ().load_image (img, f, false , 1.0 );
57
+ if (r_error) {
58
+ *r_error = i_error;
410
59
}
411
60
412
- Ref<Image> img = memnew (Image (width, height, mipmaps - 1 , info.format , src_data));
413
61
Ref<ImageTexture> texture = ImageTexture::create_from_image (img);
414
62
415
63
if (r_error) {
0 commit comments