|  | // 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; | 
|  | } | 
|  | } |