Properly emulate the alpha read pixel engine register function (used for EFB peeks).
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6313 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
b71cd5f383
commit
ab53c84dcf
|
@ -81,17 +81,6 @@ union UPEAlphaModeConfReg
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Not sure about this reg...
|
|
||||||
union UPEAlphaReadReg
|
|
||||||
{
|
|
||||||
u16 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
u16 ReadMode : 3;
|
|
||||||
u16 : 13;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// fifo Control Register
|
// fifo Control Register
|
||||||
union UPECtrlReg
|
union UPECtrlReg
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,6 +54,17 @@ enum
|
||||||
namespace PixelEngine
|
namespace PixelEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// ReadMode specifies the returned alpha channel for EFB peeks
|
||||||
|
union UPEAlphaReadReg
|
||||||
|
{
|
||||||
|
u16 Hex;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 ReadMode : 3;
|
||||||
|
u16 : 13;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "VideoConfig.h"
|
#include "VideoConfig.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
|
#include "PixelEngine.h"
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "OpcodeDecoding.h"
|
#include "OpcodeDecoding.h"
|
||||||
#include "BPStructs.h"
|
#include "BPStructs.h"
|
||||||
|
@ -614,6 +615,20 @@ void Renderer::SetColorMask()
|
||||||
D3D::gfxstate->SetRenderTargetWriteMask(color_mask);
|
D3D::gfxstate->SetRenderTargetWriteMask(color_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function allows the CPU to directly access the EFB.
|
||||||
|
// There are EFB peeks (which will read the color or depth of a pixel)
|
||||||
|
// and EFB pokes (which will change the color or depth of a pixel).
|
||||||
|
//
|
||||||
|
// The behavior of EFB peeks can only be modified by:
|
||||||
|
// - GX_PokeAlphaRead
|
||||||
|
// The behavior of EFB pokes can be modified by:
|
||||||
|
// - GX_PokeAlphaMode (TODO)
|
||||||
|
// - GX_PokeAlphaUpdate (TODO)
|
||||||
|
// - GX_PokeBlendMode (TODO)
|
||||||
|
// - GX_PokeColorUpdate (TODO)
|
||||||
|
// - GX_PokeDither (TODO)
|
||||||
|
// - GX_PokeDstAlpha (TODO)
|
||||||
|
// - GX_PokeZMode (TODO)
|
||||||
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
{
|
{
|
||||||
D3D11_MAPPED_SUBRESOURCE map;
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
|
@ -704,26 +719,20 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
|
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
|
||||||
u32 ret = *(u32*)map.pData;
|
u32 ret = *(u32*)map.pData;
|
||||||
D3D::context->Unmap(read_tex, 0);
|
D3D::context->Unmap(read_tex, 0);
|
||||||
return ret;
|
|
||||||
|
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
||||||
|
PixelEngine::UPEAlphaReadReg alpha_read_mode;
|
||||||
|
PixelEngine::Read16((u16&)alpha_read_mode, PE_DSTALPHACONF);
|
||||||
|
if(alpha_read_mode.ReadMode == 2) return ret; // GX_READ_NONE
|
||||||
|
else if(alpha_read_mode.ReadMode == 1) return (ret | 0xFF000000); // GX_READ_FF
|
||||||
|
else /*if(alpha_read_mode.ReadMode == 0)*/ return (ret & 0x00FFFFFF); // GX_READ_00
|
||||||
}
|
}
|
||||||
else //if(type == POKE_COLOR)
|
else //if(type == POKE_COLOR)
|
||||||
{
|
{
|
||||||
// TODO: Speed this up by batching pokes?
|
|
||||||
// If we're only writing one pixel (native resolution), we can directly copy the data into the target. TODO: Check if this is faster than drawing quads
|
|
||||||
u32 rgbaColor = (poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000);
|
u32 rgbaColor = (poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000);
|
||||||
if(RectToLock.right <= RectToLock.left + 1 && RectToLock.bottom <= RectToLock.top + 1)
|
|
||||||
{
|
|
||||||
D3D::context->Map(g_framebufferManager.GetEFBColorStagingBuffer(), 0, D3D11_MAP_WRITE, 0, &map);
|
|
||||||
*(u32*)map.pData = rgbaColor;
|
|
||||||
D3D::context->Unmap(g_framebufferManager.GetEFBColorStagingBuffer(), 0);
|
|
||||||
|
|
||||||
D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1);
|
// TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
|
||||||
D3D::context->CopySubresourceRegion(g_framebufferManager.GetEFBColorTexture()->GetTex(), 0, RectToLock.left, RectToLock.top, 0, g_framebufferManager.GetEFBColorStagingBuffer(), 0, &box);
|
ResetAPIState();
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ResetAPIState(); // Reset any game specific settings
|
|
||||||
|
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), NULL);
|
||||||
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
||||||
|
@ -735,7 +744,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Called from VertexShaderManager
|
// Called from VertexShaderManager
|
||||||
void UpdateViewport()
|
void UpdateViewport()
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "VideoConfig.h"
|
#include "VideoConfig.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
|
#include "PixelEngine.h"
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "OpcodeDecoding.h"
|
#include "OpcodeDecoding.h"
|
||||||
#include "BPStructs.h"
|
#include "BPStructs.h"
|
||||||
|
@ -691,6 +692,20 @@ void Renderer::SetColorMask()
|
||||||
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask);
|
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function allows the CPU to directly access the EFB.
|
||||||
|
// There are EFB peeks (which will read the color or depth of a pixel)
|
||||||
|
// and EFB pokes (which will change the color or depth of a pixel).
|
||||||
|
//
|
||||||
|
// The behavior of EFB peeks can only be modified by:
|
||||||
|
// - GX_PokeAlphaRead
|
||||||
|
// The behavior of EFB pokes can be modified by:
|
||||||
|
// - GX_PokeAlphaMode (TODO)
|
||||||
|
// - GX_PokeAlphaUpdate (TODO)
|
||||||
|
// - GX_PokeBlendMode (TODO)
|
||||||
|
// - GX_PokeColorUpdate (TODO)
|
||||||
|
// - GX_PokeDither (TODO)
|
||||||
|
// - GX_PokeDstAlpha (TODO)
|
||||||
|
// - GX_PokeZMode (TODO)
|
||||||
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
{
|
{
|
||||||
if (!g_ActiveConfig.bEFBAccessEnable)
|
if (!g_ActiveConfig.bEFBAccessEnable)
|
||||||
|
@ -738,7 +753,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
|
|
||||||
TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc);
|
TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc);
|
||||||
|
|
||||||
u32 z = 0;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
RECT RectToLock;
|
RECT RectToLock;
|
||||||
RectToLock.bottom = targetPixelRc.bottom;
|
RectToLock.bottom = targetPixelRc.bottom;
|
||||||
|
@ -813,6 +827,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY);
|
pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY);
|
||||||
|
|
||||||
float val = 0.0f;
|
float val = 0.0f;
|
||||||
|
u32 z = 0;
|
||||||
|
|
||||||
switch (g_framebufferManager.GetEFBDepthReadSurfaceFormat())
|
switch (g_framebufferManager.GetEFBDepthReadSurfaceFormat())
|
||||||
{
|
{
|
||||||
|
@ -849,9 +864,15 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
D3DLOCKED_RECT drect;
|
D3DLOCKED_RECT drect;
|
||||||
pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY);
|
pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY);
|
||||||
|
|
||||||
z = ((u32*)drect.pBits)[0];
|
u32 ret = ((u32*)drect.pBits)[0];
|
||||||
pSystemBuf->UnlockRect();
|
pSystemBuf->UnlockRect();
|
||||||
return z;
|
|
||||||
|
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
||||||
|
PixelEngine::UPEAlphaReadReg alpha_read_mode;
|
||||||
|
PixelEngine::Read16((u16&)alpha_read_mode, PE_DSTALPHACONF);
|
||||||
|
if(alpha_read_mode.ReadMode == 2) return ret; // GX_READ_NONE
|
||||||
|
else if(alpha_read_mode.ReadMode == 1) return (ret | 0xFF000000); // GX_READ_FF
|
||||||
|
else /*if(alpha_read_mode.ReadMode == 0)*/ return (ret & 0x00FFFFFF); // GX_READ_00
|
||||||
}
|
}
|
||||||
else //if(type == POKE_COLOR)
|
else //if(type == POKE_COLOR)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "Profiler.h"
|
#include "Profiler.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "ImageWrite.h"
|
#include "ImageWrite.h"
|
||||||
|
#include "PixelEngine.h"
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "OpcodeDecoding.h"
|
#include "OpcodeDecoding.h"
|
||||||
#include "BPStructs.h"
|
#include "BPStructs.h"
|
||||||
|
@ -854,6 +855,20 @@ void Renderer::SetColorMask()
|
||||||
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
|
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function allows the CPU to directly access the EFB.
|
||||||
|
// There are EFB peeks (which will read the color or depth of a pixel)
|
||||||
|
// and EFB pokes (which will change the color or depth of a pixel).
|
||||||
|
//
|
||||||
|
// The behavior of EFB peeks can only be modified by:
|
||||||
|
// - GX_PokeAlphaRead
|
||||||
|
// The behavior of EFB pokes can be modified by:
|
||||||
|
// - GX_PokeAlphaMode (TODO)
|
||||||
|
// - GX_PokeAlphaUpdate (TODO)
|
||||||
|
// - GX_PokeBlendMode (TODO)
|
||||||
|
// - GX_PokeColorUpdate (TODO)
|
||||||
|
// - GX_PokeDither (TODO)
|
||||||
|
// - GX_PokeDstAlpha (TODO)
|
||||||
|
// - GX_PokeZMode (TODO)
|
||||||
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
{
|
{
|
||||||
if (!g_ActiveConfig.bEFBAccessEnable)
|
if (!g_ActiveConfig.bEFBAccessEnable)
|
||||||
|
@ -922,7 +937,12 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
glReadPixels(srcX, srcY, 1, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &color);
|
glReadPixels(srcX, srcY, 1, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &color);
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
return color;
|
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
||||||
|
PixelEngine::UPEAlphaReadReg alpha_read_mode;
|
||||||
|
PixelEngine::Read16((u16&)alpha_read_mode, PE_DSTALPHACONF);
|
||||||
|
if(alpha_read_mode.ReadMode == 2) return color; // GX_READ_NONE
|
||||||
|
else if(alpha_read_mode.ReadMode == 1) return (color | 0xFF000000); // GX_READ_FF
|
||||||
|
else /*if(alpha_read_mode.ReadMode == 0)*/ return (color & 0x00FFFFFF); // GX_READ_00
|
||||||
}
|
}
|
||||||
|
|
||||||
case POKE_COLOR:
|
case POKE_COLOR:
|
||||||
|
|
Loading…
Reference in New Issue