// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "Direct3DStateBlock9.hpp" #include "Direct3DDevice9.hpp" #include "Direct3DVertexDeclaration9.hpp" #include "Direct3DIndexBuffer9.hpp" #include "Direct3DVertexBuffer9.hpp" #include "Direct3DBaseTexture9.hpp" #include "Direct3DPixelShader9.hpp" #include "Direct3DVertexShader9.hpp" #include "Debug.hpp" #include <assert.h> namespace D3D9 { Direct3DStateBlock9::Direct3DStateBlock9(Direct3DDevice9 *device, D3DSTATEBLOCKTYPE type) : device(device), type(type) { vertexDeclaration = 0; indexBuffer = 0; for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { streamSource[stream].vertexBuffer = 0; } for(int sampler = 0; sampler < 16 + 4; sampler++) { texture[sampler] = 0; } pixelShader = 0; vertexShader = 0; clear(); if(type == D3DSBT_PIXELSTATE || type == D3DSBT_ALL) { capturePixelRenderStates(); capturePixelTextureStates(); capturePixelSamplerStates(); capturePixelShaderStates(); } if(type == D3DSBT_VERTEXSTATE || type == D3DSBT_ALL) { captureVertexRenderStates(); captureVertexSamplerStates(); captureVertexTextureStates(); captureNPatchMode(); captureLightStates(); captureVertexShaderStates(); captureStreamSourceFrequencies(); captureFVF(); captureVertexDeclaration(); } if(type == D3DSBT_ALL) // Capture remaining states { captureTextures(); captureTexturePalette(); captureVertexStreams(); captureIndexBuffer(); captureViewport(); captureScissorRectangle(); captureTransforms(); captureTextureTransforms(); captureClippingPlanes(); captureMaterial(); } } Direct3DStateBlock9::~Direct3DStateBlock9() { clear(); } long Direct3DStateBlock9::QueryInterface(const IID &iid, void **object) { CriticalSection cs(device); TRACE(""); if(iid == IID_IDirect3DStateBlock9 || iid == IID_IUnknown) { AddRef(); *object = this; return S_OK; } *object = 0; return NOINTERFACE(iid); } unsigned long Direct3DStateBlock9::AddRef() { TRACE(""); return Unknown::AddRef(); } unsigned long Direct3DStateBlock9::Release() { TRACE(""); return Unknown::Release(); } long Direct3DStateBlock9::Apply() { CriticalSection cs(device); TRACE(""); if(device->isRecording()) { return INVALIDCALL(); } if(fvfCaptured) { device->SetFVF(FVF); } if(vertexDeclarationCaptured) { device->SetVertexDeclaration(vertexDeclaration); } if(indexBufferCaptured) { device->SetIndices(indexBuffer); } for(int state = D3DRS_ZENABLE; state <= D3DRS_BLENDOPALPHA; state++) { if(renderStateCaptured[state]) { device->SetRenderState((D3DRENDERSTATETYPE)state, renderState[state]); } } if(nPatchModeCaptured) { device->SetNPatchMode(nPatchMode); } for(int stage = 0; stage < 8; stage++) { for(int state = D3DTSS_COLOROP; state <= D3DTSS_CONSTANT; state++) { if(textureStageStateCaptured[stage][state]) { device->SetTextureStageState(stage, (D3DTEXTURESTAGESTATETYPE)state, textureStageState[stage][state]); } } } for(int sampler = 0; sampler < 16 + 4; sampler++) { for(int state = D3DSAMP_ADDRESSU; state <= D3DSAMP_DMAPOFFSET; state++) { if(samplerStateCaptured[sampler][state]) { int index = sampler < 16 ? sampler : D3DVERTEXTEXTURESAMPLER0 + (sampler - 16); device->SetSamplerState(index, (D3DSAMPLERSTATETYPE)state, samplerState[sampler][state]); } } } for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { if(streamSourceCaptured[stream]) { device->SetStreamSource(stream, streamSource[stream].vertexBuffer, streamSource[stream].offset, streamSource[stream].stride); } if(streamSourceFrequencyCaptured[stream]) { device->SetStreamSourceFreq(stream, streamSourceFrequency[stream]); } } for(int sampler = 0; sampler < 16 + 4; sampler++) { if(textureCaptured[sampler]) { int index = sampler < 16 ? sampler : D3DVERTEXTEXTURESAMPLER0 + (sampler - 16); device->SetTexture(index, texture[sampler]); } } for(int state = 0; state < 512; state++) { if(transformCaptured[state]) { device->SetTransform((D3DTRANSFORMSTATETYPE)state, &transform[state]); } } if(materialCaptured) { device->SetMaterial(&material); } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { if(lightCaptured[index]) { device->SetLight(index, &light[index]); } } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { if(lightEnableCaptured[index]) { device->LightEnable(index, lightEnableState[index]); } } if(pixelShaderCaptured) { device->SetPixelShader(pixelShader); } if(vertexShaderCaptured) { device->SetVertexShader(vertexShader); } if(viewportCaptured) { device->SetViewport(&viewport); } for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++) { if(*(int*)pixelShaderConstantF[i] != 0x80000000) { device->SetPixelShaderConstantF(i, pixelShaderConstantF[i], 1); } } for(int i = 0; i < 16; i++) { if(pixelShaderConstantI[i][0] != 0x80000000) { device->SetPixelShaderConstantI(i, pixelShaderConstantI[i], 1); } } for(int i = 0; i < 16; i++) { if(pixelShaderConstantB[i] != 0x80000000) { device->SetPixelShaderConstantB(i, &pixelShaderConstantB[i], 1); } } for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++) { if(*(int*)vertexShaderConstantF[i] != 0x80000000) { device->SetVertexShaderConstantF(i, vertexShaderConstantF[i], 1); } } for(int i = 0; i < 16; i++) { if(vertexShaderConstantI[i][0] != 0x80000000) { device->SetVertexShaderConstantI(i, vertexShaderConstantI[i], 1); } } for(int i = 0; i < 16; i++) { if(vertexShaderConstantB[i] != 0x80000000) { device->SetVertexShaderConstantB(i, &vertexShaderConstantB[i], 1); } } for(int index = 0; index < 6; index++) { if(clipPlaneCaptured[index]) { device->SetClipPlane(index, clipPlane[index]); } } if(scissorRectCaptured) { device->SetScissorRect(&scissorRect); } if(paletteNumberCaptured) { device->SetCurrentTexturePalette(paletteNumber); } return D3D_OK; } long Direct3DStateBlock9::Capture() { CriticalSection cs(device); TRACE(""); if(fvfCaptured) { device->GetFVF(&FVF); } if(vertexDeclarationCaptured) { Direct3DVertexDeclaration9 *vertexDeclaration; device->GetVertexDeclaration(reinterpret_cast<IDirect3DVertexDeclaration9**>(&vertexDeclaration)); if(vertexDeclaration) { vertexDeclaration->bind(); vertexDeclaration->Release(); } if(this->vertexDeclaration) { this->vertexDeclaration->unbind(); } this->vertexDeclaration = vertexDeclaration; } if(indexBufferCaptured) { Direct3DIndexBuffer9 *indexBuffer; device->GetIndices(reinterpret_cast<IDirect3DIndexBuffer9**>(&indexBuffer)); if(indexBuffer) { indexBuffer->bind(); indexBuffer->Release(); } if(this->indexBuffer) { this->indexBuffer->unbind(); } this->indexBuffer = indexBuffer; } for(int state = 0; state < D3DRS_BLENDOPALPHA + 1; state++) { if(renderStateCaptured[state]) { device->GetRenderState((D3DRENDERSTATETYPE)state, &renderState[state]); } } if(nPatchModeCaptured) { nPatchMode = device->GetNPatchMode(); } for(int stage = 0; stage < 8; stage++) { for(int state = 0; state < D3DTSS_CONSTANT + 1; state++) { if(textureStageStateCaptured[stage][state]) { device->GetTextureStageState(stage, (D3DTEXTURESTAGESTATETYPE)state, &textureStageState[stage][state]); } } } for(int sampler = 0; sampler < 16 + 4; sampler++) { for(int state = 0; state < D3DSAMP_DMAPOFFSET + 1; state++) { if(samplerStateCaptured[sampler][state]) { int index = sampler < 16 ? sampler : D3DVERTEXTEXTURESAMPLER0 + (sampler - 16); device->GetSamplerState(index, (D3DSAMPLERSTATETYPE)state, &samplerState[sampler][state]); } } } for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { if(streamSourceCaptured[stream]) { Direct3DVertexBuffer9 *vertexBuffer; device->GetStreamSource(stream, reinterpret_cast<IDirect3DVertexBuffer9**>(&vertexBuffer), &streamSource[stream].offset, &streamSource[stream].stride); if(vertexBuffer) { vertexBuffer->bind(); vertexBuffer->Release(); } if(streamSource[stream].vertexBuffer) { streamSource[stream].vertexBuffer->unbind(); } streamSource[stream].vertexBuffer = vertexBuffer; } if(streamSourceFrequencyCaptured[stream]) { device->GetStreamSourceFreq(stream, &streamSourceFrequency[stream]); } } for(int sampler = 0; sampler < 16 + 4; sampler++) { if(textureCaptured[sampler]) { Direct3DBaseTexture9 *texture; int index = sampler < 16 ? sampler : D3DVERTEXTEXTURESAMPLER0 + (sampler - 16); device->GetTexture(index, reinterpret_cast<IDirect3DBaseTexture9**>(&texture)); if(texture) { texture->bind(); texture->Release(); } if(this->texture[sampler]) { this->texture[sampler]->unbind(); } this->texture[sampler] = texture; } } for(int state = 0; state < 512; state++) { if(transformCaptured[state]) { device->GetTransform((D3DTRANSFORMSTATETYPE)state, &transform[state]); } } if(materialCaptured) { device->GetMaterial(&material); } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { if(lightCaptured[index]) { device->GetLight(index, &light[index]); } } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { if(lightEnableCaptured[index]) { lightEnableState[index] = false; device->GetLightEnable(index, &lightEnableState[index]); } } if(pixelShaderCaptured) { Direct3DPixelShader9 *pixelShader; device->GetPixelShader(reinterpret_cast<IDirect3DPixelShader9**>(&pixelShader)); if(pixelShader) { pixelShader->bind(); pixelShader->Release(); } if(this->pixelShader) { this->pixelShader->unbind(); } this->pixelShader = pixelShader; } if(vertexShaderCaptured) { Direct3DVertexShader9 *vertexShader; device->GetVertexShader(reinterpret_cast<IDirect3DVertexShader9**>(&vertexShader)); if(vertexShader) { vertexShader->bind(); vertexShader->Release(); } if(this->vertexShader) { this->vertexShader->unbind(); } this->vertexShader = vertexShader; } if(viewportCaptured) { device->GetViewport(&viewport); } for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++) { if(*(int*)pixelShaderConstantF[i] != 0x80000000) { device->GetPixelShaderConstantF(i, pixelShaderConstantF[i], 1); } } for(int i = 0; i < 16; i++) { if(pixelShaderConstantI[i][0] != 0x80000000) { device->GetPixelShaderConstantI(i, pixelShaderConstantI[i], 1); } } for(int i = 0; i < 16; i++) { if(pixelShaderConstantB[i] != 0x80000000) { device->GetPixelShaderConstantB(i, &pixelShaderConstantB[i], 1); } } for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++) { if(*(int*)vertexShaderConstantF[i] != 0x80000000) { device->GetVertexShaderConstantF(i, vertexShaderConstantF[i], 1); } } for(int i = 0; i < 16; i++) { if(vertexShaderConstantI[i][0] != 0x80000000) { device->GetVertexShaderConstantI(i, vertexShaderConstantI[i], 1); } } for(int i = 0; i < 16; i++) { if(vertexShaderConstantB[i] != 0x80000000) { device->GetVertexShaderConstantB(i, &vertexShaderConstantB[i], 1); } } for(int index = 0; index < 6; index++) { if(clipPlaneCaptured[index]) { device->GetClipPlane(index, clipPlane[index]); } } if(scissorRectCaptured) { device->GetScissorRect(&scissorRect); } if(paletteNumberCaptured) { device->GetCurrentTexturePalette(&paletteNumber); } return D3D_OK; } long Direct3DStateBlock9::GetDevice(IDirect3DDevice9 **device) { CriticalSection cs(this->device); TRACE(""); if(!device) { return INVALIDCALL(); } this->device->AddRef(); *device = this->device; return D3D_OK; } void Direct3DStateBlock9::lightEnable(unsigned long index, int enable) { if(index < 8) { lightEnableCaptured[index] = true; lightEnableState[index] = enable; } else ASSERT(false); // FIXME: Support unlimited index } void Direct3DStateBlock9::setClipPlane(unsigned long index, const float *plane) { clipPlaneCaptured[index] = true; clipPlane[index][0] = plane[0]; clipPlane[index][1] = plane[1]; clipPlane[index][2] = plane[2]; clipPlane[index][3] = plane[3]; } void Direct3DStateBlock9::setCurrentTexturePalette(unsigned int paletteNumber) { paletteNumberCaptured = true; this->paletteNumber = paletteNumber; } void Direct3DStateBlock9::setFVF(unsigned long FVF) { fvfCaptured = true; this->FVF = FVF; } void Direct3DStateBlock9::setIndices(Direct3DIndexBuffer9 *indexBuffer) { if(indexBuffer) indexBuffer->bind(); if(this->indexBuffer) this->indexBuffer->unbind(); indexBufferCaptured = true; this->indexBuffer = indexBuffer; } void Direct3DStateBlock9::setLight(unsigned long index, const D3DLIGHT9 *light) { if(index < 8) { lightCaptured[index] = true; this->light[index] = *light; } else ASSERT(false); // FIXME: Support unlimited index } void Direct3DStateBlock9::setMaterial(const D3DMATERIAL9 *material) { materialCaptured = true; this->material = *material; } void Direct3DStateBlock9::setNPatchMode(float segments) { nPatchModeCaptured = true; nPatchMode = segments; } void Direct3DStateBlock9::setPixelShader(Direct3DPixelShader9 *pixelShader) { if(pixelShader) pixelShader->bind(); if(this->pixelShader) this->pixelShader->unbind(); pixelShaderCaptured = true; this->pixelShader = pixelShader; } void Direct3DStateBlock9::setPixelShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count) { memcpy(&pixelShaderConstantB[startRegister], constantData, count * sizeof(int)); } void Direct3DStateBlock9::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) { memcpy(pixelShaderConstantF[startRegister], constantData, count * sizeof(float[4])); } void Direct3DStateBlock9::setPixelShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count) { memcpy(pixelShaderConstantI[startRegister], constantData, count * sizeof(int[4])); } void Direct3DStateBlock9::setRenderState(D3DRENDERSTATETYPE state, unsigned long value) { renderStateCaptured[state] = true; renderState[state] = value; } void Direct3DStateBlock9::setSamplerState(unsigned long index, D3DSAMPLERSTATETYPE state, unsigned long value) { unsigned int sampler = index < 16 ? index : (index - D3DVERTEXTEXTURESAMPLER0) + 16; if(sampler >= 16 + 4) { return; } samplerStateCaptured[sampler][state] = true; samplerState[sampler][state] = value; } void Direct3DStateBlock9::setScissorRect(const RECT *rect) { scissorRectCaptured = true; scissorRect = *rect; } void Direct3DStateBlock9::setStreamSource(unsigned int stream, Direct3DVertexBuffer9 *vertexBuffer, unsigned int offset, unsigned int stride) { if(vertexBuffer) vertexBuffer->bind(); if(streamSource[stream].vertexBuffer) streamSource[stream].vertexBuffer->unbind(); streamSourceCaptured[stream] = true; streamSource[stream].vertexBuffer = vertexBuffer; streamSource[stream].offset = offset; streamSource[stream].stride = stride; } void Direct3DStateBlock9::setStreamSourceFreq(unsigned int streamNumber, unsigned int divider) { streamSourceFrequencyCaptured[streamNumber] = true; streamSourceFrequency[streamNumber] = divider; } void Direct3DStateBlock9::setTexture(unsigned long index, Direct3DBaseTexture9 *texture) { unsigned int sampler = index < 16 ? index : (index - D3DVERTEXTEXTURESAMPLER0) + 16; if(sampler >= 16 + 4) { return; } if(texture) texture->bind(); if(this->texture[sampler]) this->texture[sampler]->unbind(); textureCaptured[sampler] = true; this->texture[sampler] = texture; } void Direct3DStateBlock9::setTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value) { textureStageStateCaptured[stage][type] = true; textureStageState[stage][type] = value; } void Direct3DStateBlock9::setTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) { transformCaptured[state] = true; transform[state] = *matrix; } void Direct3DStateBlock9::setViewport(const D3DVIEWPORT9 *viewport) { viewportCaptured = true; this->viewport = *viewport; } void Direct3DStateBlock9::setVertexDeclaration(Direct3DVertexDeclaration9 *vertexDeclaration) { if(vertexDeclaration) vertexDeclaration->bind(); if(this->vertexDeclaration) this->vertexDeclaration->unbind(); vertexDeclarationCaptured = true; this->vertexDeclaration = vertexDeclaration; } void Direct3DStateBlock9::setVertexShader(Direct3DVertexShader9 *vertexShader) { if(vertexShader) vertexShader->bind(); if(this->vertexShader) this->vertexShader->unbind(); vertexShaderCaptured = true; this->vertexShader = vertexShader; } void Direct3DStateBlock9::setVertexShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count) { memcpy(&vertexShaderConstantB[startRegister], constantData, count * sizeof(int)); } void Direct3DStateBlock9::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) { memcpy(vertexShaderConstantF[startRegister], constantData, count * sizeof(float[4])); } void Direct3DStateBlock9::setVertexShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count) { memcpy(vertexShaderConstantI[startRegister], constantData, count * sizeof(int[4])); } void Direct3DStateBlock9::clear() { // Erase capture flags fvfCaptured = false; vertexDeclarationCaptured = false; indexBufferCaptured = false; for(int state = 0; state < D3DRS_BLENDOPALPHA + 1; state++) { renderStateCaptured[state] = false; } nPatchModeCaptured = false; for(int stage = 0; stage < 8; stage++) { for(int state = 0; state < D3DTSS_CONSTANT + 1; state++) { textureStageStateCaptured[stage][state] = false; } } for(int sampler = 0; sampler < 16 + 4; sampler++) { for(int state = 0; state < D3DSAMP_DMAPOFFSET + 1; state++) { samplerStateCaptured[sampler][state] = false; } } for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { streamSourceCaptured[stream] = false; streamSourceFrequencyCaptured[stream] = false; } for(int sampler = 0; sampler < 16 + 4; sampler++) { textureCaptured[sampler] = false; } for(int state = 0; state < 512; state++) { transformCaptured[state] = false; } materialCaptured = false; for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { lightCaptured[index] = false; } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { lightEnableCaptured[index] = false; } scissorRectCaptured = false; pixelShaderCaptured = false; vertexShaderCaptured = false; viewportCaptured = false; for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++) { (int&)pixelShaderConstantF[i][0] = 0x80000000; (int&)pixelShaderConstantF[i][1] = 0x80000000; (int&)pixelShaderConstantF[i][2] = 0x80000000; (int&)pixelShaderConstantF[i][3] = 0x80000000; } for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++) { (int&)vertexShaderConstantF[i][0] = 0x80000000; (int&)vertexShaderConstantF[i][1] = 0x80000000; (int&)vertexShaderConstantF[i][2] = 0x80000000; (int&)vertexShaderConstantF[i][3] = 0x80000000; } for(int i = 0; i < 16; i++) { pixelShaderConstantI[i][0] = 0x80000000; pixelShaderConstantI[i][1] = 0x80000000; pixelShaderConstantI[i][2] = 0x80000000; pixelShaderConstantI[i][3] = 0x80000000; pixelShaderConstantB[i] = 0x80000000; vertexShaderConstantI[i][0] = 0x80000000; vertexShaderConstantI[i][1] = 0x80000000; vertexShaderConstantI[i][2] = 0x80000000; vertexShaderConstantI[i][3] = 0x80000000; vertexShaderConstantB[i] = 0x80000000; } for(int index = 0; index < 6; index++) { clipPlaneCaptured[index] = false; } paletteNumberCaptured = false; // unbind resources if(vertexDeclaration) { vertexDeclaration->unbind(); vertexDeclaration = 0; } if(indexBuffer) { indexBuffer->unbind(); indexBuffer = 0; } for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { if(streamSource[stream].vertexBuffer) { streamSource[stream].vertexBuffer->unbind(); streamSource[stream].vertexBuffer = 0; } } for(int sampler = 0; sampler < 16 + 4; sampler++) { if(texture[sampler]) { texture[sampler]->unbind(); texture[sampler] = 0; } } if(pixelShader) { pixelShader->unbind(); pixelShader = 0; } if(vertexShader) { vertexShader->unbind(); vertexShader = 0; } } void Direct3DStateBlock9::captureRenderState(D3DRENDERSTATETYPE state) { device->GetRenderState(state, &renderState[state]); renderStateCaptured[state] = true; } void Direct3DStateBlock9::captureSamplerState(unsigned long index, D3DSAMPLERSTATETYPE state) { if(index < 16) { device->GetSamplerState(index, state, &samplerState[index][state]); samplerStateCaptured[index][state] = true; } else if(index >= D3DVERTEXTEXTURESAMPLER0) { unsigned int sampler = 16 + (index - D3DVERTEXTEXTURESAMPLER0); device->GetSamplerState(index, state, &samplerState[sampler][state]); samplerStateCaptured[sampler][state] = true; } } void Direct3DStateBlock9::captureTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type) { device->GetTextureStageState(stage, type, &textureStageState[stage][type]); textureStageStateCaptured[stage][type] = true; } void Direct3DStateBlock9::captureTransform(D3DTRANSFORMSTATETYPE state) { device->GetTransform(state, &transform[state]); transformCaptured[state] = true; } void Direct3DStateBlock9::capturePixelRenderStates() { captureRenderState(D3DRS_ZENABLE); captureRenderState(D3DRS_FILLMODE); captureRenderState(D3DRS_SHADEMODE); captureRenderState(D3DRS_ZWRITEENABLE); captureRenderState(D3DRS_ALPHATESTENABLE); captureRenderState(D3DRS_LASTPIXEL); captureRenderState(D3DRS_SRCBLEND); captureRenderState(D3DRS_DESTBLEND); captureRenderState(D3DRS_ZFUNC); captureRenderState(D3DRS_ALPHAREF); captureRenderState(D3DRS_ALPHAFUNC); captureRenderState(D3DRS_DITHERENABLE); captureRenderState(D3DRS_FOGSTART); captureRenderState(D3DRS_FOGEND); captureRenderState(D3DRS_FOGDENSITY); captureRenderState(D3DRS_ALPHABLENDENABLE); captureRenderState(D3DRS_DEPTHBIAS); captureRenderState(D3DRS_STENCILENABLE); captureRenderState(D3DRS_STENCILFAIL); captureRenderState(D3DRS_STENCILZFAIL); captureRenderState(D3DRS_STENCILPASS); captureRenderState(D3DRS_STENCILFUNC); captureRenderState(D3DRS_STENCILREF); captureRenderState(D3DRS_STENCILMASK); captureRenderState(D3DRS_STENCILWRITEMASK); captureRenderState(D3DRS_TEXTUREFACTOR); captureRenderState(D3DRS_WRAP0); captureRenderState(D3DRS_WRAP1); captureRenderState(D3DRS_WRAP2); captureRenderState(D3DRS_WRAP3); captureRenderState(D3DRS_WRAP4); captureRenderState(D3DRS_WRAP5); captureRenderState(D3DRS_WRAP6); captureRenderState(D3DRS_WRAP7); captureRenderState(D3DRS_WRAP8); captureRenderState(D3DRS_WRAP9); captureRenderState(D3DRS_WRAP10); captureRenderState(D3DRS_WRAP11); captureRenderState(D3DRS_WRAP12); captureRenderState(D3DRS_WRAP13); captureRenderState(D3DRS_WRAP14); captureRenderState(D3DRS_WRAP15); captureRenderState(D3DRS_COLORWRITEENABLE); captureRenderState(D3DRS_BLENDOP); captureRenderState(D3DRS_SCISSORTESTENABLE); captureRenderState(D3DRS_SLOPESCALEDEPTHBIAS); captureRenderState(D3DRS_ANTIALIASEDLINEENABLE); captureRenderState(D3DRS_TWOSIDEDSTENCILMODE); captureRenderState(D3DRS_CCW_STENCILFAIL); captureRenderState(D3DRS_CCW_STENCILZFAIL); captureRenderState(D3DRS_CCW_STENCILPASS); captureRenderState(D3DRS_CCW_STENCILFUNC); captureRenderState(D3DRS_COLORWRITEENABLE1); captureRenderState(D3DRS_COLORWRITEENABLE2); captureRenderState(D3DRS_COLORWRITEENABLE3); captureRenderState(D3DRS_BLENDFACTOR); captureRenderState(D3DRS_SRGBWRITEENABLE); captureRenderState(D3DRS_SEPARATEALPHABLENDENABLE); captureRenderState(D3DRS_SRCBLENDALPHA); captureRenderState(D3DRS_DESTBLENDALPHA); captureRenderState(D3DRS_BLENDOPALPHA); } void Direct3DStateBlock9::capturePixelTextureStates() { for(int stage = 0; stage < 8; stage++) { captureTextureStageState(stage, D3DTSS_COLOROP); captureTextureStageState(stage, D3DTSS_COLORARG1); captureTextureStageState(stage, D3DTSS_COLORARG2); captureTextureStageState(stage, D3DTSS_ALPHAOP); captureTextureStageState(stage, D3DTSS_ALPHAARG1); captureTextureStageState(stage, D3DTSS_ALPHAARG2); captureTextureStageState(stage, D3DTSS_BUMPENVMAT00); captureTextureStageState(stage, D3DTSS_BUMPENVMAT01); captureTextureStageState(stage, D3DTSS_BUMPENVMAT10); captureTextureStageState(stage, D3DTSS_BUMPENVMAT11); captureTextureStageState(stage, D3DTSS_TEXCOORDINDEX); captureTextureStageState(stage, D3DTSS_BUMPENVLSCALE); captureTextureStageState(stage, D3DTSS_BUMPENVLOFFSET); captureTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS); captureTextureStageState(stage, D3DTSS_COLORARG0); captureTextureStageState(stage, D3DTSS_ALPHAARG0); captureTextureStageState(stage, D3DTSS_RESULTARG); } } void Direct3DStateBlock9::capturePixelSamplerStates() { for(int sampler = 0; sampler <= D3DVERTEXTEXTURESAMPLER3; sampler++) { captureSamplerState(sampler, D3DSAMP_ADDRESSU); captureSamplerState(sampler, D3DSAMP_ADDRESSV); captureSamplerState(sampler, D3DSAMP_ADDRESSW); captureSamplerState(sampler, D3DSAMP_BORDERCOLOR); captureSamplerState(sampler, D3DSAMP_MAGFILTER); captureSamplerState(sampler, D3DSAMP_MINFILTER); captureSamplerState(sampler, D3DSAMP_MIPFILTER); captureSamplerState(sampler, D3DSAMP_MIPMAPLODBIAS); captureSamplerState(sampler, D3DSAMP_MAXMIPLEVEL); captureSamplerState(sampler, D3DSAMP_MAXANISOTROPY); captureSamplerState(sampler, D3DSAMP_SRGBTEXTURE); captureSamplerState(sampler, D3DSAMP_ELEMENTINDEX); } } void Direct3DStateBlock9::capturePixelShaderStates() { pixelShaderCaptured = true; device->GetPixelShader(reinterpret_cast<IDirect3DPixelShader9**>(&pixelShader)); if(pixelShader) { pixelShader->bind(); pixelShader->Release(); } device->GetPixelShaderConstantF(0, pixelShaderConstantF[0], 32); device->GetPixelShaderConstantI(0, pixelShaderConstantI[0], 16); device->GetPixelShaderConstantB(0, pixelShaderConstantB, 16); } void Direct3DStateBlock9::captureVertexRenderStates() { captureRenderState(D3DRS_CULLMODE); captureRenderState(D3DRS_FOGENABLE); captureRenderState(D3DRS_FOGCOLOR); captureRenderState(D3DRS_FOGTABLEMODE); captureRenderState(D3DRS_FOGSTART); captureRenderState(D3DRS_FOGEND); captureRenderState(D3DRS_FOGDENSITY); captureRenderState(D3DRS_RANGEFOGENABLE); captureRenderState(D3DRS_AMBIENT); captureRenderState(D3DRS_COLORVERTEX); captureRenderState(D3DRS_FOGVERTEXMODE); captureRenderState(D3DRS_CLIPPING); captureRenderState(D3DRS_LIGHTING); captureRenderState(D3DRS_LOCALVIEWER); captureRenderState(D3DRS_EMISSIVEMATERIALSOURCE); captureRenderState(D3DRS_AMBIENTMATERIALSOURCE); captureRenderState(D3DRS_DIFFUSEMATERIALSOURCE); captureRenderState(D3DRS_SPECULARMATERIALSOURCE); captureRenderState(D3DRS_VERTEXBLEND); captureRenderState(D3DRS_CLIPPLANEENABLE); captureRenderState(D3DRS_POINTSIZE); captureRenderState(D3DRS_POINTSIZE_MIN); captureRenderState(D3DRS_POINTSPRITEENABLE); captureRenderState(D3DRS_POINTSCALEENABLE); captureRenderState(D3DRS_POINTSCALE_A); captureRenderState(D3DRS_POINTSCALE_B); captureRenderState(D3DRS_POINTSCALE_C); captureRenderState(D3DRS_MULTISAMPLEANTIALIAS); captureRenderState(D3DRS_MULTISAMPLEMASK); captureRenderState(D3DRS_PATCHEDGESTYLE); captureRenderState(D3DRS_POINTSIZE_MAX); captureRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE); captureRenderState(D3DRS_TWEENFACTOR); captureRenderState(D3DRS_POSITIONDEGREE); captureRenderState(D3DRS_NORMALDEGREE); captureRenderState(D3DRS_MINTESSELLATIONLEVEL); captureRenderState(D3DRS_MAXTESSELLATIONLEVEL); captureRenderState(D3DRS_ADAPTIVETESS_X); captureRenderState(D3DRS_ADAPTIVETESS_Y); captureRenderState(D3DRS_ADAPTIVETESS_Z); captureRenderState(D3DRS_ADAPTIVETESS_W); captureRenderState(D3DRS_ENABLEADAPTIVETESSELLATION); captureRenderState(D3DRS_NORMALIZENORMALS); captureRenderState(D3DRS_SPECULARENABLE); captureRenderState(D3DRS_SHADEMODE); } void Direct3DStateBlock9::captureVertexSamplerStates() { for(int sampler = 0; sampler <= D3DVERTEXTEXTURESAMPLER3; sampler++) { captureSamplerState(sampler, D3DSAMP_DMAPOFFSET); } } void Direct3DStateBlock9::captureVertexTextureStates() { for(int stage = 0; stage < 8; stage++) { captureTextureStageState(stage, D3DTSS_TEXCOORDINDEX); captureTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS); } } void Direct3DStateBlock9::captureNPatchMode() { nPatchMode = device->GetNPatchMode(); nPatchModeCaptured = true; } void Direct3DStateBlock9::captureLightStates() { for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { long result = device->GetLight(index, &light[index]); lightCaptured[index] = SUCCEEDED(result); } for(int index = 0; index < 8; index++) // FIXME: Support unlimited index { lightEnableState[index] = false; long result = device->GetLightEnable(index, &lightEnableState[index]); lightEnableCaptured[index] = SUCCEEDED(result); } } void Direct3DStateBlock9::captureVertexShaderStates() { vertexShaderCaptured = true; device->GetVertexShader(reinterpret_cast<IDirect3DVertexShader9**>(&vertexShader)); if(vertexShader) { vertexShader->bind(); vertexShader->Release(); } device->GetVertexShaderConstantF(0, vertexShaderConstantF[0], MAX_VERTEX_SHADER_CONST); device->GetVertexShaderConstantI(0, vertexShaderConstantI[0], 16); device->GetVertexShaderConstantB(0, vertexShaderConstantB, 16); } void Direct3DStateBlock9::captureStreamSourceFrequencies() { for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { streamSourceFrequencyCaptured[stream] = true; device->GetStreamSourceFreq(stream, &streamSourceFrequency[stream]); } } void Direct3DStateBlock9::captureFVF() { device->GetFVF(&FVF); fvfCaptured = true; } void Direct3DStateBlock9::captureVertexDeclaration() { vertexDeclarationCaptured = true; device->GetVertexDeclaration(reinterpret_cast<IDirect3DVertexDeclaration9**>(&vertexDeclaration)); if(vertexDeclaration) { vertexDeclaration->bind(); vertexDeclaration->Release(); } } void Direct3DStateBlock9::captureTextures() { for(int sampler = 0; sampler < 16 + 4; sampler++) { textureCaptured[sampler] = true; int index = sampler < 16 ? sampler : D3DVERTEXTEXTURESAMPLER0 + (sampler - 16); device->GetTexture(index, reinterpret_cast<IDirect3DBaseTexture9**>(&texture[sampler])); if(texture[sampler]) { texture[sampler]->bind(); texture[sampler]->Release(); } } } void Direct3DStateBlock9::captureTexturePalette() { paletteNumberCaptured = true; device->GetCurrentTexturePalette(&paletteNumber); } void Direct3DStateBlock9::captureVertexStreams() { for(int stream = 0; stream < MAX_VERTEX_INPUTS; stream++) { streamSourceCaptured[stream] = true; device->GetStreamSource(stream, reinterpret_cast<IDirect3DVertexBuffer9**>(&streamSource[stream].vertexBuffer), &streamSource[stream].offset, &streamSource[stream].stride); if(streamSource[stream].vertexBuffer) { streamSource[stream].vertexBuffer->bind(); streamSource[stream].vertexBuffer->Release(); } } } void Direct3DStateBlock9::captureIndexBuffer() { indexBufferCaptured = true; device->GetIndices(reinterpret_cast<IDirect3DIndexBuffer9**>(&indexBuffer)); if(indexBuffer) { indexBuffer->bind(); indexBuffer->Release(); } } void Direct3DStateBlock9::captureViewport() { device->GetViewport(&viewport); viewportCaptured = true; } void Direct3DStateBlock9::captureScissorRectangle() { device->GetScissorRect(&scissorRect); scissorRectCaptured = true; } void Direct3DStateBlock9::captureTransforms() { captureTransform(D3DTS_VIEW); captureTransform(D3DTS_PROJECTION); captureTransform(D3DTS_WORLD); } void Direct3DStateBlock9::captureTextureTransforms() { captureTransform(D3DTS_TEXTURE0); captureTransform(D3DTS_TEXTURE1); captureTransform(D3DTS_TEXTURE2); captureTransform(D3DTS_TEXTURE3); captureTransform(D3DTS_TEXTURE4); captureTransform(D3DTS_TEXTURE5); captureTransform(D3DTS_TEXTURE6); captureTransform(D3DTS_TEXTURE7); } void Direct3DStateBlock9::captureClippingPlanes() { for(int index = 0; index < 6; index++) { device->GetClipPlane(index, (float*)&clipPlane[index]); clipPlaneCaptured[index] = true; } } void Direct3DStateBlock9::captureMaterial() { device->GetMaterial(&material); materialCaptured = true; } }