22726e4d |
1 | /****************************************************************************** |
2 | * Arachnoid Graphics Plugin for Mupen64Plus |
3 | * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/ |
4 | * |
5 | * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson |
6 | * |
7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License |
9 | * as published by the Free Software Foundation; either version 2 |
10 | * of the License, or (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | *****************************************************************************/ |
21 | |
22 | #include "TextureCache.h" |
23 | |
24 | #include "RDP.h" |
25 | #include "RSP.h" |
26 | #include "CachedTexture.h" |
27 | #include "MathLib.h" |
28 | #include <algorithm> |
29 | using std::min; |
30 | #include "m64p.h" |
31 | #include "OpenGL.h" |
32 | #include "Memory.h" |
33 | #include "OpenGLRenderer.h" |
34 | #include "MultiTexturingExt.h" |
35 | //gSPBgRect1Cyc |
36 | //gSPBgRectCopy |
37 | #define GL_CLAMP_TO_EDGE 0x812F |
38 | #define GL_GENERATE_MIPMAP 0x8191 |
39 | |
40 | #include "Logger.h" |
41 | #include <iostream> |
42 | |
43 | //----------------------------------------------------------------------------- |
44 | //! Constructor |
45 | //----------------------------------------------------------------------------- |
46 | TextureCache::TextureCache() |
47 | { |
48 | m_currentTextures[0] = 0; |
49 | m_currentTextures[1] = 0; |
50 | } |
51 | |
52 | //----------------------------------------------------------------------------- |
53 | //! Destructor |
54 | //----------------------------------------------------------------------------- |
55 | TextureCache::~TextureCache() |
56 | { |
57 | dispose(); |
58 | } |
59 | |
60 | //----------------------------------------------------------------------------- |
61 | //* Initialize |
62 | //----------------------------------------------------------------------------- |
63 | bool TextureCache::initialize(RSP* rsp, RDP* rdp, Memory* memory, unsigned int textureBitDepth, unsigned int cacheSize) |
64 | { |
65 | m_rsp = rsp; |
66 | m_rdp = rdp; |
67 | m_memory = memory; |
68 | m_bitDepth = textureBitDepth; |
69 | m_maxBytes = cacheSize; |
70 | |
71 | return true; |
72 | } |
73 | |
74 | //----------------------------------------------------------------------------- |
75 | //* Update |
76 | //----------------------------------------------------------------------------- |
77 | void TextureCache::update(unsigned int tile) |
78 | { |
79 | //if (cache.bitDepth != OGL.textureBitDepth) |
80 | //{ |
81 | // TextureCache_Destroy(); |
82 | // TextureCache_Init(); |
83 | //} |
84 | |
85 | //Special textures? |
86 | if ( m_rdp->getTextureMode() == TM_BGIMAGE ) |
87 | { |
88 | return; |
89 | } |
90 | else if ( m_rdp->getTextureMode() == TM_FRAMEBUFFER ) |
91 | { |
92 | return; |
93 | } |
94 | |
95 | |
96 | CachedTexture temp; |
97 | unsigned int maskWidth = 0, maskHeight = 0; |
98 | _calculateTextureSize(tile, &temp, maskWidth, maskHeight); |
99 | |
100 | static int hits = 0; |
101 | static int misses = 0; |
102 | |
103 | //For each texture in texture cache |
104 | for (TextureList::iterator it=m_cachedTextures.begin(); it!=m_cachedTextures.end(); ++it) |
105 | { |
106 | CachedTexture* temp2 = (*it); |
107 | |
108 | if ( *temp2 == temp ) |
109 | { |
110 | _activateTexture( tile, (*it) ); |
111 | hits++; |
112 | return; |
113 | } |
114 | } |
115 | misses++; |
116 | |
117 | // If multitexturing, set the appropriate texture |
118 | //if (OGL.ARB_multitexture) |
119 | glActiveTextureARB( GL_TEXTURE0_ARB + tile ); |
120 | |
121 | //Add new texture to cache |
122 | m_currentTextures[tile] = addTop(); |
123 | m_currentTextures[tile]->activate(); |
124 | |
125 | m_currentTextures[tile]->address = m_rdp->getTextureImage()->address; |
126 | m_currentTextures[tile]->crc = temp.crc; |
127 | m_currentTextures[tile]->width = temp.width; |
128 | m_currentTextures[tile]->height = temp.height; |
129 | m_currentTextures[tile]->clampWidth = temp.clampWidth; |
130 | m_currentTextures[tile]->clampHeight = temp.clampHeight; |
131 | |
132 | m_currentTextures[tile]->format = m_rsp->getTile(tile)->format; |
133 | m_currentTextures[tile]->size = m_rsp->getTile(tile)->size; |
134 | |
135 | m_currentTextures[tile]->palette = m_rsp->getTile(tile)->palette; |
136 | /* m_currentTextures[tile]->fulS = rsp.getTile(tile)->fulS; |
137 | m_currentTextures[tile]->fulT = rsp.getTile(tile)->fulT; |
138 | m_currentTextures[tile]->ulS = rsp.getTile(tile)->ulS; |
139 | m_currentTextures[tile]->ulT = rsp.getTile(tile)->ulT; |
140 | m_currentTextures[tile]->lrS = rsp.getTile(tile)->lrS; |
141 | m_currentTextures[tile]->lrT = rsp.getTile(tile)->lrT;*/ |
142 | m_currentTextures[tile]->maskS = m_rsp->getTile(tile)->masks; |
143 | m_currentTextures[tile]->maskT = m_rsp->getTile(tile)->maskt; |
144 | m_currentTextures[tile]->mirrorS = m_rsp->getTile(tile)->mirrors; |
145 | m_currentTextures[tile]->mirrorT = m_rsp->getTile(tile)->mirrort; |
146 | m_currentTextures[tile]->clampS = m_rsp->getTile(tile)->clamps; |
147 | m_currentTextures[tile]->clampT = m_rsp->getTile(tile)->clampt; |
148 | m_currentTextures[tile]->line = m_rsp->getTile(tile)->line; |
149 | m_currentTextures[tile]->tMem = m_rsp->getTile(tile)->tmem; |
150 | |
151 | |
152 | |
153 | // cache.current[tile]->lastDList = RSP.DList; |
154 | // cache.current[tile]->frameBufferTexture = FALSE; |
155 | |
156 | //Calculate Real Width |
157 | if (m_currentTextures[tile]->clampS) |
158 | { |
159 | m_currentTextures[tile]->realWidth = pow2( temp.clampWidth ); |
160 | } |
161 | else if (m_currentTextures[tile]->mirrorS) |
162 | { |
163 | m_currentTextures[tile]->realWidth = maskWidth << 1; |
164 | } |
165 | else |
166 | { |
167 | m_currentTextures[tile]->realWidth = pow2( temp.width ); |
168 | } |
169 | |
170 | //Calculate Real Height |
171 | if (m_currentTextures[tile]->clampT) |
172 | { |
173 | m_currentTextures[tile]->realHeight = pow2( temp.clampHeight ); |
174 | } |
175 | else if (m_currentTextures[tile]->mirrorT) |
176 | { |
177 | m_currentTextures[tile]->realHeight = maskHeight << 1; |
178 | } |
179 | else |
180 | { |
181 | m_currentTextures[tile]->realHeight = pow2( temp.height ); |
182 | } |
183 | |
184 | //Calculate Scale |
185 | m_currentTextures[tile]->scaleS = 1.0f / (float)(m_currentTextures[tile]->realWidth); |
186 | m_currentTextures[tile]->scaleT = 1.0f / (float)(m_currentTextures[tile]->realHeight); |
187 | m_currentTextures[tile]->shiftScaleS = 1.0f; |
188 | m_currentTextures[tile]->shiftScaleT= 1.0f; |
189 | #if 0 |
190 | //m_currentTextures[tile]->offsetS = OGL.enable2xSaI ? 0.25f : 0.5f; |
191 | //m_currentTextures[tile]->offsetT = OGL.enable2xSaI ? 0.25f : 0.5f; |
192 | #else |
193 | m_currentTextures[tile]->offsetS = 0.5f; |
194 | m_currentTextures[tile]->offsetT = 0.5f; |
195 | #endif |
196 | |
197 | if (m_rsp->getTile(tile)->shifts > 10) |
198 | m_currentTextures[tile]->shiftScaleS = (float)(1 << (16 - m_rsp->getTile(tile)->shifts)); |
199 | else if (m_rsp->getTile(tile)->shifts > 0) |
200 | m_currentTextures[tile]->shiftScaleS /= (float)(1 << m_rsp->getTile(tile)->shifts); |
201 | |
202 | if (m_rsp->getTile(tile)->shiftt > 10) |
203 | m_currentTextures[tile]->shiftScaleT = (float)(1 << (16 - m_rsp->getTile(tile)->shiftt)); |
204 | else if (m_rsp->getTile(tile)->shiftt > 0) |
205 | m_currentTextures[tile]->shiftScaleT /= (float)(1 << m_rsp->getTile(tile)->shiftt); |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | _loadTexture( m_currentTextures[tile] ); |
212 | _activateTexture( tile, m_currentTextures[tile] ); |
213 | |
214 | m_cachedBytes += m_currentTextures[tile]->getTextureSize(); |
215 | |
216 | } |
217 | |
218 | //----------------------------------------------------------------------------- |
219 | //* Add Top |
220 | //! Adds a texture to cache |
221 | //----------------------------------------------------------------------------- |
222 | CachedTexture* TextureCache::addTop() |
223 | { |
224 | //If no memory left, remove old textures from cache |
225 | while ( m_cachedBytes > m_maxBytes ) |
226 | { |
227 | this->removeBottom(); |
228 | } |
229 | |
230 | //Allocate memory |
231 | CachedTexture* newTexture = new CachedTexture(); |
232 | |
233 | //Generate a texture |
234 | glGenTextures(1, &newTexture->m_id); |
235 | |
236 | //Add Texture to cache |
237 | m_cachedTextures.push_front(newTexture); |
238 | |
239 | return newTexture; |
240 | } |
241 | |
242 | //----------------------------------------------------------------------------- |
243 | // Remove Bottom |
244 | //----------------------------------------------------------------------------- |
245 | void TextureCache::removeBottom() |
246 | { |
247 | //Get Last Texture in list |
248 | CachedTexture* lastTexture = *(--m_cachedTextures.end()); |
249 | |
250 | //Remove Texture |
251 | m_cachedTextures.pop_back(); |
252 | m_cachedBytes -= lastTexture->getTextureSize(); |
253 | |
254 | //if (cache.bottom->frameBufferTexture) |
255 | // FrameBuffer_RemoveBuffer( cache.bottom->address ); |
256 | |
257 | //Delete texture |
258 | glDeleteTextures(1, &lastTexture->m_id); |
259 | |
260 | delete lastTexture; |
261 | } |
262 | |
263 | //----------------------------------------------------------------------------- |
264 | // Remove |
265 | //----------------------------------------------------------------------------- |
266 | void TextureCache::remove( CachedTexture *texture ) |
267 | { |
268 | |
269 | } |
270 | |
271 | //----------------------------------------------------------------------------- |
272 | //Move Texture to top |
273 | //----------------------------------------------------------------------------- |
274 | void TextureCache::moveToTop( CachedTexture *newtop ) |
275 | { |
276 | //Get Texture |
277 | TextureList::iterator it = std::find( m_cachedTextures.begin(), m_cachedTextures.end(), newtop); |
278 | |
279 | //Erase Texture |
280 | if ( it != m_cachedTextures.end() ) |
281 | { |
282 | m_cachedTextures.erase(it); |
283 | } |
284 | |
285 | //Add texture to the front of the list |
286 | m_cachedTextures.push_front(newtop); |
287 | } |
288 | |
289 | //----------------------------------------------------------------------------- |
290 | // Dispose |
291 | //----------------------------------------------------------------------------- |
292 | void TextureCache::dispose() |
293 | { |
294 | //For each texture |
295 | for (TextureList::iterator it=m_cachedTextures.begin(); it!=m_cachedTextures.end(); ++it ) |
296 | { |
297 | delete (*it); |
298 | } |
299 | m_cachedTextures.clear(); |
300 | } |
301 | |
302 | //----------------------------------------------------------------------------- |
303 | // Load Texture |
304 | //----------------------------------------------------------------------------- |
305 | void TextureCache::_loadTexture(CachedTexture* texture) |
306 | { |
307 | //Select Image Type |
308 | GetTexelFunc getTexelFunc; |
309 | unsigned int internalFormat; |
310 | int imageType; |
311 | m_formatSelector.detectImageFormat(texture, m_bitDepth, getTexelFunc, internalFormat, imageType, m_rdp->getTextureLUT()); |
312 | |
313 | //Allocate memory |
314 | unsigned int* dest = new unsigned int[ texture->getTextureSize() ]; |
315 | |
316 | //Get Line Size |
317 | unsigned short line = (unsigned short)texture->line; |
318 | if (texture->size == G_IM_SIZ_32b) |
319 | line <<= 1; |
320 | |
321 | // |
322 | //Work Your magic |
323 | // |
324 | |
325 | unsigned short mirrorSBit, maskSMask, clampSClamp; |
326 | unsigned short mirrorTBit, maskTMask, clampTClamp; |
327 | |
328 | if (texture->maskS) |
329 | { |
330 | clampSClamp = (unsigned short)(texture->clampS ? texture->clampWidth - 1 : (texture->mirrorS ? (texture->width << 1) - 1 : texture->width - 1)); |
331 | maskSMask = (1 << texture->maskS) - 1; |
332 | mirrorSBit = texture->mirrorS ? 1 << texture->maskS : 0; |
333 | } |
334 | else |
335 | { |
336 | clampSClamp = (unsigned short)min( texture->clampWidth, texture->width ) - 1; |
337 | maskSMask = 0xFFFF; |
338 | mirrorSBit = 0x0000; |
339 | } |
340 | |
341 | if (texture->maskT) |
342 | { |
343 | clampTClamp = (unsigned short)(texture->clampT ? texture->clampHeight - 1 : (texture->mirrorT ? (texture->height << 1) - 1: texture->height - 1)); |
344 | maskTMask = (1 << texture->maskT) - 1; |
345 | mirrorTBit = texture->mirrorT ? 1 << texture->maskT : 0; |
346 | } |
347 | else |
348 | { |
349 | clampTClamp = (unsigned short)min( texture->clampHeight, texture->height ) - 1; |
350 | maskTMask = 0xFFFF; |
351 | mirrorTBit = 0x0000; |
352 | } |
353 | |
354 | // Hack for Zelda warp texture |
355 | if (((texture->tMem << 3) + (texture->width * texture->height << texture->size >> 1)) > 4096) |
356 | texture->tMem = 0; |
357 | |
358 | // limit clamp values to min-0 (Perfect Dark has height=0 textures, making negative clamps) |
359 | if (clampTClamp & 0x8000) |
360 | clampTClamp = 0; |
361 | if (clampSClamp & 0x8000) |
362 | clampSClamp = 0; |
363 | |
364 | // |
365 | //Retrive texture from source (TMEM) and copy it to dest |
366 | // |
367 | |
368 | unsigned short x, y, i, j, tx, ty; |
369 | |
370 | unsigned long long* src; |
371 | |
372 | j = 0; |
373 | for (y = 0; y < texture->realHeight; y++) |
374 | { |
375 | ty = min(y, clampTClamp) & maskTMask; |
376 | |
377 | if (y & mirrorTBit) { |
378 | ty ^= maskTMask; |
379 | } |
380 | |
381 | //TODO: remove old if new works |
382 | //src = m_memory->getTextureMemory(texture->tMem) + line * ty; |
383 | src = m_memory->getTextureMemory((texture->tMem + line * ty) & 511); |
384 | |
385 | |
386 | i = (ty & 1) << 1; |
387 | for (x = 0; x < texture->realWidth; x++) |
388 | { |
389 | tx = min(x, clampSClamp) & maskSMask; |
390 | |
391 | if (x & mirrorSBit) |
392 | tx ^= maskSMask; |
393 | |
394 | if (internalFormat == GL_RGBA8) |
395 | ((unsigned int*)dest)[j++] = getTexelFunc( src, tx, i, texture->palette ); |
396 | else |
397 | ((unsigned short*)dest)[j++] = getTexelFunc( src, tx, i, texture->palette ); |
398 | } |
399 | } |
400 | |
401 | //Send Texture to OpenGL |
402 | #ifdef HAVE_GLES |
403 | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, texture->realWidth, texture->realHeight, 0, GL_RGBA, imageType, dest ); |
404 | #else |
405 | glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, texture->realWidth, texture->realHeight, 0, GL_RGBA, imageType, dest ); |
406 | #endif |
407 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
408 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
409 | delete[] dest; |
410 | } |
411 | |
412 | |
413 | void TextureCache::_calculateTextureSize(unsigned int tile, CachedTexture* out, unsigned int& maskWidth, unsigned int& maskHeight ) |
414 | { |
415 | RDPTile* rspTile = m_rsp->getTile(tile); |
416 | |
417 | //Calculate Tile Size |
418 | unsigned int tileWidth = rspTile->getWidth(); |
419 | unsigned int tileHeight = rspTile->getHeight(); |
420 | |
421 | //Get Mask Size |
422 | maskWidth = 1 << rspTile->masks; |
423 | maskHeight = 1 << rspTile->maskt; |
424 | |
425 | //Get Current Tile Size |
426 | unsigned int loadWidth = m_rdp->getCurrentTile()->getWidth(); |
427 | unsigned int loadHeight = m_rdp->getCurrentTile()->getHeight(); |
428 | |
429 | unsigned int maxTexels = ImageFormatSelector::imageFormats[rspTile->size][rspTile->format].maxTexels; |
430 | |
431 | //Get Line Width (depending on imageformat) |
432 | unsigned int lineWidth = rspTile->line << ImageFormatSelector::imageFormats[rspTile->size][rspTile->format].lineShift; |
433 | unsigned int lineHeight; |
434 | if ( lineWidth ) // Don't allow division by zero |
435 | lineHeight = min( maxTexels / lineWidth, tileHeight ); |
436 | else |
437 | lineHeight = 0; |
438 | |
439 | unsigned int width; |
440 | unsigned int height; |
441 | |
442 | if ( m_rdp->getTextureMode() == TM_TEXRECT ) |
443 | { |
444 | unsigned short texRectWidth = (unsigned short)(m_rdp->getTexRectWidth() - rspTile->uls); |
445 | unsigned short texRectHeight = (unsigned short)(m_rdp->getTexRectHeight() - rspTile->ult); |
446 | |
447 | if (rspTile->masks && ((maskWidth * maskHeight) <= maxTexels)) |
448 | width = maskWidth; |
449 | else if ((tileWidth * tileHeight) <= maxTexels) |
450 | width = tileWidth; |
451 | else if ((tileWidth * texRectHeight) <= maxTexels) |
452 | width = tileWidth; |
453 | else if ((texRectWidth * tileHeight) <= maxTexels) |
454 | width = m_rdp->getTexRectWidth(); |
455 | else if ((texRectWidth * texRectHeight) <= maxTexels) |
456 | width = m_rdp->getTexRectWidth(); |
457 | else if (m_rdp->getLoadType() == LOADTYPE_TILE) |
458 | width = loadWidth; |
459 | else |
460 | width = lineWidth; |
461 | |
462 | if (rspTile->maskt && ((maskWidth * maskHeight) <= maxTexels)) |
463 | height = maskHeight; |
464 | else if ((tileWidth * tileHeight) <= maxTexels) |
465 | height = tileHeight; |
466 | else if ((tileWidth * texRectHeight) <= maxTexels) |
467 | height = m_rdp->getTexRectHeight(); |
468 | else if ((texRectWidth * tileHeight) <= maxTexels) |
469 | height = tileHeight; |
470 | else if ((texRectWidth * texRectHeight) <= maxTexels) |
471 | height = m_rdp->getTexRectHeight(); |
472 | else if (m_rdp->getLoadType() == LOADTYPE_TILE) |
473 | height = loadHeight; |
474 | else |
475 | height = lineHeight; |
476 | } |
477 | else |
478 | { |
479 | if (rspTile->masks && ((maskWidth * maskHeight) <= maxTexels)) |
480 | width = maskWidth; // Use mask width if set and valid |
481 | else if ((tileWidth * tileHeight) <= maxTexels) |
482 | width = tileWidth; // else use tile width if valid |
483 | else if (m_rdp->getLoadType() == LOADTYPE_TILE) |
484 | width = loadWidth; // else use load width if load done with LoadTile |
485 | else |
486 | width = lineWidth; // else use line-based width |
487 | |
488 | if (rspTile->maskt && ((maskWidth * maskHeight) <= maxTexels)) |
489 | height = maskHeight; |
490 | else if ((tileWidth * tileHeight) <= maxTexels) |
491 | height = tileHeight; |
492 | else if (m_rdp->getLoadType() == LOADTYPE_TILE) |
493 | height = loadHeight; |
494 | else |
495 | height = lineHeight; |
496 | } |
497 | |
498 | unsigned int clampWidth = rspTile->clamps ? tileWidth : width; |
499 | unsigned int clampHeight = rspTile->clampt ? tileHeight : height; |
500 | |
501 | if (clampWidth > 256) |
502 | rspTile->clamps = 0; |
503 | if (clampHeight > 256) |
504 | rspTile->clampt = 0; |
505 | |
506 | // Make sure masking is valid |
507 | if (maskWidth > width) |
508 | { |
509 | rspTile->masks = powof( width ); |
510 | maskWidth = 1 << rspTile->masks; |
511 | } |
512 | |
513 | if (maskHeight > height) |
514 | { |
515 | rspTile->maskt = powof( height ); |
516 | maskHeight = 1 << rspTile->maskt; |
517 | } |
518 | |
519 | //Set output data |
520 | out->width = width; |
521 | out->height = height; |
522 | out->clampWidth = clampWidth; |
523 | out->clampHeight = clampHeight; |
524 | out->maskS = m_rsp->getTile(tile)->masks; |
525 | out->maskT = m_rsp->getTile(tile)->maskt; |
526 | out->mirrorS = m_rsp->getTile(tile)->mirrors; |
527 | out->mirrorT = m_rsp->getTile(tile)->mirrort; |
528 | out->clampS = m_rsp->getTile(tile)->clamps; |
529 | out->clampT = m_rsp->getTile(tile)->clampt; |
530 | out->format = m_rsp->getTile(tile)->format; |
531 | out->size = m_rsp->getTile(tile)->size; |
532 | out->crc = _calculateCRC(tile, width, height ); |
533 | } |
534 | |
535 | unsigned int TextureCache::_calculateCRC(unsigned int t, unsigned int width, unsigned int height) |
536 | { |
537 | RDPTile* tile = m_rsp->getTile(t); |
538 | |
539 | unsigned int crc; |
540 | unsigned int y, bpl, line; |
541 | unsigned long long *src; |
542 | |
543 | //TODO: remove if new works |
544 | //src = m_memory->getTextureMemory(tile->tmem); |
545 | bpl = width << tile->size >> 1; |
546 | |
547 | line = tile->line; |
548 | if (tile->size == G_IM_SIZ_32b) |
549 | line <<= 1; |
550 | |
551 | crc = 0xFFFFFFFF; |
552 | for (y=0; y<height; ++y) |
553 | { |
554 | src = m_memory->getTextureMemory((tile->tmem + (y * line)) & 511); |
555 | crc = m_crcCalculator.calcCRC( crc, src, bpl ); |
556 | //TODO: remove if new works |
557 | //src += line; |
558 | } |
559 | |
560 | if ( tile->format == G_IM_FMT_CI ) |
561 | { |
562 | if ( tile->size == G_IM_SIZ_4b ) |
563 | crc = m_crcCalculator.calcCRC( crc, &m_rdp->m_paletteCRC16[tile->palette], 4 ); |
564 | else if (tile->size == G_IM_SIZ_8b) |
565 | crc = m_crcCalculator.calcCRC( crc, &m_rdp->m_paletteCRC256, 4 ); |
566 | } |
567 | return crc; |
568 | } |
569 | |
570 | void TextureCache::_activateTexture( unsigned int t, CachedTexture *texture ) |
571 | { |
572 | // If multitexturing, set the appropriate texture |
573 | //if (OGL.ARB_multitexture) |
574 | glActiveTextureARB( GL_TEXTURE0_ARB + t ); |
575 | |
576 | // Bind the cached texture |
577 | texture->activate(); |
578 | |
579 | // Set filter mode. Almost always bilinear, but check anyways |
580 | unsigned int textureFiltering = m_rdp->getTextureFiltering(); |
581 | if ( textureFiltering == G_TF_BILERP || textureFiltering == G_TF_AVERAGE ) |
582 | { |
583 | if( m_mipmap > 0 ) |
584 | { |
585 | // Set Mipmap |
586 | if(m_mipmap == 1) // nearest |
587 | { |
588 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); |
589 | } |
590 | else if(m_mipmap == 2) // bilinear |
591 | { |
592 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); |
593 | } |
594 | else if(m_mipmap == 3) // trilinear |
595 | { |
596 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); |
597 | } |
598 | |
599 | // Tell to hardware to generate mipmap (himself) when glTexImage2D is called |
600 | glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); |
601 | } |
602 | else // no mipmapping |
603 | { |
604 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); |
605 | glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE ); |
606 | } |
607 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); |
608 | |
609 | } |
610 | else |
611 | { |
612 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
613 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
614 | } |
615 | |
616 | |
617 | |
618 | // Set clamping modes |
619 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture->clampS ? GL_CLAMP_TO_EDGE : GL_REPEAT ); |
620 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture->clampT ? GL_CLAMP_TO_EDGE : GL_REPEAT ); |
621 | |
622 | //texture->lastDList = RSP.DList; |
623 | |
624 | moveToTop( texture ); |
625 | |
626 | m_currentTextures[t] = texture; |
627 | } |