int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, 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; LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format); if (!texconv_shader) return 0; 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; u16 samples = TextureConversionShader::GetEncodedSampleCount(format); // 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); float sampleStride = bScaleByHalf ? 2.f : 1.f; TextureConversionShader::SetShaderParameters( (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? (float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(source.top), Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride), (float)SourceW, (float)SourceH); TargetRectangle scaledSource; scaledSource.top = 0; scaledSource.bottom = expandedHeight; scaledSource.left = 0; scaledSource.right = expandedWidth / samples; int cacheBytes = 32; if ((format & 0x0f) == 6) cacheBytes = 64; int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f); return size_in_bytes; // TODO: D3D11 is calculating this value differently! }
int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, 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; u16 samples = TextureConversionShader::GetEncodedSampleCount(format); // 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); texconv_shader.Bind(); glUniform4i(s_encodingUniforms[format], source.left, source.top, expandedWidth, bScaleByHalf ? 2 : 1); TargetRectangle scaledSource; scaledSource.top = 0; scaledSource.bottom = expandedHeight; scaledSource.left = 0; scaledSource.right = expandedWidth / samples; int cacheBytes = 32; if ((format & 0x0f) == 6) cacheBytes = 64; int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, bScaleByHalf > 0 && !bFromZBuffer); return size_in_bytes; // TODO: D3D11 is calculating this value differently! }
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) { g_renderer->ResetAPIState(); s_rgbToYuyvProgram.Bind(); EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false); FramebufferManager::SetFramebuffer(0); VertexShaderManager::SetViewportChanged(); TextureCache::DisableStage(0); g_renderer->RestoreAPIState(); GL_REPORT_ERRORD(); }
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) { g_renderer->ResetAPIState(); s_rgbToYuyvProgram.Bind(); glUniform4f(s_rgbToYuyvUniform_loc, sourceRc.left, sourceRc.top, sourceRc.right, sourceRc.bottom); // We enable linear filtering, because the gamecube does filtering in the vertical direction when // yscale is enabled. // Otherwise we get jaggies when a game uses yscaling (most PAL games) EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, dstWidth*dstHeight*2, true); FramebufferManager::SetFramebuffer(0); TextureCache::DisableStage(0); g_renderer->RestoreAPIState(); GL_REPORT_ERRORD(); }
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma) { TextureConversionShader::SetShaderParameters( (float)dstWidth, (float)dstHeight, 0.0f , 0.0f, 1.0f, 1.0f, (float)Renderer::GetTargetWidth(), (float)Renderer::GetTargetHeight()); g_renderer->ResetAPIState(); EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, dstWidth * 2, false, false,Gamma); D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); g_renderer->RestoreAPIState(); }
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry, u32 SourceW, u32 SourceH, LPDIRECT3DTEXTURE9 source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) { LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(texture_entry->format); if (!texconv_shader) return; int width = (source.right - source.left) >> bScaleByHalf; int height = (source.bottom - source.top) >> bScaleByHalf; u16 blkW = TexDecoder_GetBlockWidthInTexels(texture_entry->format); u16 blkH = TexDecoder_GetBlockHeightInTexels(texture_entry->format); u16 samples = TextureConversionShader::GetEncodedSampleCount(texture_entry->format); // only copy on cache line boundaries // extra pixels are copied but not displayed in the resulting texture s32 expandedWidth = ROUND_UP(width, blkW); s32 expandedHeight = ROUND_UP(height, blkH); float sampleStride = bScaleByHalf ? 2.f : 1.f; TextureConversionShaderLegacy::SetShaderParameters( (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? (float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(source.top), Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride), (float)SourceW, (float)SourceH); D3D::dev->SetPixelShaderConstantF(C_COLORMATRIX, PixelShaderManager::GetBuffer(), 2); TargetRectangle scaledSource; scaledSource.top = 0; scaledSource.bottom = expandedHeight; scaledSource.left = 0; scaledSource.right = expandedWidth / samples; int cacheBytes = 32; if ((texture_entry->format & 0x0f) == 6) cacheBytes = 64; int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(texture_entry->format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, (expandedWidth / samples) * 4, expandedHeight, texture_entry->BytesPerRow(), readStride, bScaleByHalf > 0, 1.0f); }