Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-z64/src/rgl_tiles.cpp
2 views
1
/*
2
* z64
3
*
4
* Copyright (C) 2007 ziggy
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License along
17
* with this program; if not, write to the Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
**/
21
22
#include "rdp.h"
23
#include "rgl.h"
24
25
#include <SDL.h>
26
27
rglTextureHead_t freeTextures;
28
rglTextureHead_t texturesByCrc[256];
29
rglTextureHead_t texturesByUsage;
30
31
void rglTouchTMEM()
32
{
33
rglTexCacheCounter++;
34
if (!rglTexCacheCounter) {
35
// shouldn't happen too often but let's do things correctly for the hell of it ;)
36
rglResetTextureCache();
37
}
38
}
39
40
inline int crc8(uint32_t crc)
41
{
42
uint8_t res;
43
res = crc^(crc>>8)^(crc>>16)^(crc>>24);
44
return res;
45
}
46
47
void rglDeleteTexture(rglTexture_t * tex)
48
{
49
//LOG("deleting texture %x\n", tex);
50
glDeleteTextures(1, &tex->id);
51
if (tex->zid)
52
glDeleteTextures(1, &tex->zid);
53
rglAssert(glGetError() == GL_NO_ERROR);
54
tex->id = tex->zid = 0;
55
CIRCLEQ_REMOVE(&texturesByUsage, tex, byUsage);
56
CIRCLEQ_REMOVE(&texturesByCrc[crc8(tex->crc)], tex, byCrc);
57
CIRCLEQ_INSERT_TAIL(rglTexture_t, &freeTextures, tex, byUsage);
58
}
59
60
rglTexture_t * rglNewTexture(uint32_t crc)
61
{
62
rglTexture_t * res;
63
64
if (CIRCLEQ_EMPTY(&freeTextures))
65
rglDeleteTexture(CIRCLEQ_FIRST(&texturesByUsage));
66
67
res = CIRCLEQ_FIRST(&freeTextures);
68
//LOG("new texture %x %x crc %x\n", res, crc, crc8(crc));
69
CIRCLEQ_REMOVE(&freeTextures, res, byUsage);
70
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByUsage, res, byUsage);
71
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByCrc[crc8(crc)], res, byCrc);
72
73
res->wt = res->ws = res->filter = 0;
74
75
return res;
76
}
77
78
void rglInitTextureCache()
79
{
80
int i;
81
// initialize textures lists
82
CIRCLEQ_INIT(rglTexture_t, &freeTextures);
83
CIRCLEQ_INIT(rglTexture_t, &texturesByUsage);
84
for (i=0; i<256; i++)
85
CIRCLEQ_INIT(rglTexture_t, &texturesByCrc[i]);
86
for (i=0; i<RGL_TEX_CACHE_SIZE; i++) {
87
CIRCLEQ_INSERT_TAIL(rglTexture_t, &freeTextures, rglTextures+i, byUsage);
88
}
89
}
90
91
void rglResetTextureCache()
92
{
93
static int init;
94
if (!init) {
95
rglInitTextureCache();
96
init = 1;
97
}
98
99
memset(rglTexCache, 0, sizeof(rglTexCache));
100
rglTexCacheCounter = 1;
101
while (!CIRCLEQ_EMPTY(&texturesByUsage))
102
rglDeleteTexture(CIRCLEQ_FIRST(&texturesByUsage));
103
104
rglInitTextureCache();
105
}
106
107
void rglTile(rdpTile_t & tile, rglTile_t & rtile, int recth)
108
{
109
rglTexture_t * tex;
110
int ws, wt;
111
int line = tile.line;
112
//int cs, ct;
113
int clipw = ((tile.sh - tile.sl) >>2)+1;
114
int cliph = ((tile.th - tile.tl) >>2)+1;
115
int indirect = 1;
116
uint8_t * from = rdpTmem;
117
int ow, oh;
118
119
// if (recth && cliph == recth+1) // hack for Mario Party (not necessary if we handle filter for texrect)
120
// cliph = recth;
121
122
// if (tile.ms && tile.mask_s && (2<<tile.mask_s)<clipw)
123
// tile.ms = 0;
124
// if (tile.mt && tile.mask_t && (2<<tile.mask_t)<cliph)
125
// tile.mt = 0;
126
// if (tile.ms) clipw /= 2;
127
// if (tile.mt) cliph /= 2;
128
129
if (!line) line = 1;
130
131
//tile.format = ti_format;
132
133
if (tile.size == 3) line <<= 1; // why why WHY ?
134
//if (tile.size == 0) clipw *= 2;
135
tile.w = line << 1 >> tile.size;
136
//if (tile.mask_s && (1<<tile.mask_s) < tile.w*2) // HACK
137
if (tile.mask_s && (1<<tile.mask_s) < tile.w)
138
tile.w = 1<<tile.mask_s;
139
if (tile.cs && ((clipw+3)&~3) < tile.w) // GL wants width divisible by 4 at least ?
140
tile.w = ((clipw+3)&~3);
141
142
tile.h = ((tile.th - tile.tl) >>2)+1; // FIXME why not cliph ???
143
//tile.h = (tile.th >>2)+1;
144
// if (tile.h <= 0)
145
// tile.h = (tile.th >>2)+1;
146
// FIXME remove test on mt ?
147
if (tile.mask_t && ((1<<tile.mask_t) < tile.h || (!tile.ct && !tile.mt)))
148
tile.h = 1<<tile.mask_t;
149
else
150
{
151
// if (tile.h < 0 || (tile.h & 3)) {
152
// tile.h = 1; while (tile.h<(tile.th>>2)) tile.h <<= 1;
153
// }
154
}
155
156
// if (!tile.mask_t && !tile.ct/* && !tile.mt*/)
157
// tile.h = (0x1000-tile.tmem)/line;
158
159
// if (tile.sl && !tile.mask_s) {
160
// printf("shifting sl %d\n", tile.sl);
161
// tile.tmem += tile.sl << tile.format >> 1;
162
// tile.tmem &= 0xfff;
163
// tile.sl = 0;
164
// }
165
// if (tile.tl && !tile.mask_t) {
166
// printf("shifting tl %d\n", tile.tl);
167
// tile.tmem += tile.tl * line;
168
// tile.tmem &= 0xfff;
169
// tile.tl = 0;
170
// }
171
172
if (recth && tile.h == 1)
173
// +1 for yoshi
174
tile.h = recth+1;
175
176
if (/*tile.h == 1 || */tile.w*tile.h << tile.size >> 1 > 0x1000-tile.tmem) {
177
DUMP("fixing tile size from %dx%d to ", tile.w, tile.h);
178
//tile.w = (line << 3) >> tile.size + 2;
179
//tile.h = 1; while (tile.h<(tile.th>>2)) tile.h <<= 1;
180
tile.h = (0x1000-tile.tmem)/line;
181
DUMP("%dx%d\n", tile.w, tile.h);
182
}
183
184
// this is a warkaround for a bug in pj64 rsp plugin
185
// now fixed
186
if (0&&recth && /*tile.line == 8 && */tile.h == 1) {
187
//LOG("direct\n");
188
tile.w = rdpTiWidth << rdpTiSize >> tile.size;
189
tile.h = recth;
190
from = gfx.RDRAM + rdpTiAddress;
191
if (recth > 1 || rdpTiWidth > 1)
192
line = rdpTiWidth << rdpTiSize >> 1;
193
indirect = 0;
194
}
195
196
{
197
int fromLine, stop, fromFormat, fromSize;
198
uint32_t address = rdpGetTmemOrigin(tile.tmem, &fromLine, &stop, &fromFormat, &fromSize);
199
DUMP("tmem %x rdram %x\n", tile.tmem, address);
200
if (address != (uint32_t)~0) {
201
rglRenderBuffer_t * buffer;
202
if (!fromLine) fromLine = line;
203
if (!tile.mask_t)
204
tile.h = (stop-tile.tmem)/line;
205
rtile.hiresBuffer = 0;
206
//while (0) {
207
CIRCLEQ_FOREACH(rglRenderBuffer_t, buffer, &rBufferHead, link) {
208
//if (buffer->flags & RGL_RB_DEPTH) continue;
209
if (buffer->area.xh != 8192)
210
buffer->addressStop = buffer->addressStart + buffer->line * ((buffer->area.yl >>2)+1);
211
212
// conservative
213
// if (address + tile.h * line > buffer->addressStart &&
214
// address < buffer->addressStop)
215
if (address >= buffer->addressStart/* + buffer->line * ((buffer->area.yh >>2)+1)*/ && // oops cannot use yh, might not be initialized
216
address + tile.h * line <= buffer->addressStop)
217
DUMP("check %x --> %x with %x --> %x (%x %x %d %x)\n",
218
address, address + tile.h * line,
219
buffer->addressStart, buffer->addressStop,
220
fromLine, buffer->line, tile.h, line);
221
222
// TODO store real address stop, it's not necessarily the same as
223
// address + tile.h * line
224
// conservative
225
// if (address + tile.h * line > buffer->addressStart &&
226
// address < buffer->addressStop &&
227
// more strict (better for LEGO racer)
228
// general solution would be : find all candidates, pick the one that covers
229
// the biggest area
230
if ((!rtile.hiresBuffer || buffer->addressStart > rtile.hiresBuffer->addressStart) &&
231
address >= buffer->addressStart/* + buffer->line * ((buffer->area.yh >>2)+1)*/ && // oops cannot use yh, might not be initialized
232
address + tile.h * line <= buffer->addressStop &&
233
(tile.h <= 1 || fromLine == buffer->line)) {
234
DUMP("texture buffer at %x %d x %d %d %d fmt %d fromfmt %d\n",
235
buffer->addressStart, tile.w, tile.h,
236
fromLine, buffer->line, tile.format, fromFormat);
237
238
rtile.hiresBuffer = buffer;
239
rtile.hiresAddress = address;
240
241
break;
242
}
243
}
244
245
if (rtile.hiresBuffer) {
246
// FIXME current buffer could be a depth buffer, in this case
247
// we want the texture rendered as depth too
248
rtile.hiresBuffer->flags &= ~RGL_RB_DEPTH;
249
//rglRenderChunks(rtile.hiresBuffer);
250
}
251
252
if (rglSettings.hiresFb && rtile.hiresBuffer) {
253
memcpy(&rtile, &tile, sizeof(tile));
254
return;
255
}
256
257
if (rtile.hiresBuffer) {
258
LOG("updating rdram %x\n", address);
259
rglFramebuffer2Rdram(*rtile.hiresBuffer, address, address + tile.h * line);
260
line = fromLine;
261
from = gfx.RDRAM + address;
262
indirect = 0;
263
}
264
265
}
266
}
267
rtile.hiresBuffer = 0;
268
269
if (tile.w > 1024) tile.w = 1024;
270
if (tile.h > 1024) tile.h = 1024;
271
272
ow = tile.w; oh = tile.h; // save w/h before making it a power of 2
273
{
274
int w=1, h=1;
275
while (w < tile.w) w*=2;
276
while (h < tile.h) h*=2;
277
tile.w = rtile.w = w;
278
tile.h = rtile.h = h;
279
}
280
281
memcpy(&rtile, &tile, sizeof(tile));
282
rtile.line = line;
283
284
// NOTE more general solutions would involve subdividing the geometry
285
// or writing clamping/mirroring in glsl
286
int badmirror_s =
287
tile.mask_s && tile.cs && tile.ms && (clipw/2) < (1<<tile.mask_s);
288
int badmirror_t =
289
tile.mask_t && tile.ct && tile.mt && (cliph/2) < (1<<tile.mask_t);
290
int clipmw = clipw, clipmh = cliph;
291
if (tile.ms && !badmirror_s) clipmw /= 2;
292
if (tile.mt && !badmirror_t) clipmh /= 2;
293
int badclamp_s =
294
tile.mask_s && tile.cs && clipmw > (1<<tile.mask_s);
295
int badclamp_t =
296
tile.mask_t && tile.ct && clipmh > (1<<tile.mask_t);
297
298
int npot_s = (tile.w-1)&tile.w;
299
int npot_t = (tile.h-1)&tile.h;
300
301
ws = GL_REPEAT;
302
//ws = GL_CLAMP_TO_EDGE;
303
if ((!tile.mask_s || tile.cs) && !badclamp_s) {
304
// tile.tmem += (tile.sl>>2) << tile.size >> 1;
305
// tile.sh -= tile.sl;
306
// tile.sl = 0;
307
ws = GL_CLAMP_TO_EDGE;
308
}
309
if (tile.ms && !badmirror_s)
310
ws = ((!tile.mask_s || tile.cs) && !badclamp_s)?
311
GL_MIRROR_CLAMP_TO_EDGE_EXT : GL_MIRRORED_REPEAT;
312
313
wt = GL_REPEAT;
314
//wt = GL_CLAMP_TO_EDGE;
315
if ((!tile.mask_t || tile.ct) && !badclamp_t) {
316
// tile.tmem += (tile.tl>>2) * line;
317
// tile.th -= tile.tl;
318
// tile.tl = 0;
319
wt = GL_CLAMP_TO_EDGE;
320
}
321
if (tile.mt && !badmirror_t)
322
wt = ((!tile.mask_t || tile.ct) && !badclamp_t)?
323
GL_MIRROR_CLAMP_TO_EDGE_EXT : GL_MIRRORED_REPEAT;
324
325
#if 1
326
if ((npot_s||npot_t) && ws != GL_CLAMP_TO_EDGE) {
327
//LOG("Fixup npot clamp s\n");
328
ws = GL_CLAMP_TO_EDGE;
329
}
330
if ((npot_t||npot_s) && wt != GL_CLAMP_TO_EDGE) {
331
//LOG("Fixup npot clamp t\n");
332
wt = GL_CLAMP_TO_EDGE;
333
}
334
#else
335
// ws = GL_CLAMP_TO_EDGE;
336
// wt = GL_CLAMP_TO_EDGE;
337
#endif
338
339
rtile.ws = ws;
340
rtile.wt = wt;
341
342
rglAssert(!(tile.tmem & ~ 0xfff));
343
if (rglTexCache[tile.tmem].counter == rglTexCacheCounter &&
344
rglTexCache[tile.tmem].tex->fmt == tile.format &&
345
rglTexCache[tile.tmem].tex->w == tile.w
346
&&
347
rglTexCache[tile.tmem].tex->h == tile.h
348
// rglTexCache[tile.tmem].tex->h > (tile.th>>2)
349
) {
350
tex = rglTexCache[tile.tmem].tex;
351
goto ok;
352
}
353
354
// printf("tile #%d fmt %s sz %d w %d mask %d %dx%d (%d %d)\n", &tile-rdpTiles, rdpImageFormats[tile.format], tile.size, line, tile.mask_s, (tile.sh - tile.sl >>2)+1, (tile.th - tile.tl >>2)+1, tile.sl>>2, tile.tl>>2);
355
356
//rglAssert(tile.w == (tile.sh - tile.sl >>2)+1);
357
358
{
359
int h, i, j, x, y;
360
int palette = 0;
361
uint32_t crc = 0;
362
rglTextureHead_t * list;
363
364
#if 1
365
if (tile.format == RDP_FORMAT_CI ||
366
(tile.size <= 1 && RDP_GETOM_EN_TLUT(rdpState.otherModes))) {
367
// tlut crc
368
h = tile.size? 256:16;
369
if (tile.size == 0) palette = (tile.palette<<4)&0xff;
370
for (i=0; i<h; i++)
371
crc = ((crc>>3)|(crc<<(32-3)))+(rdpTlut[(i+palette)*4]);
372
}
373
374
for (y=0; y<oh; y++) {
375
uint32_t * p = (uint32_t *) &from[(tile.tmem + y*line)/*&0x3fff*/];
376
for (x=0; x<(line>>2); x++)
377
crc = ((crc>>3)|(crc<<(32-3)))+(*p++);
378
}
379
380
list = texturesByCrc + crc8(crc);
381
CIRCLEQ_FOREACH(rglTexture_t, tex, list, byCrc) {
382
//LOG("comparing %x with %x\n", tex->crc, crc);
383
if (tex->crc == crc &&
384
tex->fmt == tile.format &&
385
tex->clipw >= clipw &&
386
tex->cliph >= cliph &&
387
tex->w == tile.w &&
388
tex->h >= tile.h) {
389
CIRCLEQ_REMOVE(&texturesByUsage, tex, byUsage);
390
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByUsage, tex, byUsage);
391
goto ok2;
392
}
393
// if (tex->crc == crc)
394
// LOG("Same CRC %x !\n", crc);
395
}
396
#endif
397
398
tex = rglNewTexture(crc);
399
tex->fmt = tile.format;
400
tex->w = tile.w;
401
tex->h = tile.h;
402
tex->clipw = clipw;
403
tex->cliph = cliph;
404
tex->crc = crc;
405
glGenTextures(1, &tex->id);
406
rglAssert(glGetError() == GL_NO_ERROR);
407
408
409
glBindTexture(GL_TEXTURE_2D, tex->id);
410
rglAssert(glGetError() == GL_NO_ERROR);
411
uint8_t * ptr;
412
GLuint packed = 0;
413
GLuint glfmt = 0, glpixfmt = 0;
414
415
ptr = rglTmpTex2;
416
417
#define XOR_SWAP_BYTE 3
418
#define XOR_SWAP_WORD 2
419
#define XOR_SWAP_DWORD 2
420
// ugly but it works ...
421
if (tile.cs || !tile.mask_s) ow = tile.w;
422
if (tile.ct || !tile.mask_t) oh = tile.h;
423
#define CLAMP \
424
int ci = i; \
425
int cj = j; \
426
if ((tile.cs || !tile.mask_s) && ci >= clipw) ci = clipw-1; \
427
if ((tile.ct || !tile.mask_t) && cj >= cliph) cj = cliph-1; \
428
429
switch (tile.size) {
430
case 3:
431
for (j=0; j<oh; j++)
432
for (i=0; i<ow; i++) {
433
CLAMP;
434
uint32_t *tc = (uint32_t*)from;
435
int taddr = ((tile.tmem/4) + ((cj) * (line/4)) + (ci)) ^ ((cj & indirect) ? XOR_SWAP_DWORD : 0);
436
uint32_t a = tc[taddr/*&0xfff*/];
437
//uint32_t a = *(uint32_t *)&from[j*line + i*4 + tile.tmem ^ ((j&1)<<1) ^ XOR_SWAP_DWORD];
438
*(uint32_t *)&ptr[(tile.h-1-j)*tile.w*4 + (tile.w-1-i)*4] = a;
439
}
440
break;
441
case 2:
442
for (j=0; j<oh; j++)
443
for (i=0; i<ow; i++) {
444
CLAMP;
445
uint16_t *tc = (uint16_t*)from;
446
int taddr = ((tile.tmem/2) + ((cj) * (line/2)) + (ci)) ^ ((cj & indirect) ? XOR_SWAP_WORD : 0);
447
uint16_t a = tc[(taddr ^ WORD_ADDR_XOR)/*&0x1fff*/];
448
// uint16_t a = *(uint16_t *)&from[j*line + i*2 + tile.tmem ^ ((j&1)<<2) ^ XOR_SWAP_WORD];
449
*(uint16_t *)&ptr[(tile.h-1-j)*tile.w*2 + (tile.w-1-i)*2] = a;
450
}
451
break;
452
case 1:
453
for (j=0; j<oh; j++)
454
for (i=0; i<ow; i++) {
455
CLAMP;
456
uint8_t a = *(uint8_t *)&from[((cj*line + ci + tile.tmem) ^ ((cj & indirect)<<2) ^ XOR_SWAP_BYTE)/*&0xfff*/];
457
*(uint8_t *)&ptr[(tile.h-1-j)*tile.w + (tile.w-1-i)] = a;
458
}
459
break;
460
case 0:
461
// FIXME
462
for (j=0; j<tile.h; j++)
463
for (i=0; i<tile.w; i+=2) {
464
CLAMP;
465
uint8_t a = *(uint8_t *)&from[((cj*line + ci/2 + tile.tmem) ^ ((cj & indirect)<<2) ^ XOR_SWAP_BYTE)/*&0x3fff*/];
466
*(uint8_t *)&ptr[(tile.h-1-j)*tile.w/2 + (tile.w/2-1-i/2)] = a; //(a>>4)|(a<<4);
467
}
468
break;
469
}
470
from = ptr;
471
472
i = tile.format;
473
474
// in Tom Clancy, they do this, using I texture with TLUT enabled
475
if (i != RDP_FORMAT_CI && tile.size <= 1 && RDP_GETOM_EN_TLUT(rdpState.otherModes)) {
476
LOG("fixing %s-%d tile to CI\n", rdpImageFormats[i], tile.size);
477
i = RDP_FORMAT_CI;
478
}
479
480
if (tile.size <= 1 && i == RDP_FORMAT_RGBA) {
481
LOG("fixing RGBA tile to I\n");
482
i = RDP_FORMAT_I;
483
}
484
485
switch (i) {
486
case RDP_FORMAT_CI: {
487
if (!RDP_GETOM_TLUT_TYPE(rdpState.otherModes)) {
488
glfmt = GL_RGBA;
489
packed = GL_UNSIGNED_SHORT_5_5_5_1;
490
} else {
491
glfmt = GL_RGBA;
492
glpixfmt = GL_LUMINANCE_ALPHA;
493
//glfmt = GL_LUMINANCE_ALPHA;
494
packed = GL_UNSIGNED_BYTE;
495
}
496
switch (tile.size) {
497
case 0:
498
ptr = rglTmpTex;
499
for (i=0; i<tile.w*tile.h/2; i++) {
500
uint16_t a = rdpTlut[((from[i]&0xf) + palette/* ^ WORD_ADDR_XOR*/)*4];
501
uint16_t b = rdpTlut[((from[i]>>4) + palette/* ^ WORD_ADDR_XOR*/)*4];
502
if (RDP_GETOM_TLUT_TYPE(rdpState.otherModes)) {
503
a = (a>>8)|(a<<8);
504
b = (b>>8)|(b<<8);
505
}
506
*(uint16_t *)&ptr[i*4] = a;
507
*(uint16_t *)&ptr[i*4+2] = b;
508
}
509
break;
510
case 1:
511
ptr = rglTmpTex;
512
//rdpTlut[palette] = 0;
513
for (i=0; i<tile.w*tile.h; i++) {
514
uint16_t a = rdpTlut[(from[i] + palette/* ^ WORD_ADDR_XOR*/)*4];
515
if (RDP_GETOM_TLUT_TYPE(rdpState.otherModes))
516
a = (a>>8)|(a<<8);
517
*(uint16_t *)&ptr[i*2] = a;
518
}
519
break;
520
}
521
break;
522
}
523
case RDP_FORMAT_RGBA: {
524
glfmt = GL_RGBA;
525
switch (tile.size) {
526
case 2:
527
//packed = GL_UNSIGNED_SHORT_4_4_4_4_REV;
528
packed = GL_UNSIGNED_SHORT_5_5_5_1;
529
break;
530
case 3:
531
packed = GL_UNSIGNED_INT_8_8_8_8;
532
break;
533
}
534
break;
535
}
536
case RDP_FORMAT_IA: {
537
glfmt = GL_RGBA;
538
glpixfmt = GL_LUMINANCE_ALPHA;
539
//if (tile.size == 0) line *= 2;
540
switch (tile.size) {
541
case 0: {
542
packed = GL_UNSIGNED_BYTE;
543
ptr = rglTmpTex;
544
for (i=0; i<tile.h*tile.w/2; i++) {
545
uint32_t a = (from[i]&0xe0) >> 5;
546
int8_t b = (from[i]&0x10) >> 4;
547
ptr[i*4+2] = (a<<5) | (a<<2) | (a>>1);
548
ptr[i*4+3] = -b;
549
a = (from[i]&0xe) >> 1;
550
b = (from[i]&0x1);
551
ptr[i*4+0] = (a<<5) | (a<<2) | (a>>1);
552
ptr[i*4+1] = -b;
553
}
554
break;
555
}
556
case 1: {
557
packed = GL_UNSIGNED_BYTE;
558
ptr = rglTmpTex;
559
for (i=0; i<tile.h*tile.w; i++) {
560
uint32_t a = from[i]&0xF0;
561
a = a | (a>>4);
562
ptr[i*2] = a | (a>>4);
563
a = from[i]&0x0F;
564
a = a | (a<<4);
565
ptr[i*2+1] = a;
566
}
567
break;
568
}
569
case 2:
570
packed = GL_UNSIGNED_BYTE;
571
ptr = rglTmpTex;
572
for (i=0; i<tile.h*tile.w*2; i+=2) {
573
ptr[i] = from[i+1];
574
ptr[i+1] = from[i];
575
}
576
break;
577
}
578
break;
579
}
580
case RDP_FORMAT_I: {
581
glfmt = GL_INTENSITY;
582
// if (RDP_GETOM_ALPHA_CVG_SELECT(rdpState.otherModes))
583
// glfmt = GL_LUMINANCE;
584
glpixfmt = GL_LUMINANCE;
585
switch (tile.size) {
586
case 0: {
587
packed = GL_UNSIGNED_BYTE;
588
ptr = rglTmpTex;
589
for (i=0; i<tile.h*tile.w/2; i++) {
590
uint32_t a = from[i]&0xF0;
591
ptr[i*2+1] = a | (a>>4);
592
a = from[i]&0x0F;
593
ptr[i*2] = a | (a<<4);
594
}
595
break;
596
}
597
case 1: {
598
packed = GL_UNSIGNED_BYTE;
599
break;
600
}
601
}
602
break;
603
}
604
}
605
606
if (packed) {
607
DUMP("loading texture %dx%d fmt %s size %x (%x %x %x %p)\n", tile.w, tile.h, rdpImageFormats[tile.format], tile.size, glfmt, glpixfmt, packed, ptr);
608
// printf("cycle type = %d\n", chunk.rdpState.otherModes.cycle_type);
609
if (!glpixfmt)
610
glpixfmt = glfmt;
611
rglAssert(glGetError() == GL_NO_ERROR);
612
glTexImage2D(GL_TEXTURE_2D, 0, glfmt, tile.w, tile.h, 0, glpixfmt, packed,
613
ptr);
614
rglAssert(glGetError() == GL_NO_ERROR);
615
616
617
#if 0
618
if (1||RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY) {
619
uint32_t * pixels = (uint32_t *) malloc(tile.w*tile.h*4);
620
// 0x1902 is another constant meaning GL_DEPTH_COMPONENT
621
// (but isn't defined in gl's headers !!)
622
if (1/*fmt != GL_DEPTH_COMPONENT && fmt != 0x1902*/) {
623
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
624
ilTexImage(tile.w, tile.h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
625
} else {
626
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
627
int i;
628
for (i=0; i<tile.w*tile.h; i++)
629
((unsigned char *)ptr)[i] = ((unsigned short *)pixels)[i]/256;
630
ilTexImage(tile.w, tile.h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, ptr);
631
}
632
char name[128];
633
// sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
634
// system(name);
635
static int num;
636
sprintf(name, "dump/tex%04d-%s-%d-%d-%d.png", num++, rdpImageFormats[tile.format], tile.size, &tile - rdpTiles, tile.tmem);
637
fprintf(stderr, "Writing '%s'\n", name);
638
ilSaveImage(name);
639
640
free(pixels);
641
}
642
#endif
643
}
644
if (!packed) {
645
LOGERROR("unsuported format %s size %d\n", rdpImageFormats[tile.format], tile.size);
646
}
647
648
649
}
650
ok2:
651
rglTexCache[tile.tmem].counter = rglTexCacheCounter;
652
rglTexCache[tile.tmem].tex = tex;
653
654
ok:
655
rtile.tex = tex;
656
657
{
658
GLuint filter;
659
if (recth) {
660
switch (RDP_GETOM_SAMPLE_TYPE(rdpState.otherModes)) {
661
case 0:
662
filter = GL_NEAREST;
663
break;
664
default:
665
filter = GL_LINEAR;
666
break;
667
}
668
} else
669
filter = GL_LINEAR;
670
671
rtile.filter = filter;
672
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
673
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
674
}
675
}
676
677
678