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