/*
Copyright 2021 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see .
*/
#pragma once
#include "types.h"
#include
#include "hw/pvr/Renderer_if.h"
#include
#include "dxcontext.h"
#include "rend/transform_matrix.h"
#include "d3d_texture.h"
#include "d3d_shaders.h"
#include "rend/imgui_driver.h"
class RenderStateCache
{
IDirect3DDevice9 *device = nullptr;
std::array renderState;
std::array sampler0State;
IDirect3DVertexShader9 *vertexShader = nullptr;
IDirect3DPixelShader9 *pixelShader = nullptr;
IDirect3DBaseTexture9 *texture = nullptr;
public:
void setDevice(IDirect3DDevice9 *device) {
this->device = device;
reset();
}
void reset() {
renderState.fill(0xfefefefe);
sampler0State.fill(0xfefefefe);
vertexShader = nullptr;
pixelShader = nullptr;
texture = nullptr;
}
HRESULT SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
{
if ((u32)state < renderState.size())
{
if (renderState[state] == value)
return S_OK;
renderState[state] = value;
}
return device->SetRenderState(state, value);
}
HRESULT SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
{
if (sampler == 0 && (u32)type < sampler0State.size())
{
if (sampler0State[type] == value)
return S_OK;
sampler0State[type] = value;
}
return device->SetSamplerState(sampler, type, value);
}
HRESULT SetVertexShader(IDirect3DVertexShader9 *pShader)
{
if (pShader == vertexShader)
return S_OK;
vertexShader = pShader;
return device->SetVertexShader(pShader);
}
HRESULT SetPixelShader(IDirect3DPixelShader9 *pShader)
{
if (pShader == pixelShader)
return S_OK;
pixelShader = pShader;
return device->SetPixelShader(pShader);
}
HRESULT SetTexture(DWORD stage, IDirect3DBaseTexture9 *pTexture)
{
if (stage == 0)
{
if (pTexture == texture)
return S_OK;
texture = pTexture;
}
return device->SetTexture(stage, pTexture);
}
};
struct D3DRenderer : public Renderer
{
bool Init() override;
void Term() override;
void Process(TA_context* ctx) override;
bool Render() override;
bool RenderLastFrame() override;
bool Present() override
{
if (!frameRendered)
return false;
imguiDriver->setFrameRendered();
frameRendered = false;
return true;
}
void DrawOSD(bool clear_screen) override;
BaseTextureCacheData *GetTexture(TSP tsp, TCW tcw) override;
void preReset();
void postReset();
void RenderFramebuffer(const FramebufferInfo& info) override;
private:
enum ModifierVolumeMode { Xor, Or, Inclusion, Exclusion, ModeCount };
void resize(int w, int h);
void drawStrips();
template
void drawList(const std::vector& gply, int first, int count);
template
void setGPState(const PolyParam *gp);
bool ensureVertexBufferSize(ComPtr& buffer, u32& currentSize, u32 minSize);
bool ensureIndexBufferSize(ComPtr& buffer, u32& currentSize, u32 minSize);
void updatePaletteTexture();
void updateFogTexture();
void displayFramebuffer();
void drawSorted(int first, int count, bool multipass);
void setMVS_Mode(ModifierVolumeMode mv_mode, ISP_Modvol ispc);
void drawModVols(int first, int count);
void setTexMode(D3DSAMPLERSTATETYPE state, u32 clamp, u32 mirror);
void setBaseScissor();
void prepareRttRenderTarget(u32 texAddress);
void readRttRenderTarget(u32 texAddress);
void writeFramebufferToVRAM();
RenderStateCache devCache;
ComPtr device;
ComPtr vertexBuffer;
u32 vertexBufferSize = 0;
ComPtr modvolBuffer;
u32 modvolBufferSize = 0;
ComPtr indexBuffer;
u32 indexBufferSize = 0;
ComPtr mainVtxDecl;
ComPtr modVolVtxDecl;
ComPtr framebufferTexture;
ComPtr framebufferSurface;
ComPtr backbuffer;
ComPtr paletteTexture;
ComPtr fogTexture;
ComPtr dcfbTexture;
ComPtr dcfbSurface;
ComPtr rttTexture;
ComPtr rttSurface;
ComPtr depthSurface;
ComPtr fbScaledTexture;
ComPtr fbScaledSurface;
u32 width = 0;
u32 height = 0;
TransformMatrix matrices;
D3DTextureCache texCache;
D3DShaders shaders;
RECT scissorRect{};
bool scissorEnable = false;
bool frameRendered = false;
bool frameRenderedOnce = false;
int maxAnisotropy = 1;
float aspectRatio = 4.f / 3.f;
bool dithering = false;
};