CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/GPU/D3D9/D3D9StateCache.h
Views: 1401
#pragma once12#include <cstring>3#include <wrl/client.h>45#include "Common/GPU/D3D9/D3D9ShaderCompiler.h"67// TODO: Get rid of these somehow.8extern Microsoft::WRL::ComPtr<IDirect3DDevice9> pD3Ddevice9;9extern Microsoft::WRL::ComPtr<IDirect3DDevice9Ex> pD3DdeviceEx9;1011class DirectXState {12private:13template<D3DRENDERSTATETYPE cap, bool init>14class BoolState {15bool _value;16public:17BoolState() : _value(init) {18DirectXState::state_count++;19}2021inline void set(bool value) {22if (_value != value) {23_value = value;24restore();25}26}27void force(bool value) {28bool old = _value;29set(value);30_value = old;31}32inline void enable() {33set(true);34}35inline void disable() {36set(false);37}38operator bool() const {39return isset();40}41inline bool isset() {42return _value;43}44void restore() {45pD3Ddevice9->SetRenderState(cap, _value);46}47};4849template<D3DRENDERSTATETYPE state1, DWORD p1def>50class DxState1 {51D3DRENDERSTATETYPE _state1;52DWORD p1;53public:54DxState1() : _state1(state1), p1(p1def) {55DirectXState::state_count++;56}5758inline void set(DWORD newp1) {59if (p1 != newp1) {60p1 = newp1;61restore();62}63}64void force(DWORD newp1) {65DWORD old = p1;66set(newp1);67p1 = old;68}69void restore() {70pD3Ddevice9->SetRenderState(_state1, p1);71}72};7374template<D3DSAMPLERSTATETYPE state1, DWORD p1def>75class DxSampler0State1 {76D3DSAMPLERSTATETYPE _state1;77DWORD p1;78public:79DxSampler0State1() : _state1(state1), p1(p1def) {80DirectXState::state_count++;81}8283inline void set(DWORD newp1) {84if (p1 != newp1) {85p1 = newp1;86restore();87}88}89void force(DWORD newp1) {90DWORD old = p1;91set(newp1);92p1 = old;93}94void restore() {95pD3Ddevice9->SetSamplerState(0, _state1, p1);96}97};9899// Can't have FLOAT template parameters...100template<D3DSAMPLERSTATETYPE state1, DWORD p1def>101class DxSampler0State1Float {102D3DSAMPLERSTATETYPE _state1;103union {104FLOAT p1;105DWORD p1d;106};107public:108DxSampler0State1Float() : _state1(state1), p1d(p1def) {109DirectXState::state_count++;110}111112inline void set(FLOAT newp1) {113if (p1 != newp1) {114p1 = newp1;115restore();116}117}118void force(FLOAT newp1) {119FLOAT old = p1;120set(newp1);121p1 = old;122}123void restore() {124pD3Ddevice9->SetSamplerState(0, _state1, p1d);125}126};127128template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def>129class DxState2 {130D3DRENDERSTATETYPE _state1;131D3DRENDERSTATETYPE _state2;132DWORD p1;133DWORD p2;134public:135DxState2() : _state1(state1),_state2(state2), p1(p1def), p2(p2def) {136DirectXState::state_count++;137}138139inline void set(DWORD newp1, DWORD newp2) {140if (p1 != newp1) {141p1 = newp1;142pD3Ddevice9->SetRenderState(_state1, p1);143}144if (p2 != newp2) {145p2 = newp2;146pD3Ddevice9->SetRenderState(_state2, p2);147}148}149void force(DWORD newp1, DWORD newp2) {150DWORD old1 = p1;151DWORD old2 = p2;152set(newp1, newp2);153p1 = old1;154p2 = old2;155}156void restore() {157pD3Ddevice9->SetRenderState(_state1, p1);158pD3Ddevice9->SetRenderState(_state2, p2);159}160};161162template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def, D3DRENDERSTATETYPE state3, DWORD p3def>163class DxState3 {164D3DRENDERSTATETYPE _state1;165D3DRENDERSTATETYPE _state2;166D3DRENDERSTATETYPE _state3;167DWORD p1;168DWORD p2;169DWORD p3;170public:171DxState3() : _state1(state1),_state2(state2), _state3(state3),172p1(p1def), p2(p2def), p3(p3def) {173}174175inline void set(DWORD newp1, DWORD newp2, DWORD newp3) {176if (p1 != newp1) {177p1 = newp1;178pD3Ddevice9->SetRenderState(_state1, p1);179}180if (p2 != newp2) {181p2 = newp2;182pD3Ddevice9->SetRenderState(_state2, p2);183}184if (p3 != newp3) {185p3 = newp3;186pD3Ddevice9->SetRenderState(_state3, p3);187}188}189void force(DWORD newp1, DWORD newp2, DWORD newp3) {190DWORD old1 = p1;191DWORD old2 = p2;192DWORD old3 = p3;193set(newp1, newp2, newp3);194p1 = old1;195p2 = old2;196p3 = old3;197}198void restore() {199pD3Ddevice9->SetRenderState(_state1, p1);200pD3Ddevice9->SetRenderState(_state2, p2);201pD3Ddevice9->SetRenderState(_state3, p3);202}203};204205template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def, D3DRENDERSTATETYPE state3, DWORD p3def, D3DRENDERSTATETYPE state4, DWORD p4def>206class DxState4 {207D3DRENDERSTATETYPE _state1;208D3DRENDERSTATETYPE _state2;209D3DRENDERSTATETYPE _state3;210D3DRENDERSTATETYPE _state4;211DWORD p1;212DWORD p2;213DWORD p3;214DWORD p4;215public:216DxState4() : _state1(state1), _state2(state2), _state3(state3), _state4(state4),217p1(p1def), p2(p2def), p3(p3def), p4(p4def) {218}219220inline void set(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) {221if (p1 != newp1) {222p1 = newp1;223pD3Ddevice9->SetRenderState(_state1, p1);224}225if (p2 != newp2) {226p2 = newp2;227pD3Ddevice9->SetRenderState(_state2, p2);228}229if (p3 != newp3) {230p3 = newp3;231pD3Ddevice9->SetRenderState(_state3, p3);232}233if (p4 != newp4) {234p4 = newp4;235pD3Ddevice9->SetRenderState(_state4, p4);236}237}238void force(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) {239DWORD old1 = p1;240DWORD old2 = p2;241DWORD old3 = p3;242DWORD old4 = p4;243set(newp1, newp2, newp3, newp4);244p1 = old1;245p2 = old2;246p3 = old3;247p4 = old4;248}249void restore() {250pD3Ddevice9->SetRenderState(_state1, p1);251pD3Ddevice9->SetRenderState(_state2, p2);252pD3Ddevice9->SetRenderState(_state3, p3);253pD3Ddevice9->SetRenderState(_state4, p4);254}255};256257258class SavedBlendFactor {259DWORD c;260public:261SavedBlendFactor() {262c = 0xFFFFFFFF;263DirectXState::state_count++;264}265inline void set(const float v[4]) {266DWORD newc = D3DCOLOR_COLORVALUE(v[0], v[1], v[2], v[3]);267if (c != newc) {268c = newc;269restore();270}271}272void setDWORD(DWORD newc) {273newc = ((newc >> 8) & 0xff) | (newc & 0xff00ff00) | ((newc << 16) & 0xff0000); // ARGB -> ABGR fix274if (c != newc) {275c = newc;276restore();277}278}279void force(const float v[4]) {280DWORD old = c;281set(v);282c = old;283}284inline void restore() {285pD3Ddevice9->SetRenderState(D3DRS_BLENDFACTOR, c);286}287};288289class StateVp {290D3DVIEWPORT9 viewport;291public:292StateVp() {293memset(&viewport, 0, sizeof(viewport));294// It's an error if w/h is zero, so let's start with something that can work.295viewport.Width = 1;296viewport.Height = 1;297}298inline void set(int x, int y, int w, int h, float n = 0.f, float f = 1.f) {299D3DVIEWPORT9 newviewport;300newviewport.X = x;301newviewport.Y = y;302newviewport.Width = w;303newviewport.Height = h;304newviewport.MinZ = n;305newviewport.MaxZ = f;306if (memcmp(&viewport, &newviewport, sizeof(viewport)) != 0) {307viewport = newviewport;308restore();309}310}311312void force(int x, int y, int w, int h, float n = 0.f, float f = 1.f) {313D3DVIEWPORT9 old = viewport;314set(x, y, w, h, n, f);315viewport = old;316}317318inline void restore() {319pD3Ddevice9->SetViewport(&viewport);320}321};322323class StateScissor {324RECT rect;325public:326inline void set(int x1, int y1, int x2, int y2) {327RECT newrect = {x1, y1, x2, y2};328if (memcmp(&rect, &newrect, sizeof(rect))) {329rect = newrect;330restore();331}332}333334void force(int x1, int y1, int x2, int y2) {335RECT old = rect;336set(x1, y1, x2, y2);337rect = old;338}339340inline void restore() {341pD3Ddevice9->SetScissorRect(&rect);342}343};344345bool initialized;346347public:348static int state_count;349DirectXState() : initialized(false) {}350void Initialize();351void Restore();352353// When adding a state here, don't forget to add it to DirectxState::Restore() too354BoolState<D3DRS_ALPHABLENDENABLE, false> blend;355BoolState<D3DRS_SEPARATEALPHABLENDENABLE, false> blendSeparate;356DxState4<D3DRS_SRCBLEND, D3DBLEND_SRCALPHA, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO> blendFunc;357DxState2<D3DRS_BLENDOP, D3DBLENDOP_ADD, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD> blendEquation;358SavedBlendFactor blendColor;359360BoolState<D3DRS_SCISSORTESTENABLE, false> scissorTest;361362DxState1<D3DRS_CULLMODE, D3DCULL_NONE> cullMode;363DxState1<D3DRS_SHADEMODE, D3DSHADE_GOURAUD> shadeMode;364DxState1<D3DRS_CLIPPLANEENABLE, 0> clipPlaneEnable;365366BoolState<D3DRS_ZENABLE, false> depthTest;367368DxState1<D3DRS_ALPHAFUNC, D3DCMP_ALWAYS> alphaTestFunc;369DxState1<D3DRS_ALPHAREF, 0> alphaTestRef;370BoolState<D3DRS_ALPHATESTENABLE, false> alphaTest;371372DxState1<D3DRS_ZFUNC, D3DCMP_LESSEQUAL> depthFunc;373DxState1<D3DRS_ZWRITEENABLE, TRUE> depthWrite;374375DxState1<D3DRS_COLORWRITEENABLE, 0xF> colorMask;376377StateVp viewport;378StateScissor scissorRect;379380BoolState<D3DRS_STENCILENABLE, false> stencilTest;381382DxState3<D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP> stencilOp;383DxState1<D3DRS_STENCILFUNC, D3DCMP_ALWAYS> stencilFunc;384DxState1<D3DRS_STENCILREF, 0> stencilRef;385DxState1<D3DRS_STENCILWRITEMASK, 0xFFFFFFFF> stencilWriteMask;386DxState1<D3DRS_STENCILMASK, 0xFFFFFFFF> stencilCompareMask;387388DxSampler0State1<D3DSAMP_MINFILTER, D3DTEXF_POINT> texMinFilter;389DxSampler0State1<D3DSAMP_MAGFILTER, D3DTEXF_POINT> texMagFilter;390DxSampler0State1<D3DSAMP_MIPFILTER, D3DTEXF_NONE> texMipFilter;391DxSampler0State1Float<D3DSAMP_MIPMAPLODBIAS, 0> texMipLodBias;392DxSampler0State1<D3DSAMP_MAXMIPLEVEL, 0> texMaxMipLevel;393DxSampler0State1<D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP> texAddressU;394DxSampler0State1<D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP> texAddressV;395DxSampler0State1<D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP> texAddressW;396};397398#undef STATE1399#undef STATE2400401extern DirectXState dxstate;402403404