summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorNeoBrainX <NeoBrainX@googlemail.com>2010-10-24 19:52:52 +0000
committerNeoBrainX <NeoBrainX@googlemail.com>2010-10-24 19:52:52 +0000
commitab53c84dcf7fa791c778a868866dd006e5dfa50d (patch)
tree962b9fc5c33d87ae2a17b81829abb80574830233 /Source
parentb71cd5f3832b3b426d71af84f6c6baffeea193ef (diff)
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
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.cpp11
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.h11
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/Render.cpp54
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Render.cpp27
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.cpp22
5 files changed, 87 insertions, 38 deletions
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp
index 2785d66826..580571b328 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp
@@ -81,17 +81,6 @@ union UPEAlphaModeConfReg
};
};
-// Not sure about this reg...
-union UPEAlphaReadReg
-{
- u16 Hex;
- struct
- {
- u16 ReadMode : 3;
- u16 : 13;
- };
-};
-
// fifo Control Register
union UPECtrlReg
{
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h
index 5b773c6c9b..84b30a1bb5 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.h
+++ b/Source/Core/VideoCommon/Src/PixelEngine.h
@@ -54,6 +54,17 @@ enum
namespace PixelEngine
{
+// ReadMode specifies the returned alpha channel for EFB peeks
+union UPEAlphaReadReg
+{
+ u16 Hex;
+ struct
+ {
+ u16 ReadMode : 3;
+ u16 : 13;
+ };
+};
+
void Init();
void DoState(PointerWrap &p);
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
index 3f5025baa8..97055dedf4 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
@@ -28,6 +28,7 @@
#include "VideoConfig.h"
#include "main.h"
#include "VertexManager.h"
+#include "PixelEngine.h"
#include "Render.h"
#include "OpcodeDecoding.h"
#include "BPStructs.h"
@@ -614,6 +615,20 @@ void Renderer::SetColorMask()
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)
{
D3D11_MAPPED_SUBRESOURCE map;
@@ -704,36 +719,29 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
u32 ret = *(u32*)map.pData;
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)
{
- // 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);
- 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);
- D3D::context->CopySubresourceRegion(g_framebufferManager.GetEFBColorTexture()->GetTex(), 0, RectToLock.left, RectToLock.top, 0, g_framebufferManager.GetEFBColorStagingBuffer(), 0, &box);
- return 0;
- }
- else
- {
- ResetAPIState(); // Reset any game specific settings
+ // TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
+ ResetAPIState();
- D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), NULL);
- D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
- - (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
- (float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
- - (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f);
+ D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), NULL);
+ D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
+ - (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
+ (float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
+ - (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f);
- RestoreAPIState();
- return 0;
- }
+ RestoreAPIState();
+ return 0;
}
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
index 050bdfd7f1..96795e81fe 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
@@ -30,6 +30,7 @@
#include "VideoConfig.h"
#include "main.h"
#include "VertexManager.h"
+#include "PixelEngine.h"
#include "Render.h"
#include "OpcodeDecoding.h"
#include "BPStructs.h"
@@ -691,6 +692,20 @@ void Renderer::SetColorMask()
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)
{
if (!g_ActiveConfig.bEFBAccessEnable)
@@ -738,7 +753,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc);
- u32 z = 0;
HRESULT hr;
RECT RectToLock;
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);
float val = 0.0f;
+ u32 z = 0;
switch (g_framebufferManager.GetEFBDepthReadSurfaceFormat())
{
@@ -849,9 +864,15 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
D3DLOCKED_RECT drect;
pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY);
- z = ((u32*)drect.pBits)[0];
+ u32 ret = ((u32*)drect.pBits)[0];
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)
{
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
index 3f51031597..d4dede65d7 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
@@ -36,6 +36,7 @@
#include "Profiler.h"
#include "Statistics.h"
#include "ImageWrite.h"
+#include "PixelEngine.h"
#include "Render.h"
#include "OpcodeDecoding.h"
#include "BPStructs.h"
@@ -854,6 +855,20 @@ void Renderer::SetColorMask()
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)
{
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);
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: