mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added SpriteTexCoord setting
This commit is contained in:
parent
8905f421cf
commit
19985f294e
@ -12,6 +12,7 @@ namespace Config
|
|||||||
Settings::DisplayResolution displayResolution;
|
Settings::DisplayResolution displayResolution;
|
||||||
Settings::RenderColorDepth renderColorDepth;
|
Settings::RenderColorDepth renderColorDepth;
|
||||||
Settings::ResolutionScale resolutionScale;
|
Settings::ResolutionScale resolutionScale;
|
||||||
|
Settings::SpriteTexCoord spriteTexCoord;
|
||||||
Settings::SupportedResolutions supportedResolutions;
|
Settings::SupportedResolutions supportedResolutions;
|
||||||
Settings::TextureFilter textureFilter;
|
Settings::TextureFilter textureFilter;
|
||||||
Settings::ThreadPriorityBoost threadPriorityBoost;
|
Settings::ThreadPriorityBoost threadPriorityBoost;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <Config/Settings/DisplayResolution.h>
|
#include <Config/Settings/DisplayResolution.h>
|
||||||
#include <Config/Settings/RenderColorDepth.h>
|
#include <Config/Settings/RenderColorDepth.h>
|
||||||
#include <Config/Settings/ResolutionScale.h>
|
#include <Config/Settings/ResolutionScale.h>
|
||||||
|
#include <Config/Settings/SpriteTexCoord.h>
|
||||||
#include <Config/Settings/SupportedResolutions.h>
|
#include <Config/Settings/SupportedResolutions.h>
|
||||||
#include <Config/Settings/TextureFilter.h>
|
#include <Config/Settings/TextureFilter.h>
|
||||||
#include <Config/Settings/ThreadPriorityBoost.h>
|
#include <Config/Settings/ThreadPriorityBoost.h>
|
||||||
@ -29,6 +30,7 @@ namespace Config
|
|||||||
extern Settings::DisplayResolution displayResolution;
|
extern Settings::DisplayResolution displayResolution;
|
||||||
extern Settings::RenderColorDepth renderColorDepth;
|
extern Settings::RenderColorDepth renderColorDepth;
|
||||||
extern Settings::ResolutionScale resolutionScale;
|
extern Settings::ResolutionScale resolutionScale;
|
||||||
|
extern Settings::SpriteTexCoord spriteTexCoord;
|
||||||
extern Settings::SupportedResolutions supportedResolutions;
|
extern Settings::SupportedResolutions supportedResolutions;
|
||||||
extern Settings::TextureFilter textureFilter;
|
extern Settings::TextureFilter textureFilter;
|
||||||
extern Settings::ThreadPriorityBoost threadPriorityBoost;
|
extern Settings::ThreadPriorityBoost threadPriorityBoost;
|
||||||
|
25
DDrawCompat/Config/Settings/SpriteTexCoord.cpp
Normal file
25
DDrawCompat/Config/Settings/SpriteTexCoord.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include <Config/Settings/SpriteTexCoord.h>
|
||||||
|
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
namespace Settings
|
||||||
|
{
|
||||||
|
SpriteTexCoord::SpriteTexCoord()
|
||||||
|
: MappedSetting("SpriteTexCoord", "app", {
|
||||||
|
{"app", APP},
|
||||||
|
{"clamp", CLAMP},
|
||||||
|
{"clampall", CLAMPALL},
|
||||||
|
{"round", ROUND}})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting::ParamInfo SpriteTexCoord::getParamInfo() const
|
||||||
|
{
|
||||||
|
if (ROUND == m_value)
|
||||||
|
{
|
||||||
|
return { "Offset", -50, 50, 0, m_param };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
DDrawCompat/Config/Settings/SpriteTexCoord.h
Normal file
22
DDrawCompat/Config/Settings/SpriteTexCoord.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Config/MappedSetting.h>
|
||||||
|
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
namespace Settings
|
||||||
|
{
|
||||||
|
class SpriteTexCoord : public MappedSetting<UINT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const UINT APP = 0;
|
||||||
|
static const UINT CLAMP = 1;
|
||||||
|
static const UINT CLAMPALL = 2;
|
||||||
|
static const UINT ROUND = 3;
|
||||||
|
|
||||||
|
SpriteTexCoord();
|
||||||
|
|
||||||
|
virtual ParamInfo getParamInfo() const override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -242,7 +242,13 @@ namespace D3dDdi
|
|||||||
HRESULT result = m_origVtable.pfnDestroyResource(m_device, resource);
|
HRESULT result = m_origVtable.pfnDestroyResource(m_device, resource);
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
m_resources.erase(resource);
|
auto it = m_resources.find(resource);
|
||||||
|
Resource* res = nullptr;
|
||||||
|
if (it != m_resources.end())
|
||||||
|
{
|
||||||
|
res = it->second.get();
|
||||||
|
m_resources.erase(it);
|
||||||
|
}
|
||||||
if (resource == m_sharedPrimary)
|
if (resource == m_sharedPrimary)
|
||||||
{
|
{
|
||||||
m_sharedPrimary = nullptr;
|
m_sharedPrimary = nullptr;
|
||||||
@ -253,7 +259,7 @@ namespace D3dDdi
|
|||||||
g_gdiResource = nullptr;
|
g_gdiResource = nullptr;
|
||||||
}
|
}
|
||||||
m_drawPrimitive.removeSysMemVertexBuffer(resource);
|
m_drawPrimitive.removeSysMemVertexBuffer(resource);
|
||||||
m_state.onDestroyResource(resource);
|
m_state.onDestroyResource(res, resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -14,34 +14,6 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const HANDLE DELETED_RESOURCE = reinterpret_cast<HANDLE>(0xBAADBAAD);
|
const HANDLE DELETED_RESOURCE = reinterpret_cast<HANDLE>(0xBAADBAAD);
|
||||||
|
|
||||||
UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value)
|
|
||||||
{
|
|
||||||
if (state >= D3DDDIRS_WRAP0 && state <= D3DDDIRS_WRAP7)
|
|
||||||
{
|
|
||||||
return value & (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2 | D3DWRAPCOORD_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT mapTssValue(D3DDDITEXTURESTAGESTATETYPE type, UINT value)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case D3DDDITSS_MAGFILTER:
|
|
||||||
case D3DDDITSS_MINFILTER:
|
|
||||||
return D3DTEXF_NONE == Config::textureFilter.getFilter() ? value : Config::textureFilter.getFilter();
|
|
||||||
|
|
||||||
case D3DDDITSS_MIPFILTER:
|
|
||||||
return D3DTEXF_NONE == Config::textureFilter.getMipFilter() ? value : Config::textureFilter.getMipFilter();
|
|
||||||
|
|
||||||
case D3DDDITSS_MAXANISOTROPY:
|
|
||||||
return D3DTEXF_NONE == Config::textureFilter.getFilter() ? value : Config::textureFilter.getMaxAnisotropy();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
@ -74,6 +46,9 @@ namespace D3dDdi
|
|||||||
, m_maxChangedTextureStage(0)
|
, m_maxChangedTextureStage(0)
|
||||||
, m_changedTextureStageStates{}
|
, m_changedTextureStageStates{}
|
||||||
, m_vsVertexFixup(createVertexShader(g_vsVertexFixup))
|
, m_vsVertexFixup(createVertexShader(g_vsVertexFixup))
|
||||||
|
, m_textureResource{}
|
||||||
|
, m_isLocked(false)
|
||||||
|
, m_spriteMode(false)
|
||||||
{
|
{
|
||||||
const UINT D3DBLENDOP_ADD = 1;
|
const UINT D3DBLENDOP_ADD = 1;
|
||||||
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
|
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
|
||||||
@ -167,6 +142,12 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
m_current.textureStageState[i].fill(UNINITIALIZED_STATE);
|
m_current.textureStageState[i].fill(UNINITIALIZED_STATE);
|
||||||
m_current.textureStageState[i][D3DDDITSS_TEXCOORDINDEX] = i;
|
m_current.textureStageState[i][D3DDDITSS_TEXCOORDINDEX] = i;
|
||||||
|
|
||||||
|
// When ADDRESSU or ADDRESSV is set to CLAMP, their value is overridden by D3DTSS_ADDRESS.
|
||||||
|
// Setting this to CLAMP makes them behave as expected, instead of as WRAP,
|
||||||
|
// which would be the default init value set by the runtime.
|
||||||
|
m_current.textureStageState[i][D3DTSS_ADDRESS] = D3DTADDRESS_CLAMP;
|
||||||
|
|
||||||
m_current.textureStageState[i][D3DDDITSS_ADDRESSU] = D3DTADDRESS_WRAP;
|
m_current.textureStageState[i][D3DDDITSS_ADDRESSU] = D3DTADDRESS_WRAP;
|
||||||
m_current.textureStageState[i][D3DDDITSS_ADDRESSV] = D3DTADDRESS_WRAP;
|
m_current.textureStageState[i][D3DDDITSS_ADDRESSV] = D3DTADDRESS_WRAP;
|
||||||
m_current.textureStageState[i][D3DDDITSS_BORDERCOLOR] = 0;
|
m_current.textureStageState[i][D3DDDITSS_BORDERCOLOR] = 0;
|
||||||
@ -232,9 +213,19 @@ namespace D3dDdi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceState::disableTextureClamp(UINT stage)
|
||||||
|
{
|
||||||
|
auto resource = getTextureResource(stage);
|
||||||
|
resource->disableClamp();
|
||||||
|
m_changedStates |= CS_TEXTURE_STAGE;
|
||||||
|
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSU);
|
||||||
|
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSV);
|
||||||
|
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceState::flush()
|
void DeviceState::flush()
|
||||||
{
|
{
|
||||||
if (0 == m_changedStates)
|
if (0 == m_changedStates || m_isLocked)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -264,25 +255,96 @@ namespace D3dDdi
|
|||||||
m_maxChangedTextureStage = 0;
|
m_maxChangedTextureStage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceState::onDestroyResource(HANDLE resource)
|
Resource* DeviceState::getTextureResource(UINT stage)
|
||||||
|
{
|
||||||
|
if (!m_textureResource[stage] || *m_textureResource[stage] != m_app.textures[stage])
|
||||||
|
{
|
||||||
|
m_textureResource[stage] = m_device.getResource(m_app.textures[stage]);
|
||||||
|
}
|
||||||
|
return m_textureResource[stage];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeviceState::VertexDecl& DeviceState::getVertexDecl() const
|
||||||
|
{
|
||||||
|
static const VertexDecl emptyDecl = {};
|
||||||
|
auto it = m_vertexShaderDecls.find(m_app.vertexShaderDecl);
|
||||||
|
return it != m_vertexShaderDecls.end() ? it->second : emptyDecl;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT DeviceState::mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value)
|
||||||
|
{
|
||||||
|
if (state >= D3DDDIRS_WRAP0 && state <= D3DDDIRS_WRAP7)
|
||||||
|
{
|
||||||
|
return value & (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2 | D3DWRAPCOORD_3);
|
||||||
|
}
|
||||||
|
if (D3DDDIRS_MULTISAMPLEANTIALIAS == state)
|
||||||
|
{
|
||||||
|
return 0 != value && !m_spriteMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT DeviceState::mapTssValue(UINT stage, D3DDDITEXTURESTAGESTATETYPE state, UINT value)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case D3DDDITSS_ADDRESSU:
|
||||||
|
case D3DDDITSS_ADDRESSV:
|
||||||
|
if (m_spriteMode && D3DTADDRESS_CLAMP != value)
|
||||||
|
{
|
||||||
|
if (Config::Settings::SpriteTexCoord::CLAMP == Config::spriteTexCoord.get())
|
||||||
|
{
|
||||||
|
auto resource = getTextureResource(stage);
|
||||||
|
if (resource && resource->isClampable())
|
||||||
|
{
|
||||||
|
return D3DTADDRESS_CLAMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Config::Settings::SpriteTexCoord::CLAMPALL == Config::spriteTexCoord.get())
|
||||||
|
{
|
||||||
|
return D3DTADDRESS_CLAMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
|
||||||
|
case D3DDDITSS_MAGFILTER:
|
||||||
|
case D3DDDITSS_MINFILTER:
|
||||||
|
return D3DTEXF_NONE == Config::textureFilter.getFilter() ? value : Config::textureFilter.getFilter();
|
||||||
|
|
||||||
|
case D3DDDITSS_MIPFILTER:
|
||||||
|
return D3DTEXF_NONE == Config::textureFilter.getMipFilter() ? value : Config::textureFilter.getMipFilter();
|
||||||
|
|
||||||
|
case D3DDDITSS_MAXANISOTROPY:
|
||||||
|
return D3DTEXF_NONE == Config::textureFilter.getFilter() ? value : Config::textureFilter.getMaxAnisotropy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceState::onDestroyResource(D3dDdi::Resource* resource, HANDLE resourceHandle)
|
||||||
{
|
{
|
||||||
for (UINT i = 0; i < m_current.textures.size(); ++i)
|
for (UINT i = 0; i < m_current.textures.size(); ++i)
|
||||||
{
|
{
|
||||||
if (m_current.textures[i] == resource)
|
if (m_current.textures[i] == resourceHandle)
|
||||||
{
|
{
|
||||||
m_current.textures[i] = DELETED_RESOURCE;
|
m_current.textures[i] = DELETED_RESOURCE;
|
||||||
}
|
}
|
||||||
if (m_app.textures[i] == resource)
|
if (m_app.textures[i] == resourceHandle)
|
||||||
{
|
{
|
||||||
pfnSetTexture(i, nullptr);
|
pfnSetTexture(i, nullptr);
|
||||||
}
|
}
|
||||||
|
if (m_textureResource[i] == resource)
|
||||||
|
{
|
||||||
|
m_textureResource[i] = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeResource(resource, &State::renderTarget, &D3DDDIARG_SETRENDERTARGET::hRenderTarget,
|
removeResource(resourceHandle, &State::renderTarget, &D3DDDIARG_SETRENDERTARGET::hRenderTarget,
|
||||||
&DeviceState::pfnSetRenderTarget);
|
&DeviceState::pfnSetRenderTarget);
|
||||||
removeResource(resource, &State::depthStencil, &D3DDDIARG_SETDEPTHSTENCIL::hZBuffer,
|
removeResource(resourceHandle, &State::depthStencil, &D3DDDIARG_SETDEPTHSTENCIL::hZBuffer,
|
||||||
&DeviceState::pfnSetDepthStencil);
|
&DeviceState::pfnSetDepthStencil);
|
||||||
removeResource(resource, &State::streamSource, &D3DDDIARG_SETSTREAMSOURCE::hVertexBuffer,
|
removeResource(resourceHandle, &State::streamSource, &D3DDDIARG_SETSTREAMSOURCE::hVertexBuffer,
|
||||||
&DeviceState::pfnSetStreamSource);
|
&DeviceState::pfnSetStreamSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,22 +355,37 @@ namespace D3dDdi
|
|||||||
LOG_DEBUG << Compat::array(vertexElements, data->NumVertexElements);
|
LOG_DEBUG << Compat::array(vertexElements, data->NumVertexElements);
|
||||||
|
|
||||||
const UINT D3DDECLUSAGE_POSITION = 0;
|
const UINT D3DDECLUSAGE_POSITION = 0;
|
||||||
|
const UINT D3DDECLUSAGE_TEXCOORD = 5;
|
||||||
const UINT D3DDECLUSAGE_POSITIONT = 9;
|
const UINT D3DDECLUSAGE_POSITIONT = 9;
|
||||||
|
|
||||||
|
std::vector<D3DDDIVERTEXELEMENT> ve(vertexElements, vertexElements + data->NumVertexElements);
|
||||||
|
VertexDecl decl = {};
|
||||||
|
decl.elements = ve;
|
||||||
|
|
||||||
for (UINT i = 0; i < data->NumVertexElements; ++i)
|
for (UINT i = 0; i < data->NumVertexElements; ++i)
|
||||||
{
|
{
|
||||||
if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage)
|
if (D3DDECLUSAGE_TEXCOORD == vertexElements[i].Usage)
|
||||||
{
|
{
|
||||||
std::vector<D3DDDIVERTEXELEMENT> ve(vertexElements, vertexElements + data->NumVertexElements);
|
decl.texCoordOffset[vertexElements[i].UsageIndex] = vertexElements[i].Offset;
|
||||||
ve[i].Usage = D3DDECLUSAGE_POSITION;
|
decl.texCoordType[vertexElements[i].UsageIndex] = vertexElements[i].Type;
|
||||||
HRESULT result = m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, ve.data());
|
if (vertexElements[i].UsageIndex >= decl.textureStageCount)
|
||||||
if (SUCCEEDED(result))
|
|
||||||
{
|
{
|
||||||
m_swVertexShaderDecls.insert(data->ShaderHandle);
|
decl.textureStageCount = vertexElements[i].UsageIndex + 1;
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
else if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage)
|
||||||
|
{
|
||||||
|
ve[i].Usage = D3DDECLUSAGE_POSITION;
|
||||||
|
decl.isTransformed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, vertexElements);
|
|
||||||
|
HRESULT result = m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, ve.data());
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
m_vertexShaderDecls[data->ShaderHandle] = decl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT DeviceState::pfnDeletePixelShader(HANDLE shader)
|
HRESULT DeviceState::pfnDeletePixelShader(HANDLE shader)
|
||||||
@ -321,7 +398,7 @@ namespace D3dDdi
|
|||||||
HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl);
|
HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl);
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
m_swVertexShaderDecls.erase(shader);
|
m_vertexShaderDecls.erase(shader);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -397,16 +474,29 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
m_app.textures[stage] = texture;
|
m_app.textures[stage] = texture;
|
||||||
m_changedStates |= CS_TEXTURE_STAGE;
|
m_changedStates |= CS_TEXTURE_STAGE;
|
||||||
|
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSU);
|
||||||
|
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSV);
|
||||||
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
|
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT DeviceState::pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data)
|
HRESULT DeviceState::pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data)
|
||||||
{
|
{
|
||||||
|
if (D3DTSS_ADDRESS == data->State)
|
||||||
|
{
|
||||||
|
m_app.textureStageState[data->Stage][D3DDDITSS_ADDRESSU] = data->Value;
|
||||||
|
m_app.textureStageState[data->Stage][D3DDDITSS_ADDRESSV] = data->Value;
|
||||||
|
m_changedTextureStageStates[data->Stage].set(D3DDDITSS_ADDRESSU);
|
||||||
|
m_changedTextureStageStates[data->Stage].set(D3DDDITSS_ADDRESSV);
|
||||||
|
m_maxChangedTextureStage = max(data->Stage, m_maxChangedTextureStage);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (D3DDDITSS_TEXTURECOLORKEYVAL == data->State)
|
if (D3DDDITSS_TEXTURECOLORKEYVAL == data->State)
|
||||||
{
|
{
|
||||||
m_app.textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = FALSE;
|
m_app.textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_app.textureStageState[data->Stage][data->State] = data->Value;
|
m_app.textureStageState[data->Stage][data->State] = data->Value;
|
||||||
m_changedTextureStageStates[data->Stage].set(data->State);
|
m_changedTextureStageStates[data->Stage].set(data->State);
|
||||||
m_maxChangedTextureStage = max(data->Stage, m_maxChangedTextureStage);
|
m_maxChangedTextureStage = max(data->Stage, m_maxChangedTextureStage);
|
||||||
@ -544,6 +634,27 @@ namespace D3dDdi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceState::setSpriteMode(bool spriteMode)
|
||||||
|
{
|
||||||
|
if (spriteMode != m_spriteMode)
|
||||||
|
{
|
||||||
|
m_spriteMode = spriteMode;
|
||||||
|
m_changedStates |= CS_RENDER_STATE | CS_TEXTURE_STAGE;
|
||||||
|
m_changedRenderStates.set(D3DDDIRS_MULTISAMPLEANTIALIAS);
|
||||||
|
if (Config::Settings::SpriteTexCoord::ROUND == Config::spriteTexCoord.get())
|
||||||
|
{
|
||||||
|
m_changedTextureStageStates[0].set(D3DDDITSS_ADDRESSU);
|
||||||
|
m_changedTextureStageStates[0].set(D3DDDITSS_ADDRESSV);
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DDDIARG_SETVERTEXSHADERCONSTB data = {};
|
||||||
|
data.Register = 15;
|
||||||
|
data.Count = 1;
|
||||||
|
BOOL value = spriteMode && Config::Settings::SpriteTexCoord::ROUND == Config::spriteTexCoord.get();
|
||||||
|
pfnSetVertexShaderConstB(&data, &value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceState::setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource)
|
void DeviceState::setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource)
|
||||||
{
|
{
|
||||||
if (0 == memcmp(&streamSource, &m_current.streamSource, sizeof(streamSource)))
|
if (0 == memcmp(&streamSource, &m_current.streamSource, sizeof(streamSource)))
|
||||||
@ -673,6 +784,27 @@ namespace D3dDdi
|
|||||||
m_device.flushPrimitives();
|
m_device.flushPrimitives();
|
||||||
m_device.getOrigVtable().pfnSetTexture(m_device, stage, texture);
|
m_device.getOrigVtable().pfnSetTexture(m_device, stage, texture);
|
||||||
m_current.textures[stage] = texture;
|
m_current.textures[stage] = texture;
|
||||||
|
|
||||||
|
if (0 == stage && texture)
|
||||||
|
{
|
||||||
|
auto resource = (texture == m_app.textures[stage]) ? getTextureResource(stage) : m_device.getResource(texture);
|
||||||
|
if (resource)
|
||||||
|
{
|
||||||
|
D3DDDIARG_SETVERTEXSHADERCONST data = {};
|
||||||
|
data.Register = 253;
|
||||||
|
data.Count = 1;
|
||||||
|
|
||||||
|
auto& si = resource->getFixedDesc().pSurfList[0];
|
||||||
|
ShaderConstF reg = { static_cast<float>(si.Width), static_cast<float>(si.Height),
|
||||||
|
m_vertexShaderConst[253][2], m_vertexShaderConst[253][3] };
|
||||||
|
|
||||||
|
if (0 != memcmp(®, &m_vertexShaderConst[data.Register], sizeof(reg)))
|
||||||
|
{
|
||||||
|
pfnSetVertexShaderConst(&data, ®);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DS << stage << " " << texture;
|
LOG_DS << stage << " " << texture;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -750,7 +882,8 @@ namespace D3dDdi
|
|||||||
|
|
||||||
void DeviceState::updateConfig()
|
void DeviceState::updateConfig()
|
||||||
{
|
{
|
||||||
m_changedStates |= CS_RENDER_TARGET | CS_TEXTURE_STAGE;
|
m_changedStates |= CS_RENDER_STATE | CS_RENDER_TARGET | CS_TEXTURE_STAGE;
|
||||||
|
m_changedRenderStates.set(D3DDDIRS_MULTISAMPLEANTIALIAS);
|
||||||
for (UINT i = 0; i < m_changedTextureStageStates.size(); ++i)
|
for (UINT i = 0; i < m_changedTextureStageStates.size(); ++i)
|
||||||
{
|
{
|
||||||
m_changedTextureStageStates[i].set(D3DDDITSS_MINFILTER);
|
m_changedTextureStageStates[i].set(D3DDDITSS_MINFILTER);
|
||||||
@ -758,6 +891,8 @@ namespace D3dDdi
|
|||||||
m_changedTextureStageStates[i].set(D3DDDITSS_MIPFILTER);
|
m_changedTextureStageStates[i].set(D3DDDITSS_MIPFILTER);
|
||||||
m_changedTextureStageStates[i].set(D3DDDITSS_MAXANISOTROPY);
|
m_changedTextureStageStates[i].set(D3DDDITSS_MAXANISOTROPY);
|
||||||
}
|
}
|
||||||
|
m_changedTextureStageStates[0].set(D3DDDITSS_ADDRESSU);
|
||||||
|
m_changedTextureStageStates[0].set(D3DDDITSS_ADDRESSV);
|
||||||
m_maxChangedTextureStage = m_changedTextureStageStates.size() - 1;
|
m_maxChangedTextureStage = m_changedTextureStageStates.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +948,8 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
setPixelShader(m_app.pixelShader);
|
setPixelShader(m_app.pixelShader);
|
||||||
setVertexShaderDecl(m_app.vertexShaderDecl);
|
setVertexShaderDecl(m_app.vertexShaderDecl);
|
||||||
if (m_swVertexShaderDecls.find(m_current.vertexShaderDecl) != m_swVertexShaderDecls.end())
|
auto it = m_vertexShaderDecls.find(m_app.vertexShaderDecl);
|
||||||
|
if (it != m_vertexShaderDecls.end() && it->second.isTransformed)
|
||||||
{
|
{
|
||||||
setVertexShaderFunc(m_vsVertexFixup.get());
|
setVertexShaderFunc(m_vsVertexFixup.get());
|
||||||
}
|
}
|
||||||
@ -885,7 +1021,7 @@ namespace D3dDdi
|
|||||||
m_changedTextureStageStates[stage].forEach([&](UINT stateIndex)
|
m_changedTextureStageStates[stage].forEach([&](UINT stateIndex)
|
||||||
{
|
{
|
||||||
const auto state = static_cast<D3DDDITEXTURESTAGESTATETYPE>(stateIndex);
|
const auto state = static_cast<D3DDDITEXTURESTAGESTATETYPE>(stateIndex);
|
||||||
setTextureStageState({ stage, state, mapTssValue(state, m_app.textureStageState[stage][state]) });
|
setTextureStageState({ stage, state, mapTssValue(stage, state, m_app.textureStageState[stage][state]) });
|
||||||
});
|
});
|
||||||
m_changedTextureStageStates[stage].reset();
|
m_changedTextureStageStates[stage].reset();
|
||||||
}
|
}
|
||||||
@ -894,16 +1030,18 @@ namespace D3dDdi
|
|||||||
void DeviceState::updateVertexFixupConstants()
|
void DeviceState::updateVertexFixupConstants()
|
||||||
{
|
{
|
||||||
D3DDDIARG_SETVERTEXSHADERCONST data = {};
|
D3DDDIARG_SETVERTEXSHADERCONST data = {};
|
||||||
data.Register = 254;
|
data.Register = 253;
|
||||||
data.Count = 2;
|
data.Count = 3;
|
||||||
|
|
||||||
|
const float stc = static_cast<float>(Config::spriteTexCoord.getParam()) / 100;
|
||||||
const float apc = Config::alternatePixelCenter.get();
|
const float apc = Config::alternatePixelCenter.get();
|
||||||
const auto& vp = m_app.viewport;
|
const auto& vp = m_app.viewport;
|
||||||
const auto& zr = m_current.zRange;
|
const auto& zr = m_current.zRange;
|
||||||
const float sx = static_cast<float>(m_current.viewport.Width) / m_app.viewport.Width;
|
const float sx = static_cast<float>(m_current.viewport.Width) / m_app.viewport.Width;
|
||||||
const float sy = static_cast<float>(m_current.viewport.Height) / m_app.viewport.Height;
|
const float sy = static_cast<float>(m_current.viewport.Height) / m_app.viewport.Height;
|
||||||
|
|
||||||
ShaderConstF registers[2] = {
|
ShaderConstF registers[3] = {
|
||||||
|
{ m_vertexShaderConst[253][0], m_vertexShaderConst[253][1], stc, stc },
|
||||||
{ 0.5f + apc - 0.5f / sx - vp.X - vp.Width / 2, 0.5f + apc - 0.5f / sy - vp.Y - vp.Height / 2, -zr.MinZ, 0.0f },
|
{ 0.5f + apc - 0.5f / sx - vp.X - vp.Width / 2, 0.5f + apc - 0.5f / sy - vp.Y - vp.Height / 2, -zr.MinZ, 0.0f },
|
||||||
{ 2.0f / vp.Width, -2.0f / vp.Height, 1.0f / (zr.MaxZ - zr.MinZ), 1.0f }
|
{ 2.0f / vp.Width, -2.0f / vp.Height, 1.0f / (zr.MaxZ - zr.MinZ), 1.0f }
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <d3dumddi.h>
|
#include <d3dumddi.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <set>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ const UINT D3DTEXF_ANISOTROPIC = 3;
|
|||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
{
|
{
|
||||||
class Device;
|
class Device;
|
||||||
|
class Resource;
|
||||||
|
|
||||||
class DeviceState
|
class DeviceState
|
||||||
{
|
{
|
||||||
@ -27,6 +28,24 @@ namespace D3dDdi
|
|||||||
typedef std::array<FLOAT, 4> ShaderConstF;
|
typedef std::array<FLOAT, 4> ShaderConstF;
|
||||||
typedef std::array<INT, 4> ShaderConstI;
|
typedef std::array<INT, 4> ShaderConstI;
|
||||||
|
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
D3DDDIARG_SETDEPTHSTENCIL depthStencil;
|
||||||
|
HANDLE pixelShader;
|
||||||
|
std::array<UINT, D3DDDIRS_BLENDOPALPHA + 1> renderState;
|
||||||
|
D3DDDIARG_SETRENDERTARGET renderTarget;
|
||||||
|
D3DDDIARG_SETSTREAMSOURCE streamSource;
|
||||||
|
D3DDDIARG_SETSTREAMSOURCEUM streamSourceUm;
|
||||||
|
const void* streamSourceUmBuffer;
|
||||||
|
std::array<HANDLE, 8> textures;
|
||||||
|
std::array<std::array<UINT, D3DDDITSS_TEXTURECOLORKEYVAL + 1>, 8> textureStageState;
|
||||||
|
HANDLE vertexShaderDecl;
|
||||||
|
HANDLE vertexShaderFunc;
|
||||||
|
D3DDDIARG_VIEWPORTINFO viewport;
|
||||||
|
D3DDDIARG_WINFO wInfo;
|
||||||
|
D3DDDIARG_ZRANGE zRange;
|
||||||
|
};
|
||||||
|
|
||||||
class TempPixelShaderConst
|
class TempPixelShaderConst
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -43,19 +62,26 @@ namespace D3dDdi
|
|||||||
public:
|
public:
|
||||||
TempStateLock(DeviceState& state)
|
TempStateLock(DeviceState& state)
|
||||||
: m_state(state)
|
: m_state(state)
|
||||||
, m_prevChangedStates(state.m_changedStates)
|
|
||||||
{
|
{
|
||||||
state.m_changedStates = 0;
|
state.m_isLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
~TempStateLock()
|
~TempStateLock()
|
||||||
{
|
{
|
||||||
m_state.m_changedStates = m_prevChangedStates;
|
m_state.m_isLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceState& m_state;
|
DeviceState& m_state;
|
||||||
UINT m_prevChangedStates;
|
};
|
||||||
|
|
||||||
|
struct VertexDecl
|
||||||
|
{
|
||||||
|
std::vector<D3DDDIVERTEXELEMENT> elements;
|
||||||
|
std::array<UINT, 8> texCoordOffset;
|
||||||
|
std::array<UINT, 8> texCoordType;
|
||||||
|
UINT textureStageCount;
|
||||||
|
bool isTransformed;
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceState(Device& device);
|
DeviceState(Device& device);
|
||||||
@ -84,6 +110,7 @@ namespace D3dDdi
|
|||||||
HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data);
|
HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data);
|
||||||
HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data);
|
HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data);
|
||||||
|
|
||||||
|
void setSpriteMode(bool spriteMode);
|
||||||
void setTempDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL& depthStencil);
|
void setTempDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL& depthStencil);
|
||||||
void setTempPixelShader(HANDLE shader);
|
void setTempPixelShader(HANDLE shader);
|
||||||
void setTempRenderState(const D3DDDIARG_RENDERSTATE& renderState);
|
void setTempRenderState(const D3DDDIARG_RENDERSTATE& renderState);
|
||||||
@ -97,10 +124,16 @@ namespace D3dDdi
|
|||||||
void setTempWInfo(const D3DDDIARG_WINFO& wInfo);
|
void setTempWInfo(const D3DDDIARG_WINFO& wInfo);
|
||||||
void setTempZRange(const D3DDDIARG_ZRANGE& zRange);
|
void setTempZRange(const D3DDDIARG_ZRANGE& zRange);
|
||||||
|
|
||||||
|
void disableTextureClamp(UINT stage);
|
||||||
void flush();
|
void flush();
|
||||||
|
const State& getAppState() const { return m_app; }
|
||||||
|
Resource* getTextureResource(UINT stage);
|
||||||
|
const VertexDecl& getVertexDecl() const;
|
||||||
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
|
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
|
||||||
void onDestroyResource(HANDLE resource);
|
bool isLocked() const { return m_isLocked; }
|
||||||
|
void onDestroyResource(D3dDdi::Resource* resource, HANDLE resourceHandle);
|
||||||
void updateConfig();
|
void updateConfig();
|
||||||
|
void updateStreamSource();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ScopedDeviceState;
|
friend class ScopedDeviceState;
|
||||||
@ -114,24 +147,6 @@ namespace D3dDdi
|
|||||||
CS_TEXTURE_STAGE = 1 << 4
|
CS_TEXTURE_STAGE = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State
|
|
||||||
{
|
|
||||||
D3DDDIARG_SETDEPTHSTENCIL depthStencil;
|
|
||||||
HANDLE pixelShader;
|
|
||||||
std::array<UINT, D3DDDIRS_BLENDOPALPHA + 1> renderState;
|
|
||||||
D3DDDIARG_SETRENDERTARGET renderTarget;
|
|
||||||
D3DDDIARG_SETSTREAMSOURCE streamSource;
|
|
||||||
D3DDDIARG_SETSTREAMSOURCEUM streamSourceUm;
|
|
||||||
const void* streamSourceUmBuffer;
|
|
||||||
std::array<HANDLE, 8> textures;
|
|
||||||
std::array<std::array<UINT, D3DDDITSS_TEXTURECOLORKEYVAL + 1>, 8> textureStageState;
|
|
||||||
HANDLE vertexShaderDecl;
|
|
||||||
HANDLE vertexShaderFunc;
|
|
||||||
D3DDDIARG_VIEWPORTINFO viewport;
|
|
||||||
D3DDDIARG_WINFO wInfo;
|
|
||||||
D3DDDIARG_ZRANGE zRange;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N>
|
template <int N>
|
||||||
std::unique_ptr<void, ResourceDeleter> createVertexShader(const BYTE(&code)[N])
|
std::unique_ptr<void, ResourceDeleter> createVertexShader(const BYTE(&code)[N])
|
||||||
{
|
{
|
||||||
@ -142,6 +157,9 @@ namespace D3dDdi
|
|||||||
HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember,
|
HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember,
|
||||||
HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
||||||
|
|
||||||
|
UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value);
|
||||||
|
UINT mapTssValue(UINT stage, D3DDDITEXTURESTAGESTATETYPE state, UINT value);
|
||||||
|
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
void removeResource(HANDLE resource, Data State::* data, HANDLE Data::* resourceMember,
|
void removeResource(HANDLE resource, Data State::* data, HANDLE Data::* resourceMember,
|
||||||
HRESULT(DeviceState::* pfnSetResourceFunc)(const Data*));
|
HRESULT(DeviceState::* pfnSetResourceFunc)(const Data*));
|
||||||
@ -173,7 +191,6 @@ namespace D3dDdi
|
|||||||
void updateRenderStates();
|
void updateRenderStates();
|
||||||
void updateRenderTarget();
|
void updateRenderTarget();
|
||||||
void updateShaders();
|
void updateShaders();
|
||||||
void updateStreamSource();
|
|
||||||
void updateTextureColorKey(UINT stage);
|
void updateTextureColorKey(UINT stage);
|
||||||
void updateTextureStages();
|
void updateTextureStages();
|
||||||
void updateVertexFixupConstants();
|
void updateVertexFixupConstants();
|
||||||
@ -187,11 +204,15 @@ namespace D3dDdi
|
|||||||
std::array<ShaderConstF, 256> m_vertexShaderConst;
|
std::array<ShaderConstF, 256> m_vertexShaderConst;
|
||||||
std::array<ShaderConstB, 16> m_vertexShaderConstB;
|
std::array<ShaderConstB, 16> m_vertexShaderConstB;
|
||||||
std::array<ShaderConstI, 16> m_vertexShaderConstI;
|
std::array<ShaderConstI, 16> m_vertexShaderConstI;
|
||||||
std::set<HANDLE> m_swVertexShaderDecls;
|
std::map<HANDLE, VertexDecl> m_vertexShaderDecls;
|
||||||
UINT m_changedStates;
|
UINT m_changedStates;
|
||||||
UINT m_maxChangedTextureStage;
|
UINT m_maxChangedTextureStage;
|
||||||
|
UINT m_usedTextureStages;
|
||||||
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
||||||
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
|
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup;
|
std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup;
|
||||||
|
std::array<Resource*, 8> m_textureResource;
|
||||||
|
bool m_isLocked;
|
||||||
|
bool m_spriteMode;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -453,13 +453,35 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT DrawPrimitive::draw(D3DDDIARG_DRAWPRIMITIVE data, const UINT* flagBuffer)
|
HRESULT DrawPrimitive::draw(D3DDDIARG_DRAWPRIMITIVE data, const UINT* flagBuffer)
|
||||||
{
|
{
|
||||||
m_device.getState().flush();
|
auto& state = m_device.getState();
|
||||||
|
if (!state.isLocked())
|
||||||
|
{
|
||||||
|
state.updateStreamSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||||
|
if (!state.isLocked())
|
||||||
|
{
|
||||||
|
if (m_streamSource.vertices && data.PrimitiveType >= D3DPT_TRIANGLELIST)
|
||||||
|
{
|
||||||
|
bool spriteMode = isSprite(data.VStart, 0, 1, 2);
|
||||||
|
state.setSpriteMode(spriteMode);
|
||||||
|
if (spriteMode)
|
||||||
|
{
|
||||||
|
setTextureClampMode(data.VStart, nullptr, vertexCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.setSpriteMode(false);
|
||||||
|
}
|
||||||
|
state.flush();
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == m_batched.primitiveCount || flagBuffer ||
|
if (0 == m_batched.primitiveCount || flagBuffer ||
|
||||||
!appendPrimitives(data.PrimitiveType, data.VStart, data.PrimitiveCount, nullptr, 0, 0))
|
!appendPrimitives(data.PrimitiveType, data.VStart, data.PrimitiveCount, nullptr, 0, 0))
|
||||||
{
|
{
|
||||||
flushPrimitives();
|
flushPrimitives();
|
||||||
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
|
||||||
if (m_streamSource.vertices)
|
if (m_streamSource.vertices)
|
||||||
{
|
{
|
||||||
appendVertices(data.VStart, vertexCount);
|
appendVertices(data.VStart, vertexCount);
|
||||||
@ -486,19 +508,41 @@ namespace D3dDdi
|
|||||||
HRESULT DrawPrimitive::drawIndexed(
|
HRESULT DrawPrimitive::drawIndexed(
|
||||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer)
|
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer)
|
||||||
{
|
{
|
||||||
m_device.getState().flush();
|
auto& state = m_device.getState();
|
||||||
|
if (!state.isLocked())
|
||||||
|
{
|
||||||
|
state.updateStreamSource();
|
||||||
|
}
|
||||||
|
|
||||||
auto indexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
auto indexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||||
|
auto vStart = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
|
||||||
|
if (!state.isLocked())
|
||||||
|
{
|
||||||
|
if (m_streamSource.vertices && data.PrimitiveType >= D3DPT_TRIANGLELIST)
|
||||||
|
{
|
||||||
|
bool spriteMode = isSprite(vStart, indices[0], indices[1], indices[2]);
|
||||||
|
state.setSpriteMode(spriteMode);
|
||||||
|
if (spriteMode)
|
||||||
|
{
|
||||||
|
setTextureClampMode(vStart, indices, indexCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.setSpriteMode(false);
|
||||||
|
}
|
||||||
|
state.flush();
|
||||||
|
}
|
||||||
|
|
||||||
auto [min, max] = std::minmax_element(indices, indices + indexCount);
|
auto [min, max] = std::minmax_element(indices, indices + indexCount);
|
||||||
data.MinIndex = *min;
|
data.MinIndex = *min;
|
||||||
data.NumVertices = *max - *min + 1;
|
data.NumVertices = *max - *min + 1;
|
||||||
|
|
||||||
if (0 == m_batched.primitiveCount || flagBuffer ||
|
if (0 == m_batched.primitiveCount || flagBuffer ||
|
||||||
!appendPrimitives(data.PrimitiveType, data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride),
|
!appendPrimitives(data.PrimitiveType, vStart, data.PrimitiveCount, indices, *min, *max))
|
||||||
data.PrimitiveCount, indices, *min, *max))
|
|
||||||
{
|
{
|
||||||
flushPrimitives();
|
flushPrimitives();
|
||||||
m_batched.baseVertexIndex = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
|
m_batched.baseVertexIndex = vStart;
|
||||||
if (m_streamSource.vertices)
|
if (m_streamSource.vertices)
|
||||||
{
|
{
|
||||||
appendIndexedVerticesWithoutRebase(indices, indexCount, m_batched.baseVertexIndex, *min, *max);
|
appendIndexedVerticesWithoutRebase(indices, indexCount, m_batched.baseVertexIndex, *min, *max);
|
||||||
@ -605,6 +649,15 @@ namespace D3dDdi
|
|||||||
return m_batched.vertices.size() / m_streamSource.stride;
|
return m_batched.vertices.size() / m_streamSource.stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DrawPrimitive::isSprite(INT baseVertexIndex, UINT16 index0, UINT16 index1, UINT16 index2)
|
||||||
|
{
|
||||||
|
auto v = m_streamSource.vertices + baseVertexIndex * m_streamSource.stride;
|
||||||
|
auto v0 = reinterpret_cast<const D3DTLVERTEX*>(v + index0 * m_streamSource.stride);
|
||||||
|
auto v1 = reinterpret_cast<const D3DTLVERTEX*>(v + index1 * m_streamSource.stride);
|
||||||
|
auto v2 = reinterpret_cast<const D3DTLVERTEX*>(v + index2 * m_streamSource.stride);
|
||||||
|
return v0->sz == v1->sz && v0->sz == v2->sz;
|
||||||
|
}
|
||||||
|
|
||||||
INT DrawPrimitive::loadIndices(const void* indices, UINT count)
|
INT DrawPrimitive::loadIndices(const void* indices, UINT count)
|
||||||
{
|
{
|
||||||
INT startIndex = m_indexBuffer.load(indices, count);
|
INT startIndex = m_indexBuffer.load(indices, count);
|
||||||
@ -748,4 +801,53 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawPrimitive::setTextureClampMode(INT baseVertexIndex, const UINT16* indices, UINT count)
|
||||||
|
{
|
||||||
|
if (Config::Settings::SpriteTexCoord::CLAMP != Config::spriteTexCoord.get())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& state = m_device.getState();
|
||||||
|
auto& appState = state.getAppState();
|
||||||
|
auto& decl = state.getVertexDecl();
|
||||||
|
auto vertices = m_streamSource.vertices + baseVertexIndex * m_streamSource.stride;
|
||||||
|
|
||||||
|
for (UINT stage = 0; stage < decl.textureStageCount; ++stage)
|
||||||
|
{
|
||||||
|
const UINT D3DDECLTYPE_FLOAT2 = 1;
|
||||||
|
if (!appState.textures[stage] ||
|
||||||
|
D3DDECLTYPE_FLOAT2 != decl.texCoordType[stage] ||
|
||||||
|
D3DTADDRESS_CLAMP == appState.textureStageState[stage][D3DDDITSS_ADDRESSU] &&
|
||||||
|
D3DTADDRESS_CLAMP == appState.textureStageState[stage][D3DDDITSS_ADDRESSV])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resource = state.getTextureResource(stage);
|
||||||
|
if (!resource || !resource->isClampable())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float texelWidth = 1 / static_cast<float>(resource->getFixedDesc().pSurfList[0].Width);
|
||||||
|
const float texelHeight = 1 / static_cast<float>(resource->getFixedDesc().pSurfList[0].Height);
|
||||||
|
const float minU = -texelWidth;
|
||||||
|
const float maxU = 1 + texelWidth;
|
||||||
|
const float minV = -texelHeight;
|
||||||
|
const float maxV = 1 + texelHeight;
|
||||||
|
|
||||||
|
for (UINT i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
auto vertex = vertices + (indices ? indices[i] : i) * m_streamSource.stride;
|
||||||
|
const float* texCoord = reinterpret_cast<const float*>(vertex + decl.texCoordOffset[stage]);
|
||||||
|
if (texCoord[0] < minU || texCoord[0] > maxU || texCoord[1] < minV || texCoord[1] > maxV)
|
||||||
|
{
|
||||||
|
state.disableTextureClamp(stage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ namespace D3dDdi
|
|||||||
void convertToTriangleList();
|
void convertToTriangleList();
|
||||||
HRESULT flush(const UINT* flagBuffer);
|
HRESULT flush(const UINT* flagBuffer);
|
||||||
HRESULT flushIndexed(const UINT* flagBuffer);
|
HRESULT flushIndexed(const UINT* flagBuffer);
|
||||||
|
bool isSprite(INT baseVertexIndex, UINT16 index0, UINT16 index1, UINT16 index2);
|
||||||
INT loadIndices(const void* indices, UINT count);
|
INT loadIndices(const void* indices, UINT count);
|
||||||
INT loadVertices(UINT count);
|
INT loadVertices(UINT count);
|
||||||
UINT getBatchedVertexCount() const;
|
UINT getBatchedVertexCount() const;
|
||||||
@ -77,6 +78,7 @@ namespace D3dDdi
|
|||||||
void repeatLastBatchedVertex();
|
void repeatLastBatchedVertex();
|
||||||
|
|
||||||
HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride);
|
HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride);
|
||||||
|
void setTextureClampMode(INT baseVertexIndex, const UINT16* indices, UINT count);
|
||||||
|
|
||||||
Device& m_device;
|
Device& m_device;
|
||||||
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
||||||
|
@ -117,6 +117,7 @@ namespace D3dDdi
|
|||||||
, m_scaledSize{}
|
, m_scaledSize{}
|
||||||
, m_isOversized(false)
|
, m_isOversized(false)
|
||||||
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
|
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
|
||||||
|
, m_isClampable(true)
|
||||||
{
|
{
|
||||||
if (m_origData.Flags.VertexBuffer &&
|
if (m_origData.Flags.VertexBuffer &&
|
||||||
m_origData.Flags.MightDrawFromLocked &&
|
m_origData.Flags.MightDrawFromLocked &&
|
||||||
@ -440,6 +441,11 @@ namespace D3dDdi
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Resource::disableClamp()
|
||||||
|
{
|
||||||
|
m_isClampable = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Resource::downscale(Resource*& rt, LONG& srcWidth, LONG& srcHeight, LONG dstWidth, LONG dstHeight)
|
bool Resource::downscale(Resource*& rt, LONG& srcWidth, LONG& srcHeight, LONG dstWidth, LONG dstHeight)
|
||||||
{
|
{
|
||||||
LONG newSrcWidth = (srcWidth + 1) / 2;
|
LONG newSrcWidth = (srcWidth + 1) / 2;
|
||||||
|
@ -29,9 +29,11 @@ namespace D3dDdi
|
|||||||
const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; }
|
const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; }
|
||||||
const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; }
|
const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; }
|
||||||
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
|
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
|
||||||
|
bool isClampable() const { return m_isClampable; }
|
||||||
|
|
||||||
HRESULT blt(D3DDDIARG_BLT data);
|
HRESULT blt(D3DDDIARG_BLT data);
|
||||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||||
|
void disableClamp();
|
||||||
void* getLockPtr(UINT subResourceIndex);
|
void* getLockPtr(UINT subResourceIndex);
|
||||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||||
void onDestroyResource(HANDLE resource);
|
void onDestroyResource(HANDLE resource);
|
||||||
@ -115,5 +117,6 @@ namespace D3dDdi
|
|||||||
SIZE m_scaledSize;
|
SIZE m_scaledSize;
|
||||||
bool m_isOversized;
|
bool m_isOversized;
|
||||||
bool m_isSurfaceRepoResource;
|
bool m_isSurfaceRepoResource;
|
||||||
|
bool m_isClampable;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@
|
|||||||
<ShaderModel>2.0</ShaderModel>
|
<ShaderModel>2.0</ShaderModel>
|
||||||
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
|
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
|
||||||
<ShaderType>Pixel</ShaderType>
|
<ShaderType>Pixel</ShaderType>
|
||||||
|
<DisableOptimizations>false</DisableOptimizations>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -226,6 +227,7 @@
|
|||||||
<ClInclude Include="Config\Settings\DisplayResolution.h" />
|
<ClInclude Include="Config\Settings\DisplayResolution.h" />
|
||||||
<ClInclude Include="Config\Settings\RenderColorDepth.h" />
|
<ClInclude Include="Config\Settings\RenderColorDepth.h" />
|
||||||
<ClInclude Include="Config\Settings\ResolutionScale.h" />
|
<ClInclude Include="Config\Settings\ResolutionScale.h" />
|
||||||
|
<ClInclude Include="Config\Settings\SpriteTexCoord.h" />
|
||||||
<ClInclude Include="Config\Settings\SupportedResolutions.h" />
|
<ClInclude Include="Config\Settings\SupportedResolutions.h" />
|
||||||
<ClInclude Include="Config\Settings\TextureFilter.h" />
|
<ClInclude Include="Config\Settings\TextureFilter.h" />
|
||||||
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
|
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
|
||||||
@ -350,6 +352,7 @@
|
|||||||
<ClCompile Include="Config\Settings\DisplayRefreshRate.cpp" />
|
<ClCompile Include="Config\Settings\DisplayRefreshRate.cpp" />
|
||||||
<ClCompile Include="Config\Settings\DisplayResolution.cpp" />
|
<ClCompile Include="Config\Settings\DisplayResolution.cpp" />
|
||||||
<ClCompile Include="Config\Settings\ResolutionScale.cpp" />
|
<ClCompile Include="Config\Settings\ResolutionScale.cpp" />
|
||||||
|
<ClCompile Include="Config\Settings\SpriteTexCoord.cpp" />
|
||||||
<ClCompile Include="Config\Settings\SupportedResolutions.cpp" />
|
<ClCompile Include="Config\Settings\SupportedResolutions.cpp" />
|
||||||
<ClCompile Include="Config\Settings\TextureFilter.cpp" />
|
<ClCompile Include="Config\Settings\TextureFilter.cpp" />
|
||||||
<ClCompile Include="D3dDdi\Adapter.cpp" />
|
<ClCompile Include="D3dDdi\Adapter.cpp" />
|
||||||
|
@ -528,6 +528,9 @@
|
|||||||
<ClInclude Include="Config\Settings\ConfigHotKey.h">
|
<ClInclude Include="Config\Settings\ConfigHotKey.h">
|
||||||
<Filter>Header Files\Config\Settings</Filter>
|
<Filter>Header Files\Config\Settings</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Config\Settings\SpriteTexCoord.h">
|
||||||
|
<Filter>Header Files\Config\Settings</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Gdi\Gdi.cpp">
|
<ClCompile Include="Gdi\Gdi.cpp">
|
||||||
@ -833,6 +836,9 @@
|
|||||||
<ClCompile Include="Input\HotKey.cpp">
|
<ClCompile Include="Input\HotKey.cpp">
|
||||||
<Filter>Source Files\Input</Filter>
|
<Filter>Source Files\Input</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Config\Settings\SpriteTexCoord.cpp">
|
||||||
|
<Filter>Source Files\Config\Settings</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="DDrawCompat.rc">
|
<ResourceCompile Include="DDrawCompat.rc">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
namespace Overlay
|
namespace Overlay
|
||||||
{
|
{
|
||||||
ConfigWindow::ConfigWindow()
|
ConfigWindow::ConfigWindow()
|
||||||
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 200 }, Config::configHotKey.get())
|
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 300 }, Config::configHotKey.get())
|
||||||
, m_focus(nullptr)
|
, m_focus(nullptr)
|
||||||
{
|
{
|
||||||
addControl(Config::alternatePixelCenter);
|
addControl(Config::alternatePixelCenter);
|
||||||
@ -16,6 +16,7 @@ namespace Overlay
|
|||||||
addControl(Config::displayFilter);
|
addControl(Config::displayFilter);
|
||||||
addControl(Config::renderColorDepth);
|
addControl(Config::renderColorDepth);
|
||||||
addControl(Config::resolutionScale);
|
addControl(Config::resolutionScale);
|
||||||
|
addControl(Config::spriteTexCoord);
|
||||||
addControl(Config::textureFilter);
|
addControl(Config::textureFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ namespace Overlay
|
|||||||
if (&Config::antialiasing == &m_setting ||
|
if (&Config::antialiasing == &m_setting ||
|
||||||
&Config::renderColorDepth == &m_setting ||
|
&Config::renderColorDepth == &m_setting ||
|
||||||
&Config::resolutionScale == &m_setting ||
|
&Config::resolutionScale == &m_setting ||
|
||||||
|
&Config::spriteTexCoord == &m_setting ||
|
||||||
&Config::textureFilter == &m_setting)
|
&Config::textureFilter == &m_setting)
|
||||||
{
|
{
|
||||||
D3dDdi::Device::updateAllConfig();
|
D3dDdi::Device::updateAllConfig();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
bool g_useTexCoordAdj : register(b15);
|
||||||
|
float4 g_texCoordAdj : register(c253);
|
||||||
float4 g_offset : register(c254);
|
float4 g_offset : register(c254);
|
||||||
float4 g_multiplier : register(c255);
|
float4 g_multiplier : register(c255);
|
||||||
|
|
||||||
@ -19,5 +21,9 @@ VS main(const VS i)
|
|||||||
o.pos.xyz *= w;
|
o.pos.xyz *= w;
|
||||||
o.pos.w = w;
|
o.pos.w = w;
|
||||||
o.fog = i.color[1].a;
|
o.fog = i.color[1].a;
|
||||||
|
if (g_useTexCoordAdj)
|
||||||
|
{
|
||||||
|
o.tex[0].xy = round(o.tex[0].xy * g_texCoordAdj.xy + g_texCoordAdj.zw) / g_texCoordAdj.xy;
|
||||||
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user