summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2015-09-05 02:45:29 +1200
committerScott Mansell <phiren@gmail.com>2015-09-06 21:16:51 +1200
commitb9be3245e1bcd3929baf4d1c66fe5a14b336cdbc (patch)
tree74ad51f328cce90485ee1fdf1f97f2546b01e2bc /Source/Core
parent52948bb3ef016abd7e35e775b17b7cf3f487d49c (diff)
Move common EFB copy code into VideoCommon
Addded a few duplicated depth copy texture formats to the enum in TextureDecoder.h. These texture formats were already implemented in TextureCacheBase and the ogl/dx11 texture cache implementations.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp60
-rw-r--r--Source/Core/VideoBackends/D3D/PSTextureEncoder.h4
-rw-r--r--Source/Core/VideoBackends/D3D/TextureCache.cpp23
-rw-r--r--Source/Core/VideoBackends/D3D/TextureCache.h2
-rw-r--r--Source/Core/VideoBackends/D3D/TextureEncoder.h89
-rw-r--r--Source/Core/VideoBackends/OGL/TextureCache.cpp20
-rw-r--r--Source/Core/VideoBackends/OGL/TextureCache.h2
-rw-r--r--Source/Core/VideoBackends/OGL/TextureConverter.cpp55
-rw-r--r--Source/Core/VideoBackends/OGL/TextureConverter.h4
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp106
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.h13
-rw-r--r--Source/Core/VideoCommon/TextureConversionShader.cpp2
-rw-r--r--Source/Core/VideoCommon/TextureDecoder.h5
-rw-r--r--Source/Core/VideoCommon/TextureDecoder_Common.cpp15
14 files changed, 151 insertions, 249 deletions
diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
index 3285ff8602..a5fa6de7a5 100644
--- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
+++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
@@ -87,55 +87,21 @@ void PSTextureEncoder::Shutdown()
SAFE_RELEASE(m_out);
}
-size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
+void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf)
{
if (!m_ready) // Make sure we initialized OK
- return 0;
-
- // Clamp srcRect to 640x528. BPS: The Strike tries to encode an 800x600
- // texture, which is invalid.
- EFBRectangle correctSrc = srcRect;
- correctSrc.ClampUL(0, 0, EFB_WIDTH, EFB_HEIGHT);
-
- // Validate source rect size
- if (correctSrc.GetWidth() <= 0 || correctSrc.GetHeight() <= 0)
- return 0;
+ return;
HRESULT hr;
- unsigned int blockW = BLOCK_WIDTHS[dstFormat];
- unsigned int blockH = BLOCK_HEIGHTS[dstFormat];
-
- // Round up source dims to multiple of block size
- unsigned int actualWidth = correctSrc.GetWidth() / (scaleByHalf ? 2 : 1);
- actualWidth = (actualWidth + blockW-1) & ~(blockW-1);
- unsigned int actualHeight = correctSrc.GetHeight() / (scaleByHalf ? 2 : 1);
- actualHeight = (actualHeight + blockH-1) & ~(blockH-1);
-
- unsigned int numBlocksX = actualWidth/blockW;
- unsigned int numBlocksY = actualHeight/blockH;
-
- unsigned int cacheLinesPerRow;
- if (dstFormat == 0x6) // RGBA takes two cache lines per block; all others take one
- cacheLinesPerRow = numBlocksX*2;
- else
- cacheLinesPerRow = numBlocksX;
- _assert_msg_(VIDEO, cacheLinesPerRow*32 <= MAX_BYTES_PER_BLOCK_ROW, "cache lines per row sanity check");
-
- unsigned int totalCacheLines = cacheLinesPerRow * numBlocksY;
- _assert_msg_(VIDEO, totalCacheLines*32 <= MAX_BYTES_PER_ENCODE, "total encode size sanity check");
-
- size_t encodeSize = 0;
-
// Reset API
g_renderer->ResetAPIState();
// Set up all the state for EFB encoding
-
{
- D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow * 8), FLOAT(numBlocksY));
+ D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(texture_entry->CacheLinesPerRow() * 8), FLOAT(texture_entry->NumBlocksY()));
D3D::context->RSSetViewports(1, &vp);
EFBRectangle fullSrcRect;
@@ -155,9 +121,9 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
EFBEncodeParams params;
- params.SrcLeft = correctSrc.left;
- params.SrcTop = correctSrc.top;
- params.DestWidth = actualWidth;
+ params.SrcLeft = srcRect.left;
+ params.SrcTop = srcRect.top;
+ params.DestWidth = texture_entry->native_width;
params.ScaleFactor = scaleByHalf ? 2 : 1;
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &params, 0, 0);
D3D::stateman->SetPixelConstants(m_encodeParams);
@@ -172,12 +138,12 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
targetRect.AsRECT(),
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
- SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf),
+ SetStaticShader(texture_entry->format, srcFormat, isIntensity, scaleByHalf),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout());
// Copy to staging buffer
- D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, cacheLinesPerRow * 8, numBlocksY, 1);
+ D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, texture_entry->CacheLinesPerRow() * 8, texture_entry->NumBlocksY(), 1);
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
// Transfer staging buffer to GameCube/Wii RAM
@@ -186,16 +152,14 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
u8* src = (u8*)map.pData;
- for (unsigned int y = 0; y < numBlocksY; ++y)
+ for (unsigned int y = 0; y < texture_entry->NumBlocksY(); ++y)
{
- memcpy(dst, src, cacheLinesPerRow*32);
- dst += dstStride;
+ memcpy(dst, src, texture_entry->CacheLinesPerRow() * 32);
+ dst += texture_entry->memory_stride;
src += map.RowPitch;
}
D3D::context->Unmap(m_outStage, 0);
-
- encodeSize = dstStride * numBlocksY;
}
// Restore API
@@ -203,8 +167,6 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t dstStrid
D3D::context->OMSetRenderTargets(1,
&FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV());
-
- return encodeSize;
}
ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, PEControl::PixelFormat srcFormat,
diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h
index 7034a17bb9..2857e9de7e 100644
--- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h
+++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h
@@ -6,6 +6,8 @@
#include "VideoBackends/D3D/TextureEncoder.h"
+#include "VideoCommon/TextureCacheBase.h"
+
struct ID3D11Texture2D;
struct ID3D11RenderTargetView;
struct ID3D11Buffer;
@@ -29,7 +31,7 @@ public:
void Init();
void Shutdown();
- size_t Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
+ void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf);
diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp
index 5616a833e2..60a5922f29 100644
--- a/Source/Core/VideoBackends/D3D/TextureCache.cpp
+++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/HW/Memmap.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DShader.h"
#include "VideoBackends/D3D/D3DState.h"
@@ -185,7 +184,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf
}
}
-void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
+void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
@@ -226,10 +225,13 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
// Create texture copy
D3D::drawShadedTexQuad(
- (srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
- &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
- (srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
- VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
+ (srcFormat == PEControl::Z24 ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(),
+ &sourcerect, Renderer::GetTargetWidth(),
+ Renderer::GetTargetHeight(),
+ srcFormat == PEControl::Z24 ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
+ VertexShaderCache::GetSimpleVertexShader(),
+ VertexShaderCache::GetSimpleInputLayout(),
+ GeometryShaderCache::GetCopyGeometryShader());
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
@@ -237,14 +239,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (!g_ActiveConfig.bSkipEFBCopyToRam)
{
- u8* dst = Memory::GetPointer(dstAddr);
- size_t encoded_size = g_encoder->Encode(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf);
-
- size_in_bytes = (u32)encoded_size;
-
- TextureCache::MakeRangeDynamic(dstAddr, (u32)encoded_size);
-
- this->hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
+ g_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf);
}
}
diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h
index 9cd52afcf6..4fed08ff65 100644
--- a/Source/Core/VideoBackends/D3D/TextureCache.h
+++ b/Source/Core/VideoBackends/D3D/TextureCache.h
@@ -34,7 +34,7 @@ private:
void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels) override;
- void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
+ void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat) override;
diff --git a/Source/Core/VideoBackends/D3D/TextureEncoder.h b/Source/Core/VideoBackends/D3D/TextureEncoder.h
index a2a2a34fdb..445fffd218 100644
--- a/Source/Core/VideoBackends/D3D/TextureEncoder.h
+++ b/Source/Core/VideoBackends/D3D/TextureEncoder.h
@@ -5,96 +5,11 @@
#pragma once
#include "VideoCommon/BPMemory.h"
+#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VideoCommon.h"
namespace DX11
{
-
-// 4-bit format: 8x8 texels / cache line
-// 8-bit format: 8x4 texels / cache line
-// 16-bit format: 4x4 texels / cache line
-// 32-bit format: 4x4 texels / 2 cache lines
-// Compressed format: 8x8 texels / cache line
-
-// Document EFB encoding formats here with examples of where they are used.
-
-// Format: 0 - R4
-// Used in The Legend of Zelda: The Wind Waker for character shadows (srcFormat 1,
-// isIntensity 1, scaleByHalf 1).
-
-// Format: 1 - R8
-// FIXME: Unseen. May or may not be a duplicate of format 8.
-
-// Format: 2 - A4 R4
-// FIXME: Unseen.
-
-// Format: 3 - A8 R8
-// FIXME: Unseen.
-
-// Format: 4 - R5 G6 B5
-// Used in Wind Waker for most render-to-texture effects like heat shimmer and
-// depth-of-field.
-
-// Format: 5 - 1 R5 G5 B5 or 0 A3 R4 G4 B4
-// Used in Twilight Princess for character shadows.
-
-// Format: 6 - A8 R8 A8 R8 | G8 B8 G8 B8
-// Used in Twilight Princess for bloom effect.
-
-// Format: 7 - A8
-// Used in Metroid Prime 2 for the scan visor.
-
-// Format: 8 - R8
-// Used in Twilight Princess for the map.
-
-// Format: 9 - G8
-// FIXME: Unseen.
-
-// Format: A - B8
-// Used in Metroid Prime 2 for the scan visor.
-
-// Format: B - G8 R8
-// Used in Wind Waker for depth-of-field. Usually used with srcFormat 3 to
-// render depth textures. The bytes are swapped, so games have to correct it
-// in RAM before using it as a texture.
-
-// Format: C - B8 G8
-// FIXME: Unseen.
-
-const unsigned int BLOCK_WIDTHS[16] = {
- 8, // R4
- 8, // R8 (FIXME: duplicate of R8 below?)
- 8, // A4 R4
- 4, // A8 R8
- 4, // R5 G6 B5
- 4, // 1 R5 G5 B5 or 0 A3 R4 G4 B4
- 4, // A8 R8 A8 R8 | G8 B8 G8 B8 (two cache lines)
- 8, // A8
- 8, // R8 (FIXME: duplicate of R8 above?)
- 8, // G8
- 8, // B8
- 4, // G8 R8
- 4, // B8 G8
- 0, 0, 0 // Unknown formats
-};
-
-const unsigned int BLOCK_HEIGHTS[16] = {
- 8, // R4
- 4, // R8 (FIXME: duplicate of R8 below?)
- 4, // A4 R4
- 4, // A8 R8
- 4, // R5 G6 B5
- 4, // 1 R5 G5 B5 or 0 A3 R4 G4 B4
- 4, // A8 R8 A8 R8 | G8 B8 G8 B8 (two cache lines)
- 4, // A8
- 4, // R8 (FIXME: duplicate of R8 above?)
- 4, // G8
- 4, // B8
- 4, // G8 R8
- 4, // B8 G8
- 0, 0, 0 // Unknown formats
-};
-
// Maximum number of bytes that can occur in a texture block-row generated by
// the encoder
static const UINT MAX_BYTES_PER_BLOCK_ROW = (EFB_WIDTH/4)*64;
@@ -111,7 +26,7 @@ public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
// Returns size in bytes of encoded block of memory
- virtual size_t Encode(u8* dst, unsigned int dstFormat, size_t dstStride,
+ virtual void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf) = 0;
diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp
index d388da2084..c8c71ccc29 100644
--- a/Source/Core/VideoBackends/OGL/TextureCache.cpp
+++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp
@@ -213,7 +213,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
TextureCache::SetStage();
}
-void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
+void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int dstFormat, u32 dstStride,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
@@ -264,24 +264,14 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (!g_ActiveConfig.bSkipEFBCopyToRam)
{
- int encoded_size = TextureConverter::EncodeToRamFromTexture(
- dstAddr,
+ TextureConverter::EncodeToRamFromTexture(
+ dstPointer,
+ this,
read_texture,
srcFormat == PEControl::Z24,
isIntensity,
- dstFormat,
scaleByHalf,
- srcRect,
- dstStride);
-
- u8* dst = Memory::GetPointer(dstAddr);
- u64 const new_hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
-
- size_in_bytes = (u32)encoded_size;
-
- TextureCache::MakeRangeDynamic(dstAddr, encoded_size);
-
- hash = new_hash;
+ srcRect);
}
FramebufferManager::SetFramebuffer(0);
diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h
index b8843c4edf..3f6f54b876 100644
--- a/Source/Core/VideoBackends/OGL/TextureCache.h
+++ b/Source/Core/VideoBackends/OGL/TextureCache.h
@@ -41,7 +41,7 @@ private:
void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level) override;
- void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
+ void FromRenderTarget(u8 *dst, unsigned int dstFormat, u32 dstStride,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat) override;
diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp
index c85b617294..5020058da0 100644
--- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp
+++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp
@@ -268,59 +268,18 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
}
}
-int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source, u32 writeStride)
+void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry,
+ GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source)
{
- u32 format = copyfmt;
-
- if (bFromZBuffer)
- {
- format |= _GX_TF_ZTF;
- if (copyfmt == 11)
- format = GX_TF_Z16;
- else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
- format |= _GX_TF_CTF;
- }
- else
- {
- if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
- format |= _GX_TF_CTF;
- }
-
- SHADER& texconv_shader = GetOrCreateEncodingShader(format);
-
- u8 *dest_ptr = Memory::GetPointer(address);
-
- int width = (source.right - source.left) >> bScaleByHalf;
- int height = (source.bottom - source.top) >> bScaleByHalf;
-
- int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
-
- u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
- u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
-
- // only copy on cache line boundaries
- // extra pixels are copied but not displayed in the resulting texture
- s32 expandedWidth = (width + blkW) & (~blkW);
- s32 expandedHeight = (height + blkH) & (~blkH);
+ SHADER& texconv_shader = GetOrCreateEncodingShader(texture_entry->format);
texconv_shader.Bind();
- glUniform4i(s_encodingUniforms[format],
- source.left, source.top,
- expandedWidth, bScaleByHalf ? 2 : 1);
-
- unsigned int numBlocksX = expandedWidth / TexDecoder_GetBlockWidthInTexels(format);
- unsigned int numBlocksY = expandedHeight / TexDecoder_GetBlockHeightInTexels(format);
- unsigned int cacheLinesPerRow;
- if ((format & 0x0f) == 6)
- cacheLinesPerRow = numBlocksX * 2;
- else
- cacheLinesPerRow = numBlocksX;
+ glUniform4i(s_encodingUniforms[texture_entry->format],
+ source.left, source.top, texture_entry->native_width, bScaleByHalf ? 2 : 1);
EncodeToRamUsingShader(source_texture,
- dest_ptr, cacheLinesPerRow * 32, numBlocksY,
- writeStride, bScaleByHalf > 0 && !bFromZBuffer);
- return size_in_bytes; // TODO: D3D11 is calculating this value differently!
-
+ dest_ptr, texture_entry->CacheLinesPerRow() * 32, texture_entry->NumBlocksY(),
+ texture_entry->memory_stride, bScaleByHalf > 0 && !bFromZBuffer);
}
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight)
diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h
index c41dfe10ac..186c9fe6d0 100644
--- a/Source/Core/VideoBackends/OGL/TextureConverter.h
+++ b/Source/Core/VideoBackends/OGL/TextureConverter.h
@@ -5,6 +5,7 @@
#pragma once
#include "VideoBackends/OGL/GLUtil.h"
+#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VideoCommon.h"
namespace OGL
@@ -24,7 +25,8 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
// returns size of the encoded data (in bytes)
-int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source, u32 writeStride);
+void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry,
+ GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source);
}
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index 5ab1b47bc4..62bf511863 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -182,24 +182,6 @@ void TextureCache::Cleanup(int _frameCount)
}
}
-void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
-{
- TexCache::iterator
- iter = textures_by_address.begin();
-
- while (iter != textures_by_address.end())
- {
- if (iter->second->OverlapsMemoryRange(start_address, size))
- {
- iter = FreeTexture(iter);
- }
- else
- {
- ++iter;
- }
- }
-}
-
bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const
{
if (addr + size_in_bytes <= range_address)
@@ -243,7 +225,7 @@ TextureCache::TCacheEntryBase* TextureCache::DoPartialTextureUpdates(TexCache::i
&& entry_to_update->addr <= entry->addr
&& entry->addr + entry->size_in_bytes <= entry_to_update->addr + entry_to_update->size_in_bytes
&& entry->frameCount == FRAMECOUNT_INVALID
- && entry->copyStride == numBlocksX * block_size)
+ && entry->memory_stride == numBlocksX * block_size)
{
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
@@ -753,9 +735,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 0: // Z4
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f;
cbufid = 0;
+ dstFormat |= _GX_TF_CTF;
break;
+ case 8: // Z8H
+ dstFormat |= _GX_TF_CTF;
case 1: // Z8
- case 8: // Z8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
cbufid = 1;
break;
@@ -768,6 +752,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 11: // Z16 (reverse order)
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 3;
+ dstFormat |= _GX_TF_CTF;
break;
case 6: // Z24X8
@@ -778,11 +763,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 9: // Z8M
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 5;
+ dstFormat |= _GX_TF_CTF;
break;
case 10: // Z8L
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 6;
+ dstFormat |= _GX_TF_CTF;
break;
case 12: // Z16L - copy lower 16 depth bits
@@ -790,6 +777,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
// Used e.g. in Zelda: Skyward Sword
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 7;
+ dstFormat |= _GX_TF_CTF;
break;
default:
@@ -798,6 +786,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
cbufid = 8;
break;
}
+
+ dstFormat |= _GX_TF_ZTF;
}
else if (isIntensity)
{
@@ -862,11 +852,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
ColorMask[0] = 15.0f;
ColorMask[4] = 1.0f / 15.0f;
cbufid = 14;
+ dstFormat |= _GX_TF_CTF;
break;
case 1: // R8
case 8: // R8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
cbufid = 15;
+ dstFormat |= _GX_TF_CTF;
break;
case 2: // RA4
@@ -881,6 +873,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 17;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 3: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f;
@@ -892,6 +885,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 19;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 7: // A8
@@ -907,25 +901,30 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 21;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 9: // G8
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 22;
+ dstFormat |= _GX_TF_CTF;
break;
case 10: // B8
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 23;
+ dstFormat |= _GX_TF_CTF;
break;
case 11: // RG8
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 24;
+ dstFormat |= _GX_TF_CTF;
break;
case 12: // GB8
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 25;
+ dstFormat |= _GX_TF_CTF;
break;
case 4: // RGB565
@@ -973,6 +972,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
}
}
+ u8* dst = Memory::GetPointer(dstAddr);
+ if (dst == nullptr)
+ {
+ ERROR_LOG(VIDEO, "Trying to copy from EFB to invalid address 0x%8x", dstAddr);
+ return;
+ }
+
const unsigned int tex_w = scaleByHalf ? srcRect.GetWidth() / 2 : srcRect.GetWidth();
const unsigned int tex_h = scaleByHalf ? srcRect.GetHeight() / 2 : srcRect.GetHeight();
@@ -996,17 +1002,36 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
TCacheEntryBase* entry = AllocateTexture(config);
- // TODO: Using the wrong dstFormat, dumb...
entry->SetGeneralParameters(dstAddr, 0, dstFormat);
entry->SetDimensions(tex_w, tex_h, 1);
entry->SetHashes(TEXHASH_INVALID);
entry->frameCount = FRAMECOUNT_INVALID;
- entry->is_efb_copy = true;
+ entry->SetEfbCopy(dstStride);
entry->is_custom_tex = false;
- entry->copyStride = dstStride;
- entry->FromRenderTarget(dstAddr, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
+ entry->FromRenderTarget(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
+
+ if (!g_ActiveConfig.bSkipEFBCopyToRam)
+ {
+ entry->hash = GetHash64(dst, (int)entry->size_in_bytes, g_ActiveConfig.iSafeTextureCache_ColorSamples);
+
+ // Invalidate all textures that overlap the range of our texture
+ TexCache::iterator
+ iter = textures_by_address.begin();
+
+ while (iter != textures_by_address.end())
+ {
+ if (iter->second->OverlapsMemoryRange(dstAddr, entry->size_in_bytes))
+ {
+ iter = FreeTexture(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
if (g_ActiveConfig.bDumpEFBTarget)
{
@@ -1052,3 +1077,36 @@ TextureCache::TexCache::iterator TextureCache::FreeTexture(TexCache::iterator it
return textures_by_address.erase(iter);
}
+
+u32 TextureCache::TCacheEntryBase::CacheLinesPerRow() const
+{
+ u32 blockW = TexDecoder_GetBlockWidthInTexels(format) - 1;
+ // Round up source height to multiple of block size
+ u32 actualWidth = (native_width + blockW) & ~(blockW);
+
+ u32 numBlocksX = actualWidth / TexDecoder_GetBlockWidthInTexels(format);
+
+ // RGBA takes two cache lines per block; all others take one
+ if (format == GX_TF_RGBA8)
+ numBlocksX = numBlocksX * 2;
+ return numBlocksX;
+}
+
+u32 TextureCache::TCacheEntryBase::NumBlocksY() const
+{
+ u32 blockH = TexDecoder_GetBlockHeightInTexels(format) - 1;
+ // Round up source height to multiple of block size
+ u32 actualHeight = (native_height + blockH) & ~(blockH);
+
+ return actualHeight / TexDecoder_GetBlockHeightInTexels(format);
+}
+
+void TextureCache::TCacheEntryBase::SetEfbCopy(u32 stride)
+{
+ is_efb_copy = true;
+ memory_stride = stride;
+
+ _assert_msg_(VIDEO, memory_stride >= CacheLinesPerRow(), "Memory stride is too small");
+
+ size_in_bytes = memory_stride * NumBlocksY();
+}
diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h
index 6bb80f945c..c012cad0fc 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.h
+++ b/Source/Core/VideoCommon/TextureCacheBase.h
@@ -53,7 +53,7 @@ public:
u32 format;
bool is_efb_copy;
bool is_custom_tex;
- u32 copyStride;
+ u32 memory_stride;
unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view
unsigned int native_levels;
@@ -76,6 +76,7 @@ public:
native_width = _native_width;
native_height = _native_height;
native_levels = _native_levels;
+ memory_stride = _native_width;
}
void SetHashes(u64 _hash)
@@ -83,6 +84,8 @@ public:
hash = _hash;
}
+ void SetEfbCopy(u32 stride);
+
TCacheEntryBase(const TCacheEntryConfig& c) : config(c) {}
virtual ~TCacheEntryBase();
@@ -96,7 +99,7 @@ public:
virtual void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level) = 0;
- virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
+ virtual void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat) = 0;
@@ -104,6 +107,11 @@ public:
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
bool IsEfbCopy() const { return is_efb_copy; }
+
+ u32 NumBlocksY() const;
+ u32 CacheLinesPerRow() const;
+
+ void Memset(u8* ptr, u32 tag);
};
virtual ~TextureCache(); // needs virtual for DX11 dtor
@@ -115,7 +123,6 @@ public:
static void Cleanup(int _frameCount);
static void Invalidate();
- static void MakeRangeDynamic(u32 start_address, u32 size);
virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0;
diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp
index 9375a984c8..033a56b4aa 100644
--- a/Source/Core/VideoCommon/TextureConversionShader.cpp
+++ b/Source/Core/VideoCommon/TextureConversionShader.cpp
@@ -650,9 +650,11 @@ const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
case GX_CTF_GB8:
WriteCC8Encoder(p, "gb", ApiType);
break;
+ case GX_CTF_Z8H:
case GX_TF_Z8:
WriteC8Encoder(p, "r", ApiType);
break;
+ case GX_CTF_Z16R:
case GX_TF_Z16:
WriteZ16Encoder(p, ApiType);
break;
diff --git a/Source/Core/VideoCommon/TextureDecoder.h b/Source/Core/VideoCommon/TextureDecoder.h
index 1abcc5705c..fd3ee43ff7 100644
--- a/Source/Core/VideoCommon/TextureDecoder.h
+++ b/Source/Core/VideoCommon/TextureDecoder.h
@@ -35,7 +35,6 @@ enum TextureFormat
GX_CTF_R4 = 0x0 | _GX_TF_CTF,
GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
- GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
GX_CTF_A8 = 0x7 | _GX_TF_CTF,
GX_CTF_R8 = 0x8 | _GX_TF_CTF,
GX_CTF_G8 = 0x9 | _GX_TF_CTF,
@@ -43,13 +42,17 @@ enum TextureFormat
GX_CTF_RG8 = 0xB | _GX_TF_CTF,
GX_CTF_GB8 = 0xC | _GX_TF_CTF,
+ // Texture formats (which match the color formats above)
GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
+ // copy only texture formats
GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z8H = 0x8 | _GX_TF_ZTF | _GX_TF_CTF, // This produces an identical result to to GX_TF_Z8
GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z16R = 0xB | _GX_TF_ZTF | _GX_TF_CTF, // Reversed version of GX_TF_Z16
GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
};
diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp
index 092b8ec1e0..8fc1631b93 100644
--- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp
+++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp
@@ -35,7 +35,6 @@ int TexDecoder_GetTexelSizeInNibbles(int format)
case GX_CTF_R4: return 1;
case GX_CTF_RA4: return 2;
case GX_CTF_RA8: return 4;
- case GX_CTF_YUVA8: return 8;
case GX_CTF_A8: return 2;
case GX_CTF_R8: return 2;
case GX_CTF_G8: return 2;
@@ -48,10 +47,14 @@ int TexDecoder_GetTexelSizeInNibbles(int format)
case GX_TF_Z24X8: return 8;
case GX_CTF_Z4: return 1;
+ case GX_CTF_Z8H: return 2;
case GX_CTF_Z8M: return 2;
case GX_CTF_Z8L: return 2;
+ case GX_CTF_Z16R: return 4;
case GX_CTF_Z16L: return 4;
- default: return 1;
+ default:
+ PanicAlert("Unsupported Texture Format (%08x)! (GetTexelSizeInNibbles)", format);
+ return 1;
}
}
@@ -88,11 +91,13 @@ int TexDecoder_GetBlockWidthInTexels(u32 format)
case GX_TF_Z16: return 4;
case GX_TF_Z24X8: return 4;
case GX_CTF_Z4: return 8;
+ case GX_CTF_Z8H: return 8;
case GX_CTF_Z8M: return 8;
case GX_CTF_Z8L: return 8;
+ case GX_CTF_Z16R: return 4;
case GX_CTF_Z16L: return 4;
default:
- ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format);
+ PanicAlert("Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format);
return 8;
}
}
@@ -125,11 +130,13 @@ int TexDecoder_GetBlockHeightInTexels(u32 format)
case GX_TF_Z16: return 4;
case GX_TF_Z24X8: return 4;
case GX_CTF_Z4: return 8;
+ case GX_CTF_Z8H: return 4;
case GX_CTF_Z8M: return 4;
case GX_CTF_Z8L: return 4;
+ case GX_CTF_Z16R: return 4;
case GX_CTF_Z16L: return 4;
default:
- ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format);
+ PanicAlert("Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format);
return 4;
}
}