Dependency cleanup in DX9.
[dolphin.git] / Source / Plugins / Plugin_VideoDX9 / Src / TextureCache.cpp
blob4da1000df60d003917f5703b14d1963760c0580e
1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include <d3dx9.h>
20 #include "Globals.h"
21 #include "Statistics.h"
22 #include "MemoryUtil.h"
23 #include "Hash.h"
25 #include "CommonPaths.h"
26 #include "FileUtil.h"
28 #include "D3DBase.h"
29 #include "D3DTexture.h"
30 #include "D3DUtil.h"
31 #include "FramebufferManager.h"
32 #include "PixelShaderCache.h"
33 #include "PixelShaderManager.h"
34 #include "VertexShaderManager.h"
35 #include "VertexShaderCache.h"
37 #include "Render.h"
39 #include "TextureDecoder.h"
40 #include "TextureCache.h"
41 #include "HiresTextures.h"
42 #include "TextureConverter.h"
44 #include "debugger/debugger.h"
46 u8 *TextureCache::temp = NULL;
47 TextureCache::TexCache TextureCache::textures;
49 extern int frameCount;
51 #define TEMP_SIZE (1024*1024*4)
52 #define TEXTURE_KILL_THRESHOLD 200
54 void TextureCache::TCacheEntry::Destroy(bool shutdown)
56 if (texture)
57 texture->Release();
58 texture = 0;
59 if (!isRenderTarget && !shutdown && !g_ActiveConfig.bSafeTextureCache)
61 u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr);
62 if (ptr && *ptr == hash)
63 *ptr = oldpixel;
67 void TextureCache::Init()
69 temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
70 TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
71 HiresTextures::Init(globals->unique_id);
74 void TextureCache::Invalidate(bool shutdown)
76 for (TexCache::iterator iter = textures.begin(); iter != textures.end(); ++iter)
77 iter->second.Destroy(shutdown);
78 textures.clear();
79 HiresTextures::Shutdown();
82 void TextureCache::InvalidateRange(u32 start_address, u32 size)
84 TexCache::iterator iter = textures.begin();
85 while (iter != textures.end())
87 int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
88 if (rangePosition == 0)
90 iter->second.Destroy(false);
91 textures.erase(iter++);
93 else
95 ++iter;
100 void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
102 TexCache::iterator iter = textures.begin();
103 while (iter != textures.end())
105 int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
106 if ( rangePosition == 0)
108 iter->second.hash = 0;
110 ++iter;
114 int TextureCache::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size)
116 if (addr + size_in_bytes < range_address)
117 return -1;
118 if (addr >= range_address + range_size)
119 return 1;
120 return 0;
123 void TextureCache::Shutdown()
125 Invalidate(true);
126 FreeMemoryPages(temp, TEMP_SIZE);
127 temp = NULL;
130 void TextureCache::Cleanup()
132 TexCache::iterator iter = textures.begin();
133 while (iter != textures.end())
135 if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount)
137 iter->second.Destroy(false);
138 iter = textures.erase(iter);
140 else
142 ++iter;
147 TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt,bool UseNativeMips, int maxlevel)
149 if (address == 0)
150 return NULL;
152 u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
153 int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
154 int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
155 int bsdepth = TexDecoder_GetTexelSizeInNibbles(tex_format);
156 int expandedWidth = (width + bsw) & (~bsw);
157 int expandedHeight = (height + bsh) & (~bsh);
159 u64 hash_value;
160 u32 texID = address;
161 u64 texHash;
162 u32 FullFormat = tex_format;
163 bool TextureIsDinamic = false;
164 if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
165 u32 FullFormat = (tex_format | (tlutfmt << 16));
167 if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)
169 texHash = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
170 if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
172 // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
173 // tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower.
174 // This trick (to change the texID depending on the TLUT addr) is a trick to get around
175 // an issue with metroid prime's fonts, where it has multiple sets of fonts on top of
176 // each other stored in a single texture, and uses the palette to make different characters
177 // visible or invisible. Thus, unless we want to recreate the textures for every drawn character,
178 // we must make sure that texture with different tluts get different IDs.
179 u64 tlutHash = TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
180 texHash ^= tlutHash;
181 if (g_ActiveConfig.bSafeTextureCache)
183 texID = texID ^ ((u32)(tlutHash & 0xFFFFFFFF)) ^ ((u32)((tlutHash >> 32) & 0xFFFFFFFF));
186 if (g_ActiveConfig.bSafeTextureCache)
187 hash_value = texHash;
190 bool skip_texture_create = false;
191 TexCache::iterator iter = textures.find(texID);
193 if (iter != textures.end())
195 TCacheEntry &entry = iter->second;
197 if (!g_ActiveConfig.bSafeTextureCache)
199 if(entry.isRenderTarget || entry.isDinamic)
201 if(!g_ActiveConfig.bCopyEFBToTexture && g_ActiveConfig.bVerifyTextureModificationsByCPU)
203 hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
204 if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
206 hash_value ^= TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
209 else
211 hash_value = 0;
214 else
216 hash_value = ((u32 *)ptr)[0];
219 else
221 if(entry.isRenderTarget || entry.isDinamic)
223 if(g_ActiveConfig.bCopyEFBToTexture || !g_ActiveConfig.bVerifyTextureModificationsByCPU)
225 hash_value = 0;
229 if (((entry.isRenderTarget || entry.isDinamic) && hash_value == entry.hash && address == entry.addr)
230 || ((address == entry.addr) && (hash_value == entry.hash) && FullFormat == entry.fmt/* && entry.MipLevels == maxlevel*/))
232 entry.frameCount = frameCount;
233 entry.isDinamic = false;
234 D3D::SetTexture(stage, entry.texture);
235 return &entry;
237 else
239 // Let's reload the new texture data into the same texture,
240 // instead of destroying it and having to create a new one.
241 // Might speed up movie playback very, very slightly.
242 TextureIsDinamic = (entry.isRenderTarget || entry.isDinamic) && !g_ActiveConfig.bCopyEFBToTexture;
244 if (!entry.isRenderTarget &&
245 ((!entry.isDinamic && width == entry.w && height==entry.h && FullFormat == entry.fmt /* && entry.MipLevels < maxlevel*/)
246 || (entry.isDinamic && entry.w == width && entry.h == height)))
248 skip_texture_create = true;
250 else
252 entry.Destroy(false);
253 textures.erase(iter);
258 // Make an entry in the table
259 TCacheEntry& entry = textures[texID];
260 entry.isDinamic = TextureIsDinamic;
261 PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
263 if (g_ActiveConfig.bHiresTextures)
265 // Load Custom textures
266 char texPathTemp[MAX_PATH];
267 int oldWidth = width;
268 int oldHeight = height;
270 sprintf(texPathTemp, "%s_%08x_%i", globals->unique_id, texHash, tex_format);
271 pcfmt = HiresTextures::GetHiresTex(texPathTemp, &width, &height, tex_format, temp);
273 if (pcfmt != PC_TEX_FMT_NONE)
275 expandedWidth = width;
276 expandedHeight = height;
277 entry.scaleX = (float) width / oldWidth;
278 entry.scaleY = (float) height / oldHeight;
282 if (pcfmt == PC_TEX_FMT_NONE)
283 pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
285 D3DFORMAT d3d_fmt;
286 bool swap_r_b = false;
287 switch (pcfmt) {
288 case PC_TEX_FMT_BGRA32:
289 d3d_fmt = D3DFMT_A8R8G8B8;
290 break;
291 case PC_TEX_FMT_RGBA32:
292 d3d_fmt = D3DFMT_A8R8G8B8;
293 swap_r_b = true;
294 break;
295 case PC_TEX_FMT_RGB565:
296 d3d_fmt = D3DFMT_R5G6B5;
297 break;
298 case PC_TEX_FMT_IA4_AS_IA8:
299 d3d_fmt = D3DFMT_A8L8;
300 break;
301 case PC_TEX_FMT_I8:
302 case PC_TEX_FMT_I4_AS_I8:
303 d3d_fmt = D3DFMT_A8P8; // A hack which means the format is a packed
304 // 8-bit intensity texture. It is unpacked
305 // to A8L8 in D3DTexture.cpp
306 break;
307 case PC_TEX_FMT_IA8:
308 d3d_fmt = D3DFMT_A8L8;
309 break;
310 case PC_TEX_FMT_DXT1:
311 d3d_fmt = D3DFMT_DXT1;
312 break;
315 entry.oldpixel = ((u32 *)ptr)[0];
316 if (g_ActiveConfig.bSafeTextureCache || entry.isDinamic)
317 entry.hash = hash_value;
318 else
320 entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
321 ((u32 *)ptr)[0] = entry.hash;
324 entry.addr = address;
325 entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format);
326 entry.isRenderTarget = false;
327 bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
328 entry.isNonPow2 = false;
329 int TexLevels = (width > height)?width:height;
330 TexLevels = (isPow2 && UseNativeMips && (maxlevel > 0)) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : ((isPow2)? 0 : 1);
331 if(TexLevels > (maxlevel + 1) && maxlevel > 0)
332 TexLevels = (maxlevel + 1);
333 entry.MipLevels = maxlevel;
334 if (!skip_texture_create)
336 entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b, TexLevels);
338 else
340 D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b, 0);
342 if(TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
344 int level = 1;
345 int mipWidth = (width + 1) >> 1;
346 int mipHeight = (height + 1) >> 1;
347 ptr += entry.size_in_bytes;
348 while((mipHeight || mipWidth) && (level < TexLevels))
350 u32 currentWidth = (mipWidth > 0)? mipWidth : 1;
351 u32 currentHeight = (mipHeight > 0)? mipHeight : 1;
352 expandedWidth = (currentWidth + bsw) & (~bsw);
353 expandedHeight = (currentHeight + bsh) & (~bsh);
354 TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
355 D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, currentWidth, currentHeight, expandedWidth, d3d_fmt, swap_r_b,level);
356 u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
357 ptr += size;
358 mipWidth >>= 1;
359 mipHeight >>= 1;
360 level++;
363 entry.frameCount = frameCount;
364 entry.w = width;
365 entry.h = height;
366 entry.Scaledw = width;
367 entry.Scaledh = height;
368 entry.fmt = FullFormat;
370 if (g_ActiveConfig.bDumpTextures)
372 // dump texture to file
373 char szTemp[MAX_PATH];
374 char szDir[MAX_PATH];
375 const char* uniqueId = globals->unique_id;
376 bool bCheckedDumpDir = false;
378 sprintf(szDir, "%s%s", File::GetUserPath(D_DUMPTEXTURES_IDX), uniqueId);
380 if (!bCheckedDumpDir)
382 if (!File::Exists(szDir) || !File::IsDirectory(szDir))
383 File::CreateDir(szDir);
385 bCheckedDumpDir = true;
388 sprintf(szTemp, "%s/%s_%08x_%i.png", szDir, uniqueId, texHash, tex_format);
390 if (!File::Exists(szTemp))
391 PD3DXSaveTextureToFileA(szTemp,D3DXIFF_PNG,entry.texture,0);
394 INCSTAT(stats.numTexturesCreated);
395 SETSTAT(stats.numTexturesAlive, (int)textures.size());
397 //Set the texture!
398 D3D::SetTexture(stage, entry.texture);
400 DEBUGGER_PAUSE_LOG_AT(NEXT_NEW_TEXTURE,true,{printf("A new texture (%d x %d) is loaded", width, height);});
401 return &entry;
404 void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect)
406 int efb_w = source_rect.GetWidth();
407 int efb_h = source_rect.GetHeight();
409 int tex_w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
410 int tex_h = (abs(source_rect.GetHeight()) >> bScaleByHalf);
411 //compensate the texture grow if supersampling is enabled to conserve memory usage
412 float SuperSampleCompensation = g_ActiveConfig.iMultisampleMode + 1;
413 SuperSampleCompensation = 1.0f / SuperSampleCompensation;
414 float xScale = Renderer::GetTargetScaleX();
415 float yScale = Renderer::GetTargetScaleY();
417 int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(xScale * SuperSampleCompensation * tex_w)):tex_w;
418 int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(yScale * SuperSampleCompensation * tex_h)):tex_h;
420 TexCache::iterator iter;
421 LPDIRECT3DTEXTURE9 tex = NULL;
422 iter = textures.find(address);
423 bool TextureIsDinamic = false;
424 if (iter != textures.end())
426 if ((iter->second.isRenderTarget && iter->second.Scaledw == Scaledtex_w && iter->second.Scaledh == Scaledtex_h)
427 || (iter->second.isDinamic && iter->second.w == tex_w && iter->second.h == tex_h))
429 tex = iter->second.texture;
430 TextureIsDinamic = iter->second.isDinamic;
431 iter->second.frameCount = frameCount;
433 else
435 // Remove it and recreate it as a render target
436 if(iter->second.texture)
437 iter->second.texture->Release();
438 iter->second.texture = 0;
439 textures.erase(iter);
442 if(TextureIsDinamic)
444 Scaledtex_w = tex_w;
445 Scaledtex_h = tex_h;
447 if(!tex)
449 TCacheEntry entry;
450 entry.addr = address;
451 entry.isRenderTarget = true;
452 entry.hash = 0;
453 entry.frameCount = frameCount;
454 entry.w = tex_w;
455 entry.h = tex_h;
456 entry.Scaledw = Scaledtex_w;
457 entry.Scaledh = Scaledtex_h;
458 entry.fmt = copyfmt;
459 entry.isNonPow2 = true;
460 entry.isDinamic = false;
461 D3D::dev->CreateTexture(Scaledtex_w, Scaledtex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
462 textures[address] = entry;
463 tex = entry.texture;
466 // Make sure to resolve anything we need to read from.
467 LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager.GetEFBDepthTexture(source_rect) : FBManager.GetEFBColorTexture(source_rect);
469 // We have to run a pixel shader, for color conversion.
470 Renderer::ResetAPIState(); // reset any game specific settings
471 if(!TextureIsDinamic || g_ActiveConfig.bCopyEFBToTexture)
474 float colmat[16]= {0.0f};
475 float fConstAdd[4] = {0.0f};
477 if (bFromZBuffer)
479 switch(copyfmt)
481 case 0: // Z4
482 case 1: // Z8
483 colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
484 break;
485 case 3: // Z16 //?
486 colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f;
487 case 11: // Z16 (reverse order)
488 colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
489 break;
490 case 6: // Z24X8
491 colmat[0] = colmat[5] = colmat[10] = 1.0f;
492 break;
493 case 9: // Z8M
494 colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
495 break;
496 case 10: // Z8L
497 colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
498 break;
499 case 12: // Z16L
500 colmat[2] = colmat[6] = colmat[10] = colmat[13] = 1.0f;
501 break;
502 default:
503 ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", copyfmt);
504 colmat[2] = colmat[5] = colmat[8] = 1.0f;
505 break;
508 else if (bIsIntensityFmt)
510 fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f;
511 switch (copyfmt)
513 case 0: // I4
514 case 1: // I8
515 case 2: // IA4
516 case 3: // IA8
517 colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f;
518 colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f;
519 colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f;
521 if (copyfmt < 2)
523 fConstAdd[3] = 16.0f / 255.0f;
524 colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f;
526 else// alpha
527 colmat[15] = 1;
529 break;
530 default:
531 ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", copyfmt);
532 colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
533 break;
536 else
538 switch (copyfmt)
540 case 0: // R4
541 case 8: // R8
542 colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
543 break;
544 case 2: // RA4
545 case 3: // RA8
546 colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
547 break;
549 case 7: // A8
550 colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1;
551 break;
552 case 9: // G8
553 colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1;
554 break;
555 case 10: // B8
556 colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1;
557 break;
558 case 11: // RG8
559 colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1;
560 break;
561 case 12: // GB8
562 colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1;
563 break;
565 case 4: // RGB565
566 colmat[0] = colmat[5] = colmat[10] = 1;
567 fConstAdd[3] = 1; // set alpha to 1
568 break;
569 case 5: // RGB5A3
570 case 6: // RGBA8
571 colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
572 break;
574 default:
575 ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", copyfmt);
576 colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
577 break;
581 LPDIRECT3DSURFACE9 Rendersurf = NULL;
582 tex->GetSurfaceLevel(0,&Rendersurf);
583 D3D::dev->SetDepthStencilSurface(NULL);
584 D3D::dev->SetRenderTarget(0, Rendersurf);
586 D3DVIEWPORT9 vp;
588 // Stretch picture with increased internal resolution
589 vp.X = 0;
590 vp.Y = 0;
591 vp.Width = Scaledtex_w;
592 vp.Height = Scaledtex_h;
593 vp.MinZ = 0.0f;
594 vp.MaxZ = 1.0f;
595 D3D::dev->SetViewport(&vp);
596 RECT destrect;
597 destrect.bottom = Scaledtex_h;
598 destrect.left = 0;
599 destrect.right = Scaledtex_w;
600 destrect.top = 0;
603 PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
604 TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
605 RECT sourcerect;
606 sourcerect.bottom = targetSource.bottom;
607 sourcerect.left = targetSource.left;
608 sourcerect.right = targetSource.right;
609 sourcerect.top = targetSource.top;
612 if(bFromZBuffer)
614 if(bScaleByHalf || g_ActiveConfig.iMultisampleMode)
616 D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
617 D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
619 else
621 D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
622 D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
625 else
627 D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
628 D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
632 D3DFORMAT bformat = FBManager.GetEFBDepthRTSurfaceFormat();
633 int SSAAMode = g_ActiveConfig.iMultisampleMode;
634 D3D::drawShadedTexQuad(
635 read_texture,
636 &sourcerect,
637 Renderer::GetFullTargetWidth() ,
638 Renderer::GetFullTargetHeight(),
639 Scaledtex_w,
640 Scaledtex_h,
641 ((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(SSAAMode): PixelShaderCache::GetColorMatrixProgram(SSAAMode),
642 VertexShaderCache::GetSimpleVertexShader(SSAAMode));
643 Rendersurf->Release();
646 if(!g_ActiveConfig.bCopyEFBToTexture)
648 textures[address].hash = TextureConverter::EncodeToRamFromTexture(
649 address,
650 read_texture,
651 Renderer::GetFullTargetWidth(),
652 Renderer::GetFullTargetHeight(),
653 xScale,
654 yScale,
655 (float)((Renderer::GetFullTargetWidth() - Renderer::GetTargetWidth()) / 2),
656 (float)((Renderer::GetFullTargetHeight() - Renderer::GetTargetHeight()) / 2) ,
657 bFromZBuffer,
658 bIsIntensityFmt,
659 copyfmt,
660 bScaleByHalf,
661 source_rect);
664 D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
665 D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
666 D3D::SetTexture(0,NULL);
667 D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
668 D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
669 Renderer::RestoreAPIState();