Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / GlideHQ / TxFilter.cpp
CommitLineData
98e75f2d 1/*
2 * Texture Filtering
3 * Version: 1.0
4 *
5 * Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
6 * Email koolsmoky(at)users.sourceforge.net
7 * Web http://www.3dfxzone.it/koolsmoky
8 *
9 * this is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * this is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Make; see the file COPYING. If not, write to
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#ifdef __MSC__
25#pragma warning(disable: 4786)
26#endif
27
28#include "TxFilter.h"
29#include "TextureFilters.h"
30#include "TxDbg.h"
31#include <functional>
32#include <thread>
33
34void TxFilter::clear()
35{
36 /* clear hires texture cache */
37 delete _txHiResCache;
38 _txHiResCache = NULL;
39
40 /* clear texture cache */
41 delete _txTexCache;
42 _txTexCache = NULL;
43
44 /* free memory */
45 TxMemBuf::getInstance()->shutdown();
46
47 /* clear other stuff */
48 delete _txImage;
49 _txImage = NULL;
50 delete _txQuantize;
51 _txQuantize = NULL;
52 delete _txUtil;
53 _txUtil = NULL;
54}
55
56TxFilter::~TxFilter()
57{
58 clear();
59}
60
61TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options,
62 int cachesize, wchar_t *datapath, wchar_t *cachepath,
63 wchar_t *ident, dispInfoFuncExt callback) :
64 _numcore(1), _tex1(NULL), _tex2(NULL), _maxwidth(0), _maxheight(0),
65 _maxbpp(0), _options(0), _cacheSize(0), _ident(), _datapath(), _cachepath(),
66 _txQuantize(NULL), _txTexCache(NULL), _txHiResCache(NULL), _txUtil(NULL),
67 _txImage(NULL), _initialized(false)
68{
69 clear(); /* gcc does not allow the destructor to be called */
70
71 /* shamelessness :P this first call to the debug output message creates
72 * a file in the executable directory. */
73 INFO(0, L"------------------------------------------------------------------\n");
74#ifdef GHQCHK
75 INFO(0, L" GlideHQ Hires Texture Checker 1.02.00.%d\n", 0);
76#else
77 INFO(0, L" GlideHQ version 1.02.00.%d\n", 0);
78#endif
79 INFO(0, L" Copyright (C) 2010 Hiroshi Morii All Rights Reserved\n");
80 INFO(0, L" email : koolsmoky(at)users.sourceforge.net\n");
81 INFO(0, L" website : http://www.3dfxzone.it/koolsmoky\n");
82 INFO(0, L"\n");
83 INFO(0, L" Glide64 official website : http://glide64.emuxhaven.net\n");
84 INFO(0, L"------------------------------------------------------------------\n");
85
86 _options = options;
87
88 _txImage = new TxImage();
89 _txQuantize = new TxQuantize();
90 _txUtil = new TxUtil();
91
92 /* get number of CPU cores. */
93 _numcore = _txUtil->getNumberofProcessors();
94
95 _initialized = 0;
96
97 _tex1 = NULL;
98 _tex2 = NULL;
99
100 /* XXX: anything larger than 1024 * 1024 is overkill */
101 _maxwidth = maxwidth > 1024 ? 1024 : maxwidth;
102 _maxheight = maxheight > 1024 ? 1024 : maxheight;
103 _maxbpp = maxbpp;
104
105 _cacheSize = cachesize;
106
107 /* TODO: validate options and do overrides here*/
108
109 /* save path name */
110 if (datapath)
111 _datapath.assign(datapath);
112 if (cachepath)
113 _cachepath.assign(cachepath);
114
115 /* save ROM name */
116 if (ident && wcscmp(ident, L"DEFAULT") != 0)
117 _ident.assign(ident);
118
119 /* check for dxtn extensions */
120 if (!TxLoadLib::getInstance()->getdxtCompressTexFuncExt())
121 _options &= ~S3TC_COMPRESSION;
122
123 if (!TxLoadLib::getInstance()->getfxtCompressTexFuncExt())
124 _options &= ~FXT1_COMPRESSION;
125
126 switch (options & COMPRESSION_MASK) {
127 case FXT1_COMPRESSION:
128 case S3TC_COMPRESSION:
129 break;
130 case NCC_COMPRESSION:
131 default:
132 _options &= ~COMPRESSION_MASK;
133 }
134
135 if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight)) {
136 if (!_tex1)
137 _tex1 = TxMemBuf::getInstance()->get(0);
138
139 if (!_tex2)
140 _tex2 = TxMemBuf::getInstance()->get(1);
141 }
142
143#if !_16BPP_HACK
144 /* initialize hq4x filter */
145 hq4x_init();
146#endif
147
148 /* initialize texture cache in bytes. 128Mb will do nicely in most cases */
149 _txTexCache = new TxTexCache(_options, _cacheSize, _datapath.c_str(), _cachepath.c_str(), _ident.c_str(), callback);
150
151 /* hires texture */
152#if HIRES_TEXTURE
153 _txHiResCache = new TxHiResCache(_maxwidth, _maxheight, _maxbpp, _options, _datapath.c_str(), _cachepath.c_str(), _ident.c_str(), callback);
154
155 if (_txHiResCache->empty())
156 _options &= ~HIRESTEXTURES_MASK;
157#endif
158
159 if (!(_options & COMPRESS_TEX))
160 _options &= ~COMPRESSION_MASK;
161
162 if (_tex1 && _tex2)
163 _initialized = 1;
164}
165
166boolean
167TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint64 g64crc, GHQTexInfo *info)
168{
169 uint8 *texture = src;
170 uint8 *tmptex = _tex1;
171 uint16 destformat = srcformat;
172
173 /* We need to be initialized first! */
174 if (!_initialized) return 0;
175
176 /* find cached textures */
177 if (_cacheSize) {
178
179 /* calculate checksum of source texture */
180 if (!g64crc)
181 g64crc = (uint64)(_txUtil->checksumTx(texture, srcwidth, srcheight, srcformat));
182
183 DBG_INFO(80, L"filter: crc:%08X %08X %d x %d gfmt:%x\n",
184 (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff), srcwidth, srcheight, srcformat);
185
186#if 0 /* use hirestex to retrieve cached textures. */
187 /* check if we have it in cache */
188 if (!(g64crc & 0xffffffff00000000) && /* we reach here only when there is no hires texture for this crc */
189 _txTexCache->get(g64crc, info)) {
190 DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
191 return 1; /* yep, we've got it */
192 }
193#endif
194 }
195
196 /* Leave small textures alone because filtering makes little difference.
197 * Moreover, some filters require at least 4 * 4 to work.
198 * Bypass _options to do ARGB8888->16bpp if _maxbpp=16 or forced color reduction.
199 */
200 if ((srcwidth >= 4 && srcheight >= 4) &&
201 ((_options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESSION_MASK)) ||
202 (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) {
203
204#if !_16BPP_HACK
205 /* convert textures to a format that the compressor accepts (ARGB8888) */
206 if (_options & COMPRESSION_MASK) {
207#endif
208 if (srcformat != GR_TEXFMT_ARGB_8888) {
209 if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, GR_TEXFMT_ARGB_8888)) {
210 DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
211 return 0;
212 }
213 texture = tmptex;
214 destformat = GR_TEXFMT_ARGB_8888;
215 }
216#if !_16BPP_HACK
217 }
218#endif
219
220 switch (destformat) {
221 case GR_TEXFMT_ARGB_8888:
222
223 /*
224 * prepare texture enhancements (x2, x4 scalers)
225 */
226 int scale_shift = 0, num_filters = 0;
227 uint32 filter = 0;
228
229 if ((_options & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) {
230 if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
231 filter |= HQ4X_ENHANCEMENT;
232 scale_shift = 2;
233 num_filters++;
234 } else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
235 filter |= HQ2X_ENHANCEMENT;
236 scale_shift = 1;
237 num_filters++;
238 }
239 } else if (_options & ENHANCEMENT_MASK) {
240 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
241 filter |= (_options & ENHANCEMENT_MASK);
242 scale_shift = 1;
243 num_filters++;
244 }
245 }
246
247 /*
248 * prepare texture filters
249 */
250 if (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
251 filter |= (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK));
252 num_filters++;
253 }
254
255 /*
256 * execute texture enhancements and filters
257 */
258 while (num_filters > 0) {
259
260 tmptex = (texture == _tex1) ? _tex2 : _tex1;
261
262 uint8 *_texture = texture;
263 uint8 *_tmptex = tmptex;
264
265#if !defined(NO_FILTER_THREAD)
266 unsigned int numcore = _numcore;
267 unsigned int blkrow = 0;
268 while (numcore > 1 && blkrow == 0) {
269 blkrow = (srcheight >> 2) / numcore;
270 numcore--;
271 }
272 if (blkrow > 0 && numcore > 1) {
273 std::thread *thrd[MAX_NUMCORE];
274 unsigned int i;
275 int blkheight = blkrow << 2;
276 unsigned int srcStride = (srcwidth * blkheight) << 2;
277 unsigned int destStride = srcStride << scale_shift << scale_shift;
278 for (i = 0; i < numcore - 1; i++) {
279 thrd[i] = new std::thread(std::bind(filter_8888,
280 (uint32*)_texture,
281 srcwidth,
282 blkheight,
283 (uint32*)_tmptex,
284 filter));
285 _texture += srcStride;
286 _tmptex += destStride;
287 }
288 thrd[i] = new std::thread(std::bind(filter_8888,
289 (uint32*)_texture,
290 srcwidth,
291 srcheight - blkheight * i,
292 (uint32*)_tmptex,
293 filter));
294 for (i = 0; i < numcore; i++) {
295 thrd[i]->join();
296 delete thrd[i];
297 }
298 } else {
299 filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter);
300 }
301#else
302 filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter);
303#endif
304
305 if (filter & ENHANCEMENT_MASK) {
306 srcwidth <<= scale_shift;
307 srcheight <<= scale_shift;
308 filter &= ~ENHANCEMENT_MASK;
309 scale_shift = 0;
310 }
311
312 texture = tmptex;
313 num_filters--;
314 }
315
316 /*
317 * texture compression
318 */
319 /* ignored if we only have texture compression option on.
320 * only done when texture enhancer is used. see constructor. */
321 if ((_options & COMPRESSION_MASK) &&
322 (srcwidth >= 64 && srcheight >= 64) /* Texture compression is not suitable for low pixel coarse detail
323 * textures. The assumption here is that textures larger than 64x64
324 * have enough detail to produce decent quality when compressed. The
325 * down side is that narrow stripped textures that the N64 often use
326 * for large background textures are also ignored. It would be more
327 * reasonable if decisions are made based on fourier-transform
328 * spectrum or RMS error.
329 */
330 ) {
331 int compressionType = _options & COMPRESSION_MASK;
332 int tmpwidth, tmpheight;
333 uint16 tmpformat;
334 /* XXX: textures that use 8bit alpha channel look bad with the current
335 * fxt1 library, so we substitute it with dxtn for now. afaik all gfx
336 * cards that support fxt1 also support dxtn. (3dfx and Intel) */
337 if ((destformat == GR_TEXFMT_ALPHA_INTENSITY_88) ||
338 (destformat == GR_TEXFMT_ARGB_8888) ||
339 (destformat == GR_TEXFMT_ALPHA_8)) {
340 compressionType = S3TC_COMPRESSION;
341 }
342 tmptex = (texture == _tex1) ? _tex2 : _tex1;
343 if (_txQuantize->compress(texture, tmptex,
344 srcwidth, srcheight, srcformat,
345 &tmpwidth, &tmpheight, &tmpformat,
346 compressionType)) {
347 srcwidth = tmpwidth;
348 srcheight = tmpheight;
349 destformat = tmpformat;
350 texture = tmptex;
351 }
352 }
353
354
355 /*
356 * texture (re)conversions
357 */
358 if (destformat == GR_TEXFMT_ARGB_8888) {
359 if (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) srcformat = GR_TEXFMT_ARGB_4444;
360 if (srcformat != GR_TEXFMT_ARGB_8888) {
361 tmptex = (texture == _tex1) ? _tex2 : _tex1;
362 if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, GR_TEXFMT_ARGB_8888, srcformat)) {
363 DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
364 return 0;
365 }
366 texture = tmptex;
367 destformat = srcformat;
368 }
369 }
370
371 break;
372#if !_16BPP_HACK
373 case GR_TEXFMT_ARGB_4444:
374
375 int scale_shift = 0;
376 tmptex = (texture == _tex1) ? _tex2 : _tex1;
377
378 switch (_options & ENHANCEMENT_MASK) {
379 case HQ4X_ENHANCEMENT:
380 if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
381 hq4x_4444((uint8*)texture, (uint8*)tmptex, srcwidth, srcheight, srcwidth, srcwidth * 4 * 2);
382 scale_shift = 2;
383 }/* else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
384 hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
385 scale_shift = 1;
386 }*/
387 break;
388 case HQ2X_ENHANCEMENT:
389 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
390 hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
391 scale_shift = 1;
392 }
393 break;
394 case HQ2XS_ENHANCEMENT:
395 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
396 hq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
397 scale_shift = 1;
398 }
399 break;
400 case LQ2X_ENHANCEMENT:
401 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
402 lq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
403 scale_shift = 1;
404 }
405 break;
406 case LQ2XS_ENHANCEMENT:
407 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
408 lq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
409 scale_shift = 1;
410 }
411 break;
412 case X2SAI_ENHANCEMENT:
413 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
414 Super2xSaI_4444((uint16*)texture, (uint16*)tmptex, srcwidth, srcheight, srcwidth);
415 scale_shift = 1;
416 }
417 break;
418 case X2_ENHANCEMENT:
419 if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
420 Texture2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
421 scale_shift = 1;
422 }
423 }
424 if (scale_shift) {
425 srcwidth <<= scale_shift;
426 srcheight <<= scale_shift;
427 texture = tmptex;
428 }
429
430 if (_options & SMOOTH_FILTER_MASK) {
431 tmptex = (texture == _tex1) ? _tex2 : _tex1;
432 SmoothFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SMOOTH_FILTER_MASK));
433 texture = tmptex;
434 } else if (_options & SHARP_FILTER_MASK) {
435 tmptex = (texture == _tex1) ? _tex2 : _tex1;
436 SharpFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SHARP_FILTER_MASK));
437 texture = tmptex;
438 }
439
440 break;
441 case GR_TEXFMT_ARGB_1555:
442 break;
443 case GR_TEXFMT_RGB_565:
444 break;
445 case GR_TEXFMT_ALPHA_8:
446 break;
447#endif /* _16BPP_HACK */
448 }
449 }
450
451 /* fill in the texture info. */
452 info->data = texture;
453 info->width = srcwidth;
454 info->height = srcheight;
455 info->format = destformat;
456 info->smallLodLog2 = _txUtil->grLodLog2(srcwidth, srcheight);
457 info->largeLodLog2 = info->smallLodLog2;
458 info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(srcwidth, srcheight);
459 info->is_hires_tex = 0;
460
461 /* cache the texture. */
462 if (_cacheSize) _txTexCache->add(g64crc, info);
463
464 DBG_INFO(80, L"filtered texture: %d x %d gfmt:%x\n", info->width, info->height, info->format);
465
466 return 1;
467}
468
469boolean
470TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
471{
472 /* NOTE: Rice CRC32 sometimes return the same value for different textures.
473 * As a workaround, Glide64 CRC32 is used for the key for NON-hires
474 * texture cache.
475 *
476 * r_crc64 = hi:palette low:texture
477 * (separate crc. doesn't necessary have to be rice crc)
478 * g64crc = texture + palette glide64 crc32
479 * (can be any other crc if robust)
480 */
481
482 DBG_INFO(80, L"hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n",
483 (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff),
484 (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff));
485
486#if HIRES_TEXTURE
487 /* check if we have it in hires memory cache. */
488 if ((_options & HIRESTEXTURES_MASK) && r_crc64) {
489 if (_txHiResCache->get(r_crc64, info)) {
490 DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
491
492 /* TODO: Enable emulation for special N64 combiner modes. There are few ways
493 * to get this done. Also applies for CI textures below.
494 *
495 * Solution 1. Load the hiresolution textures in ARGB8888 (or A8, IA88) format
496 * to cache. When a cache is hit, then we take the modes passed in from Glide64
497 * (also TODO) and apply the modification. Then we do color reduction or format
498 * conversion or compression if desired and stuff it into the non-hires texture
499 * cache.
500 *
501 * Solution 2. When a cache is hit and if the combiner modes are present,
502 * convert the texture to ARGB4444 and pass it back to Glide64 to process.
503 * If a texture is compressed, it needs to be decompressed first. Then add
504 * the processed texture to the non-hires texture cache.
505 *
506 * Solution 3. Hybrid of the above 2. Load the textures in ARGB8888 (A8, IA88)
507 * format. Convert the texture to ARGB4444 and pass it back to Glide64 when
508 * the combiner modes are present. Get the processed texture back from Glide64
509 * and compress if desired and add it to the non-hires texture cache.
510 *
511 * Solution 4. Take the easy way out and forget about this whole thing.
512 */
513
514 return 1; /* yep, got it */
515 }
516 if (_txHiResCache->get((r_crc64 & 0xffffffff), info)) {
517 DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
518
519 /* for true CI textures, we use the passed in palette to convert to
520 * ARGB1555 and add it to memory cache.
521 *
522 * NOTE: we do this AFTER all other texture cache searches because
523 * only a few texture packs actually use true CI textures.
524 *
525 * NOTE: the pre-converted palette from Glide64 is in RGBA5551 format.
526 * A comp comes before RGB comp.
527 */
528 if (palette && info->format == GR_TEXFMT_P_8) {
529 DBG_INFO(80, L"found GR_TEXFMT_P_8 format. Need conversion!!\n");
530
531 int width = info->width;
532 int height = info->height;
533 uint16 format = info->format;
534 /* XXX: avoid collision with zlib compression buffer in TxHiResTexture::get */
535 uint8 *texture = info->data;
536 uint8 *tmptex = (texture == _tex1) ? _tex2 : _tex1;
537
538 /* use palette and convert to 16bit format */
539 _txQuantize->P8_16BPP((uint32*)texture, (uint32*)tmptex, info->width, info->height, (uint32*)palette);
540 texture = tmptex;
541 format = GR_TEXFMT_ARGB_1555;
542
543#if 1
544 /* XXX: compressed if memory cache compression is ON */
545 if (_options & COMPRESSION_MASK) {
546 tmptex = (texture == _tex1) ? _tex2 : _tex1;
547 if (_txQuantize->quantize(texture, tmptex, info->width, info->height, format, GR_TEXFMT_ARGB_8888)) {
548 texture = tmptex;
549 format = GR_TEXFMT_ARGB_8888;
550 }
551 if (format == GR_TEXFMT_ARGB_8888) {
552 tmptex = (texture == _tex1) ? _tex2 : _tex1;
553 if (_txQuantize->compress(texture, tmptex,
554 info->width, info->height, GR_TEXFMT_ARGB_1555,
555 &width, &height, &format,
556 _options & COMPRESSION_MASK)) {
557 texture = tmptex;
558 } else {
559 /*if (!_txQuantize->quantize(texture, tmptex, info->width, info->height, GR_TEXFMT_ARGB_8888, GR_TEXFMT_ARGB_1555)) {
560 DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", format);
561 return 0;
562 }*/
563 texture = tmptex;
564 format = GR_TEXFMT_ARGB_1555;
565 }
566 }
567 }
568#endif
569
570 /* fill in the required info to return */
571 info->data = texture;
572 info->width = width;
573 info->height = height;
574 info->format = format;
575 info->smallLodLog2 = _txUtil->grLodLog2(width, height);
576 info->largeLodLog2 = info->smallLodLog2;
577 info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height);
578 info->is_hires_tex = 1;
579
580 /* XXX: add to hires texture cache!!! */
581 _txHiResCache->add(r_crc64, info);
582
583 DBG_INFO(80, L"GR_TEXFMT_P_8 loaded as gfmt:%x!\n", format);
584 }
585
586 return 1;
587 }
588 }
589#endif
590
591 /* check if we have it in memory cache */
592 if (_cacheSize && g64crc) {
593 if (_txTexCache->get(g64crc, info)) {
594 DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
595 return 1; /* yep, we've got it */
596 }
597 }
598
599 DBG_INFO(80, L"no cache hits.\n");
600
601 return 0;
602}
603
604uint64
605TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
606{
607 if (_options & (HIRESTEXTURES_MASK|DUMP_TEX))
608 return _txUtil->checksum64(src, width, height, size, rowStride, palette);
609
610 return 0;
611}
612
613boolean
614TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
615{
616 if (!_initialized)
617 return 0;
618
619 if (!(_options & DUMP_TEX))
620 return 0;
621
622#ifdef DUMP_CACHE
623 DBG_INFO(80, L"gfmt = %02x n64fmt = %02x\n", gfmt, n64fmt);
624 DBG_INFO(80, L"hirestex: r_crc64:%08X %08X\n",
625 (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff));
626
627 if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, (gfmt & 0x00ff), GR_TEXFMT_ARGB_8888))
628 return 0;
629
630 src = _tex1;
631
632 if (!_datapath.empty() && !_ident.empty()) {
633 /* dump it to disk */
634 FILE *fp = NULL;
635 std::wstring tmpbuf;
636 wchar_t texid[36];
637
638 /* create directories */
639 tmpbuf.assign(_datapath + L"/texture_dump");
640 if (!boost::filesystem::exists(tmpbuf) &&
641 !boost::filesystem::create_directory(tmpbuf))
642 return 0;
643
644 tmpbuf.append(L"/" + _ident);
645 if (!boost::filesystem::exists(tmpbuf) &&
646 !boost::filesystem::create_directory(tmpbuf))
647 return 0;
648
649 tmpbuf.append(L"/GlideHQ");
650 if (!boost::filesystem::exists(tmpbuf) &&
651 !boost::filesystem::create_directory(tmpbuf))
652 return 0;
653
654 if ((n64fmt >> 8) == 0x2) {
655 swprintf(texid, 36, L"%08X#%01X#%01X#%08X", (uint32)(r_crc64 & 0xffffffff), (uint32)(n64fmt >> 8), (uint32)(n64fmt & 0xf), (uint32)(r_crc64 >> 32));
656 tmpbuf.append(L"/" + _ident + L"#" + texid + L"_ciByRGBA.png");
657 } else {
658 swprintf(texid, 36, L"%08X#%01X#%01X", (uint32)(r_crc64 & 0xffffffff), (uint32)(n64fmt >> 8), (uint32)(n64fmt & 0xf));
659 tmpbuf.append(L"/" + _ident + L"#" + texid + L"_all.png");
660 }
661
662#ifdef WIN32
663 if ((fp = _wfopen(tmpbuf.c_str(), L"wb")) != NULL) {
664#else
665 char cbuf[MAX_PATH];
666 wcstombs(cbuf, tmpbuf.c_str(), MAX_PATH);
667 if ((fp = fopen(cbuf, "wb")) != NULL) {
668#endif
669 _txImage->writePNG(src, fp, width, height, (rowStridePixel << 2), 0x0003, 0);
670 fclose(fp);
671 return 1;
672 }
673 }
674#endif
675
676 return 0;
677}
678
679boolean
680TxFilter::reloadhirestex()
681{
682 DBG_INFO(80, L"Reload hires textures from texture pack.\n");
683
684 if (_txHiResCache->load(0)) {
685 if (_txHiResCache->empty()) _options &= ~HIRESTEXTURES_MASK;
686 else _options |= HIRESTEXTURES_MASK;
687
688 return 1;
689 }
690
691 return 0;
692}