|  | // 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 "Direct3DDevice8.hpp" | 
|  |  | 
|  | #include "Direct3D8.hpp" | 
|  | #include "Direct3DSurface8.hpp" | 
|  | #include "Direct3DIndexBuffer8.hpp" | 
|  | #include "Direct3DVertexBuffer8.hpp" | 
|  | #include "Direct3DTexture8.hpp" | 
|  | #include "Direct3DVolumeTexture8.hpp" | 
|  | #include "Direct3DCubeTexture8.hpp" | 
|  | #include "Direct3DSwapChain8.hpp" | 
|  | #include "Direct3DPixelShader8.hpp" | 
|  | #include "Direct3DVertexShader8.hpp" | 
|  | #include "Direct3DVolume8.hpp" | 
|  |  | 
|  | #include "Debug.hpp" | 
|  | #include "Capabilities.hpp" | 
|  | #include "Renderer.hpp" | 
|  | #include "Config.hpp" | 
|  | #include "FrameBuffer.hpp" | 
|  | #include "Clipper.hpp" | 
|  | #include "Configurator.hpp" | 
|  | #include "Timer.hpp" | 
|  | #include "Resource.hpp" | 
|  |  | 
|  | #include <assert.h> | 
|  |  | 
|  | bool localShaderConstants = false; | 
|  |  | 
|  | namespace D3D8 | 
|  | { | 
|  | inline unsigned long FtoDW(float f)   // FIXME: Deprecate | 
|  | { | 
|  | return (unsigned long&)f; | 
|  | } | 
|  |  | 
|  | Direct3DDevice8::Direct3DDevice8(const HINSTANCE instance, Direct3D8 *d3d8, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), d3d8(d3d8), adapter(adapter), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags), presentParameters(*presentParameters) | 
|  | { | 
|  | init = true; | 
|  | recordState = false; | 
|  |  | 
|  | d3d8->AddRef(); | 
|  |  | 
|  | context = new sw::Context(); | 
|  | renderer = new sw::Renderer(context, sw::Direct3D, false); | 
|  |  | 
|  | swapChain.push_back(0); | 
|  | depthStencil = 0; | 
|  | renderTarget = 0; | 
|  |  | 
|  | for(int i = 0; i < 8; i++) | 
|  | { | 
|  | texture[i] = 0; | 
|  | } | 
|  |  | 
|  | cursor = 0; | 
|  | unsigned char one[32 * 32 / sizeof(unsigned char)]; | 
|  | memset(one, 0xFFFFFFFF, sizeof(one)); | 
|  | unsigned char zero[32 * 32 / sizeof(unsigned char)] = {0}; | 
|  | nullCursor = CreateCursor(instance, 0, 0, 32, 32, one, zero); | 
|  | win32Cursor = GetCursor(); | 
|  |  | 
|  | Reset(presentParameters); | 
|  |  | 
|  | pixelShader.push_back(0);   // pixelShader[0] = 0 | 
|  | vertexShader.push_back(0);   // vertexShader[0] = 0 | 
|  | vertexShaderHandle = 0; | 
|  | pixelShaderHandle = 0; | 
|  |  | 
|  | lightsDirty = true; | 
|  |  | 
|  | for(int i = 0; i < 16; i++) | 
|  | { | 
|  | dataStream[i] = 0; | 
|  | streamStride[i] = 0; | 
|  | } | 
|  |  | 
|  | indexData = 0; | 
|  | baseVertexIndex = 0; | 
|  | declaration = 0; | 
|  | FVF = 0; | 
|  |  | 
|  | D3DMATERIAL8 material; | 
|  |  | 
|  | material.Diffuse.r = 1.0f; | 
|  | material.Diffuse.g = 1.0f; | 
|  | material.Diffuse.b = 1.0f; | 
|  | material.Diffuse.a = 0.0f; | 
|  | material.Ambient.r = 0.0f; | 
|  | material.Ambient.g = 0.0f; | 
|  | material.Ambient.b = 0.0f; | 
|  | material.Ambient.a = 0.0f; | 
|  | material.Emissive.r = 0.0f; | 
|  | material.Emissive.g = 0.0f; | 
|  | material.Emissive.b = 0.0f; | 
|  | material.Emissive.a = 0.0f; | 
|  | material.Specular.r = 0.0f; | 
|  | material.Specular.g = 0.0f; | 
|  | material.Specular.b = 0.0f; | 
|  | material.Specular.a = 0.0f; | 
|  | material.Power = 0.0f; | 
|  |  | 
|  | SetMaterial(&material); | 
|  |  | 
|  | D3DMATRIX identity = {1, 0, 0, 0, | 
|  | 0, 1, 0, 0, | 
|  | 0, 0, 1, 0, | 
|  | 0, 0, 0, 1}; | 
|  |  | 
|  | SetTransform(D3DTS_VIEW, &identity); | 
|  | SetTransform(D3DTS_PROJECTION, &identity); | 
|  | SetTransform(D3DTS_TEXTURE0, &identity); | 
|  | SetTransform(D3DTS_TEXTURE1, &identity); | 
|  | SetTransform(D3DTS_TEXTURE2, &identity); | 
|  | SetTransform(D3DTS_TEXTURE3, &identity); | 
|  | SetTransform(D3DTS_TEXTURE4, &identity); | 
|  | SetTransform(D3DTS_TEXTURE5, &identity); | 
|  | SetTransform(D3DTS_TEXTURE6, &identity); | 
|  | SetTransform(D3DTS_TEXTURE7, &identity); | 
|  |  | 
|  | for(int i = 0; i < 12; i++) | 
|  | { | 
|  | SetTransform(D3DTS_WORLDMATRIX(i), &identity); | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 8; i++) | 
|  | { | 
|  | float zero[4] = {0, 0, 0, 0}; | 
|  |  | 
|  | SetPixelShaderConstant(i, zero, 1); | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 256; i++) | 
|  | { | 
|  | float zero[4] = {0, 0, 0, 0}; | 
|  |  | 
|  | SetVertexShaderConstant(i, zero, 1); | 
|  | } | 
|  |  | 
|  | init = false; | 
|  |  | 
|  | if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE)) | 
|  | { | 
|  | configureFPU(); | 
|  | } | 
|  | } | 
|  |  | 
|  | Direct3DDevice8::~Direct3DDevice8() | 
|  | { | 
|  | delete renderer; | 
|  | renderer = 0; | 
|  | delete context; | 
|  | context = 0; | 
|  |  | 
|  | d3d8->Release(); | 
|  | d3d8 = 0; | 
|  |  | 
|  | for(unsigned int i = 0; i < swapChain.size(); i++) | 
|  | { | 
|  | if(swapChain[i]) | 
|  | { | 
|  | swapChain[i]->unbind(); | 
|  | swapChain[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | if(depthStencil) | 
|  | { | 
|  | depthStencil->unbind(); | 
|  | depthStencil = 0; | 
|  | } | 
|  |  | 
|  | if(renderTarget) | 
|  | { | 
|  | renderTarget->unbind(); | 
|  | renderTarget = 0; | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 8; i++) | 
|  | { | 
|  | if(texture[i]) | 
|  | { | 
|  | texture[i]->unbind(); | 
|  | texture[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 16; i++) | 
|  | { | 
|  | if(dataStream[i]) | 
|  | { | 
|  | dataStream[i]->unbind(); | 
|  | dataStream[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | if(indexData) | 
|  | { | 
|  | indexData->unbind(); | 
|  | indexData = 0; | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < pixelShader.size(); i++) | 
|  | { | 
|  | if(pixelShader[i]) | 
|  | { | 
|  | pixelShader[i]->unbind(); | 
|  | pixelShader[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < vertexShader.size(); i++) | 
|  | { | 
|  | if(vertexShader[i]) | 
|  | { | 
|  | vertexShader[i]->unbind(); | 
|  | vertexShader[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < stateRecorder.size(); i++) | 
|  | { | 
|  | if(stateRecorder[i]) | 
|  | { | 
|  | stateRecorder[i]->unbind(); | 
|  | stateRecorder[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | palette.clear(); | 
|  |  | 
|  | delete cursor; | 
|  | DestroyCursor(nullCursor); | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::QueryInterface(const IID &iid, void **object) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(iid == IID_IDirect3DDevice8 || | 
|  | iid == IID_IUnknown) | 
|  | { | 
|  | AddRef(); | 
|  | *object = this; | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | *object = 0; | 
|  |  | 
|  | return NOINTERFACE(iid); | 
|  | } | 
|  |  | 
|  | unsigned long Direct3DDevice8::AddRef() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return Unknown::AddRef(); | 
|  | } | 
|  |  | 
|  | unsigned long Direct3DDevice8::Release() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return Unknown::Release(); | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::ApplyStateBlock(unsigned long token) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | stateRecorder[token]->Apply(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::BeginScene() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::BeginStateBlock() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | recordState = true; | 
|  | Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, (D3DSTATEBLOCKTYPE)0); | 
|  | stateBlock->bind(); | 
|  | stateRecorder.push_back(stateBlock); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CaptureStateBlock(unsigned long token) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | stateRecorder[token]->Capture(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil) | 
|  | { | 
|  | TRACE("unsigned long count = %d, const D3DRECT *rects = 0x%0.8p, unsigned long flags = 0x%0.8X, unsigned long color = 0x%0.8X, float z = %f, unsigned long stencil = %d", count, rects, flags, color, z, stencil); | 
|  |  | 
|  | if(!rects && count != 0) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(flags & D3DCLEAR_STENCIL)   // Check for stencil component | 
|  | { | 
|  | D3DSURFACE_DESC description; | 
|  | depthStencil->GetDesc(&description); | 
|  |  | 
|  | switch(description.Format) | 
|  | { | 
|  | case D3DFMT_D15S1: | 
|  | case D3DFMT_D24S8: | 
|  | case D3DFMT_D24X8: | 
|  | case D3DFMT_D24X4S4: | 
|  | break; | 
|  | case D3DFMT_D16_LOCKABLE: | 
|  | case D3DFMT_D32: | 
|  | case D3DFMT_D16: | 
|  | return INVALIDCALL(); | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  |  | 
|  | if(!rects) | 
|  | { | 
|  | count = 1; | 
|  |  | 
|  | D3DRECT rect; | 
|  | rect.x1 = viewport.X; | 
|  | rect.x2 = viewport.X + viewport.Width; | 
|  | rect.y1 = viewport.Y; | 
|  | rect.y2 = viewport.Y + viewport.Height; | 
|  |  | 
|  | rects = ▭ | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < count; i++) | 
|  | { | 
|  | sw::Rect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); | 
|  |  | 
|  | clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height); | 
|  |  | 
|  | if(flags & D3DCLEAR_TARGET) | 
|  | { | 
|  | if(renderTarget) | 
|  | { | 
|  | D3DSURFACE_DESC description; | 
|  | renderTarget->GetDesc(&description); | 
|  |  | 
|  | float rgba[4]; | 
|  | rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000; | 
|  | rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00; | 
|  | rgba[2] = (float)(color & 0x000000FF) / 0x000000FF; | 
|  | rgba[3] = (float)(color & 0xFF000000) / 0xFF000000; | 
|  |  | 
|  | renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget, clearRect, 0xF); | 
|  | } | 
|  | } | 
|  |  | 
|  | if(flags & D3DCLEAR_ZBUFFER) | 
|  | { | 
|  | z = sw::clamp01(z); | 
|  | depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); | 
|  | } | 
|  |  | 
|  | if(flags & D3DCLEAR_STENCIL) | 
|  | { | 
|  | depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); | 
|  | } | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CopyRects(IDirect3DSurface8 *sourceSurface, const RECT *sourceRectsArray, unsigned int rects, IDirect3DSurface8 *destinationSurface, const POINT *destPointsArray) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!sourceSurface || !destinationSurface) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(sourceRectsArray && rects == 0 || !sourceRectsArray && rects > 0) | 
|  | { | 
|  | return INVALIDCALL();   // FIXME: Verify REF behaviour | 
|  | } | 
|  |  | 
|  | D3DSURFACE_DESC sourceDescription; | 
|  | D3DSURFACE_DESC destDescription; | 
|  |  | 
|  | sourceSurface->GetDesc(&sourceDescription); | 
|  | destinationSurface->GetDesc(&destDescription); | 
|  |  | 
|  | if(sourceDescription.Format != destDescription.Format) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | int sWidth = sourceDescription.Width; | 
|  | int sHeight = sourceDescription.Height; | 
|  | int dWidth = destDescription.Width; | 
|  | int dHeight = destDescription.Height; | 
|  |  | 
|  | RECT sRect = {0, 0, sWidth, sHeight}; | 
|  | POINT dPoint = {0, 0}; | 
|  |  | 
|  | if(!sourceRectsArray || !destPointsArray) | 
|  | { | 
|  | sourceRectsArray = &sRect; | 
|  | destPointsArray = &dPoint; | 
|  |  | 
|  | rects = 1; | 
|  | } | 
|  |  | 
|  | int bpp = 8 * Direct3DSurface8::bytes(sourceDescription.Format); | 
|  |  | 
|  | for(unsigned int i = 0; i < rects; i++) | 
|  | { | 
|  | const RECT &sRect = sourceRectsArray[i]; | 
|  | const POINT &dPoint = destPointsArray[i]; | 
|  |  | 
|  | int rWidth = sRect.right - sRect.left; | 
|  | int rHeight = sRect.bottom - sRect.top; | 
|  |  | 
|  | RECT dRect; | 
|  |  | 
|  | dRect.top = dPoint.y; | 
|  | dRect.left = dPoint.x; | 
|  | dRect.bottom = dPoint.y + rHeight; | 
|  | dRect.right = dPoint.x + rWidth; | 
|  |  | 
|  | D3DLOCKED_RECT sourceLock; | 
|  | D3DLOCKED_RECT destLock; | 
|  |  | 
|  | sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY); | 
|  | destinationSurface->LockRect(&destLock, &dRect, D3DLOCK_DISCARD); | 
|  |  | 
|  | for(int y = 0; y < rHeight; y++) | 
|  | { | 
|  | switch(sourceDescription.Format) | 
|  | { | 
|  | case D3DFMT_DXT1: | 
|  | case D3DFMT_DXT2: | 
|  | case D3DFMT_DXT3: | 
|  | case D3DFMT_DXT4: | 
|  | case D3DFMT_DXT5: | 
|  | memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8); | 
|  | y += 3;   // Advance four lines at once | 
|  | break; | 
|  | default: | 
|  | memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8); | 
|  | } | 
|  |  | 
|  | (char*&)sourceLock.pBits += sourceLock.Pitch; | 
|  | (char*&)destLock.pBits += destLock.Pitch; | 
|  | } | 
|  |  | 
|  | sourceSurface->UnlockRect(); | 
|  | destinationSurface->UnlockRect(); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain8 **swapChain) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *swapChain = 0; | 
|  |  | 
|  | if(!presentParameters || !swapChain) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(presentParameters->BackBufferCount > 3) | 
|  | { | 
|  | return INVALIDCALL();   // Maximum of three back buffers | 
|  | } | 
|  |  | 
|  | if(presentParameters->BackBufferCount == 0) | 
|  | { | 
|  | presentParameters->BackBufferCount = 1; | 
|  | } | 
|  |  | 
|  | D3DPRESENT_PARAMETERS present = *presentParameters; | 
|  |  | 
|  | *swapChain = new Direct3DSwapChain8(this, &present); | 
|  |  | 
|  | if(!*swapChain) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *swapChain; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | this->swapChain.push_back(static_cast<Direct3DSwapChain8*>(*swapChain)); | 
|  |  | 
|  | (*swapChain)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **cubeTexture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *cubeTexture = 0; | 
|  |  | 
|  | if(edgeLength == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *cubeTexture = new Direct3DCubeTexture8(this, edgeLength, levels, usage, format, pool); | 
|  |  | 
|  | if(!*cubeTexture) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *cubeTexture; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*cubeTexture)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, IDirect3DSurface8 **surface) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *surface = 0; | 
|  |  | 
|  | if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, format == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL); | 
|  |  | 
|  | if(!*surface) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *surface; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*surface)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateImageSurface(unsigned int width, unsigned int height, D3DFORMAT format, IDirect3DSurface8 **surface) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *surface = 0; | 
|  |  | 
|  | if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, true, 0); | 
|  |  | 
|  | if(!*surface) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *surface; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*surface)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **indexBuffer) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *indexBuffer = new Direct3DIndexBuffer8(this, length, usage, format, pool); | 
|  |  | 
|  | if(!*indexBuffer) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *indexBuffer; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*indexBuffer)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreatePixelShader(const unsigned long *function, unsigned long *handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!function || !handle || function[0] > pixelShaderVersion) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | unsigned int index; | 
|  |  | 
|  | for(index = 1; index < pixelShader.size(); index++)   // Skip NULL handle | 
|  | { | 
|  | if(pixelShader[index] == 0) | 
|  | { | 
|  | pixelShader[index] = new Direct3DPixelShader8(this, function);   // FIXME: Check for null | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if(index == pixelShader.size()) | 
|  | { | 
|  | pixelShader.push_back(new Direct3DPixelShader8(this, function)); | 
|  | } | 
|  |  | 
|  | pixelShader[index]->AddRef(); | 
|  |  | 
|  | *handle = index; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, int lockable, IDirect3DSurface8 **surface) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *surface = 0; | 
|  |  | 
|  | if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, lockable != FALSE, D3DUSAGE_RENDERTARGET); | 
|  |  | 
|  | if(!*surface) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *surface; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*surface)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateStateBlock(D3DSTATEBLOCKTYPE type, unsigned long *token) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!token) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, type); | 
|  | stateBlock->bind(); | 
|  | stateRecorder.push_back(stateBlock); | 
|  | *token = (unsigned long)(stateRecorder.size() - 1); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture8 **texture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *texture = 0; | 
|  |  | 
|  | if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *texture = new Direct3DTexture8(this, width, height, levels, usage, format, pool); | 
|  |  | 
|  | if(!*texture) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *texture; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*texture)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer8 **vertexBuffer) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *vertexBuffer = new Direct3DVertexBuffer8(this, length, usage, FVF, pool); | 
|  |  | 
|  | if(!*vertexBuffer) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *vertexBuffer; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*vertexBuffer)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateVertexShader(const unsigned long *declaration, const unsigned long *function, unsigned long *handle, unsigned long usage) | 
|  | { | 
|  | TRACE("const unsigned long *declaration = 0x%0.8p, const unsigned long *function = 0x%0.8p, unsigned long *handle = 0x%0.8p, unsigned long usage = %d", declaration, function, handle, usage); | 
|  |  | 
|  | if(!declaration || !handle || (function && function[0] > vertexShaderVersion)) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | unsigned int index; | 
|  |  | 
|  | for(index = 1; index < vertexShader.size(); index++)   // NOTE: skip NULL handle | 
|  | { | 
|  | if(vertexShader[index] == 0) | 
|  | { | 
|  | vertexShader[index] = new Direct3DVertexShader8(this, declaration, function);   // FIXME: Check for null | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if(index == vertexShader.size()) | 
|  | { | 
|  | vertexShader.push_back(new Direct3DVertexShader8(this, declaration, function)); | 
|  | } | 
|  |  | 
|  | vertexShader[index]->AddRef(); | 
|  |  | 
|  | *handle = (index << 16) + 1; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture8 **volumeTexture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | *volumeTexture = 0; | 
|  |  | 
|  | if(width == 0 || height == 0 || depth == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *volumeTexture = new Direct3DVolumeTexture8(this, width, height, depth, levels, usage, format, pool); | 
|  |  | 
|  | if(!*volumeTexture) | 
|  | { | 
|  | return OUTOFMEMORY(); | 
|  | } | 
|  |  | 
|  | if(GetAvailableTextureMem() == 0) | 
|  | { | 
|  | delete *volumeTexture; | 
|  |  | 
|  | return OUTOFVIDEOMEMORY(); | 
|  | } | 
|  |  | 
|  | (*volumeTexture)->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DeletePatch(unsigned int handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DeleteStateBlock(unsigned long token) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(token >= stateRecorder.size() || !stateRecorder[token]) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | stateRecorder[token]->unbind(); | 
|  | stateRecorder[token] = 0; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DeleteVertexShader(unsigned long handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | unsigned int index = handle >> 16; | 
|  |  | 
|  | if(index >= vertexShader.size() || !vertexShader[index]) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | vertexShader[index]->Release(); | 
|  | vertexShader[index] = 0; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!indexData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!bindData(indexData, baseVertexIndex) || !primitiveCount) | 
|  | { | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account | 
|  |  | 
|  | sw::DrawType drawType; | 
|  |  | 
|  | if(indexData->is32Bit()) | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  |  | 
|  | bindData(indexData, baseVertexIndex); | 
|  |  | 
|  | renderer->draw(drawType, indexOffset, primitiveCount); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DeletePixelShader(unsigned long handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(handle >= pixelShader.size() || !pixelShader[handle]) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | pixelShader[handle]->Release(); | 
|  | pixelShader[handle] = 0; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!vertexStreamZeroData || !indexData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | int length = (minIndex + numVertices) * vertexStreamZeroStride; | 
|  |  | 
|  | Direct3DVertexBuffer8 *vertexBuffer = new Direct3DVertexBuffer8(this, length, 0, 0, D3DPOOL_DEFAULT); | 
|  |  | 
|  | unsigned char *data; | 
|  | vertexBuffer->Lock(0, 0, &data, 0); | 
|  | memcpy(data, vertexStreamZeroData, length); | 
|  | vertexBuffer->Unlock(); | 
|  |  | 
|  | SetStreamSource(0, vertexBuffer, vertexStreamZeroStride); | 
|  |  | 
|  | switch(type) | 
|  | { | 
|  | case D3DPT_POINTLIST:		length = primitiveCount;		break; | 
|  | case D3DPT_LINELIST:		length = primitiveCount * 2;	break; | 
|  | case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break; | 
|  | case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break; | 
|  | case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break; | 
|  | case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | length *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2; | 
|  |  | 
|  | Direct3DIndexBuffer8 *indexBuffer = new Direct3DIndexBuffer8(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT); | 
|  |  | 
|  | indexBuffer->Lock(0, 0, &data, 0); | 
|  | memcpy(data, indexData, length); | 
|  | indexBuffer->Unlock(); | 
|  |  | 
|  | SetIndices(indexBuffer, 0); | 
|  |  | 
|  | if(!bindData(indexBuffer, 0) || !primitiveCount) | 
|  | { | 
|  | vertexBuffer->Release(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | sw::DrawType drawType; | 
|  |  | 
|  | if(indexDataFormat == D3DFMT_INDEX32) | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  |  | 
|  | renderer->draw(drawType, 0, primitiveCount); | 
|  |  | 
|  | SetStreamSource(0, 0, 0); | 
|  | SetIndices(0, 0); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!bindData(0, startVertex) || !primitiveCount) | 
|  | { | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | sw::DrawType drawType; | 
|  |  | 
|  | switch(primitiveType) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | renderer->draw(drawType, 0, primitiveCount); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!vertexStreamZeroData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | IDirect3DVertexBuffer8 *vertexBuffer = 0; | 
|  | int length = 0; | 
|  |  | 
|  | switch(primitiveType) | 
|  | { | 
|  | case D3DPT_POINTLIST:		length = primitiveCount;		break; | 
|  | case D3DPT_LINELIST:		length = primitiveCount * 2;	break; | 
|  | case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break; | 
|  | case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break; | 
|  | case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break; | 
|  | case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | length *= vertexStreamZeroStride; | 
|  |  | 
|  | CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer); | 
|  |  | 
|  | unsigned char *data; | 
|  | vertexBuffer->Lock(0, 0, &data, 0); | 
|  | memcpy(data, vertexStreamZeroData, length); | 
|  | vertexBuffer->Unlock(); | 
|  |  | 
|  | SetStreamSource(0, vertexBuffer, vertexStreamZeroStride); | 
|  |  | 
|  | if(!bindData(0, 0) || !primitiveCount) | 
|  | { | 
|  | vertexBuffer->Release(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | sw::DrawType drawType; | 
|  |  | 
|  | switch(primitiveType) | 
|  | { | 
|  | case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break; | 
|  | case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break; | 
|  | case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break; | 
|  | case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break; | 
|  | case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break; | 
|  | case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | renderer->draw(drawType, 0, primitiveCount); | 
|  |  | 
|  | SetStreamSource(0, 0, 0); | 
|  | vertexBuffer->Release(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!numSegs || !rectPatchInfo) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!numSegs || !triPatchInfo) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::EndScene() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::EndStateBlock(unsigned long *token) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!token) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | recordState = false; | 
|  | *token = (unsigned long)(stateRecorder.size() - 1); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | unsigned int Direct3DDevice8::GetAvailableTextureMem() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | int availableMemory = textureMemory - Direct3DResource8::getMemoryUsage(); | 
|  | if(availableMemory < 0) availableMemory = 0; | 
|  |  | 
|  | // Round to nearest MB | 
|  | return (availableMemory + 0x80000) & 0xFFF00000; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface8 **backBuffer) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | swapChain[index]->GetBackBuffer(index, type, backBuffer); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetClipPlane(unsigned long index, float *plane) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!plane || index >= 6) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | plane[0] = this->plane[index][0]; | 
|  | plane[1] = this->plane[index][1]; | 
|  | plane[2] = this->plane[index][2]; | 
|  | plane[3] = this->plane[index][3]; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetClipStatus(D3DCLIPSTATUS8 *clipStatus) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!clipStatus) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *clipStatus = this->clipStatus; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!parameters) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | parameters->AdapterOrdinal = adapter; | 
|  | parameters->BehaviorFlags = behaviourFlags; | 
|  | parameters->DeviceType = deviceType; | 
|  | parameters->hFocusWindow = focusWindow; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetCurrentTexturePalette(unsigned int *paletteNumber) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!paletteNumber) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *paletteNumber = currentPalette; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetDepthStencilSurface(IDirect3DSurface8 **depthStencilSurface) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!depthStencilSurface) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *depthStencilSurface = depthStencil; | 
|  |  | 
|  | if(depthStencil) | 
|  | { | 
|  | depthStencil->AddRef(); | 
|  | } | 
|  |  | 
|  | return D3D_OK;   // FIXME: Return NOTFOUND() when no depthStencil? | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetDeviceCaps(D3DCAPS8 *caps) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return d3d8->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps); | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetDirect3D(IDirect3D8 **d3d8) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!d3d8) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | ASSERT(this->d3d8); | 
|  |  | 
|  | *d3d8 = this->d3d8; | 
|  | this->d3d8->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetDisplayMode(D3DDISPLAYMODE *mode) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!mode) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | d3d8->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, mode); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetFrontBuffer(IDirect3DSurface8 *destSurface) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!destSurface) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DLOCKED_RECT description; | 
|  | destSurface->LockRect(&description, 0, 0); | 
|  |  | 
|  | swapChain[0]->screenshot(description.pBits); | 
|  |  | 
|  | destSurface->UnlockRect(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::GetGammaRamp(D3DGAMMARAMP *ramp) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!ramp) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | swapChain[0]->getGammaRamp((sw::GammaRamp*)ramp); | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetIndices(IDirect3DIndexBuffer8 **indexData, unsigned int *baseVertexIndex) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!indexData || !baseVertexIndex) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *indexData = this->indexData; | 
|  |  | 
|  | if(this->indexData) | 
|  | { | 
|  | this->indexData->AddRef(); | 
|  | } | 
|  |  | 
|  | *baseVertexIndex = this->baseVertexIndex; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetInfo(unsigned long devInfoID, void *devInfoStruct, unsigned long devInfoStructSize) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!devInfoStruct || devInfoStructSize == 0) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | switch(devInfoID) | 
|  | { | 
|  | case 0: return E_FAIL; | 
|  | case 1: return E_FAIL; | 
|  | case 2: return E_FAIL; | 
|  | case 3: return E_FAIL; | 
|  | case 4: return S_FALSE; | 
|  | case 5: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_RESOURCEMANAGER | 
|  | case 6: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_D3DVERTEXSTATS | 
|  | case 7: return E_FAIL; | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetLight(unsigned long index, D3DLIGHT8 *light) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!light) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!this->light.exists(index)) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *light = this->light[index]; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetLightEnable(unsigned long index , int *enable) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!enable) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!light.exists(index)) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *enable = light[index].enable; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetMaterial(D3DMATERIAL8 *material) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!material) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *material = this->material; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(paletteNumber > 0xFFFF || !entries) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 256; i++) | 
|  | { | 
|  | entries[i] = palette[paletteNumber].entry[i]; | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetPixelShader(unsigned long *handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!handle) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *handle = pixelShaderHandle; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetPixelShaderFunction(unsigned long handle, void *data, unsigned long *size) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!data) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetPixelShaderConstant(unsigned long startRegister, void *constantData, unsigned long count) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!constantData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < count; i++) | 
|  | { | 
|  | ((float*)constantData)[i * 4 + 0] = pixelShaderConstant[startRegister + i][0]; | 
|  | ((float*)constantData)[i * 4 + 1] = pixelShaderConstant[startRegister + i][1]; | 
|  | ((float*)constantData)[i * 4 + 2] = pixelShaderConstant[startRegister + i][2]; | 
|  | ((float*)constantData)[i * 4 + 3] = pixelShaderConstant[startRegister + i][3]; | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetRasterStatus(D3DRASTER_STATUS *rasterStatus) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!rasterStatus) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!value) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *value = renderState[state]; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetRenderTarget(IDirect3DSurface8 **renderTarget) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!renderTarget) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *renderTarget = this->renderTarget; | 
|  | this->renderTarget->AddRef(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer8 **streamData, unsigned int *stride) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(streamNumber >= 16 || !streamData || !stride) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *streamData = dataStream[streamNumber]; | 
|  |  | 
|  | if(dataStream[streamNumber]) | 
|  | { | 
|  | dataStream[streamNumber]->AddRef(); | 
|  | } | 
|  |  | 
|  | *stride = 0;   // NOTE: Unimplemented | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetTexture(unsigned long stage, IDirect3DBaseTexture8 **texture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!texture || stage >= 8) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *texture = this->texture[stage]; | 
|  |  | 
|  | if(this->texture[stage]) | 
|  | { | 
|  | this->texture[stage]->AddRef(); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE state, unsigned long *value) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!value  || stage < 0 || stage >= 8 || state < 0 || state > D3DTSS_RESULTARG)   // FIXME: Set *value to 0? | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *value = textureStageState[stage][state]; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!matrix || state < 0 || state > 511) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *matrix = this->matrix[state]; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetVertexShader(unsigned long *handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!handle) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *handle = vertexShaderHandle; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetVertexShaderConstant(unsigned long startRegister, void *constantData, unsigned long count) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!constantData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < count; i++) | 
|  | { | 
|  | ((float*)constantData)[i * 4 + 0] = vertexShaderConstant[startRegister + i][0]; | 
|  | ((float*)constantData)[i * 4 + 1] = vertexShaderConstant[startRegister + i][1]; | 
|  | ((float*)constantData)[i * 4 + 2] = vertexShaderConstant[startRegister + i][2]; | 
|  | ((float*)constantData)[i * 4 + 3] = vertexShaderConstant[startRegister + i][3]; | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetVertexShaderDeclaration(unsigned long handle, void *data, unsigned long *size) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!data || !size) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetVertexShaderFunction(unsigned long handle, void *data, unsigned long *size) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!data || !size) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::GetViewport(D3DVIEWPORT8 *viewport) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!viewport) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *viewport = this->viewport; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::LightEnable(unsigned long index, int enable) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(!light.exists(index))   // Insert default light | 
|  | { | 
|  | D3DLIGHT8 light; | 
|  |  | 
|  | light.Type = D3DLIGHT_DIRECTIONAL; | 
|  | light.Diffuse.r = 1; | 
|  | light.Diffuse.g = 1; | 
|  | light.Diffuse.b = 1; | 
|  | light.Diffuse.a = 0; | 
|  | light.Specular.r = 0; | 
|  | light.Specular.g = 0; | 
|  | light.Specular.b = 0; | 
|  | light.Specular.a = 0; | 
|  | light.Ambient.r = 0; | 
|  | light.Ambient.g = 0; | 
|  | light.Ambient.b = 0; | 
|  | light.Ambient.a = 0; | 
|  | light.Position.x = 0; | 
|  | light.Position.y = 0; | 
|  | light.Position.z = 0; | 
|  | light.Direction.x = 0; | 
|  | light.Direction.y = 0; | 
|  | light.Direction.z = 1; | 
|  | light.Range = 0; | 
|  | light.Falloff = 0; | 
|  | light.Attenuation0 = 0; | 
|  | light.Attenuation1 = 0; | 
|  | light.Attenuation2 = 0; | 
|  | light.Theta = 0; | 
|  | light.Phi = 0; | 
|  |  | 
|  | SetLight(index, &light); | 
|  | } | 
|  |  | 
|  | light[index].enable = (enable != FALSE); | 
|  |  | 
|  | lightsDirty = true; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->lightEnable(index, enable); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!matrix) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DMATRIX *current = &this->matrix[state]; | 
|  |  | 
|  | sw::Matrix C(current->_11, current->_21, current->_31, current->_41, | 
|  | current->_12, current->_22, current->_32, current->_42, | 
|  | current->_13, current->_23, current->_33, current->_43, | 
|  | current->_14, current->_24, current->_34, current->_44); | 
|  |  | 
|  | sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41, | 
|  | matrix->_12, matrix->_22, matrix->_32, matrix->_42, | 
|  | matrix->_13, matrix->_23, matrix->_33, matrix->_43, | 
|  | matrix->_14, matrix->_24, matrix->_34, matrix->_44); | 
|  |  | 
|  | switch(state) | 
|  | { | 
|  | case D3DTS_WORLD: | 
|  | renderer->setModelMatrix(C * M); | 
|  | break; | 
|  | case D3DTS_VIEW: | 
|  | renderer->setViewMatrix(C * M); | 
|  | break; | 
|  | case D3DTS_PROJECTION: | 
|  | renderer->setProjectionMatrix(C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE0: | 
|  | renderer->setTextureMatrix(0, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE1: | 
|  | renderer->setTextureMatrix(1, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE2: | 
|  | renderer->setTextureMatrix(2, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE3: | 
|  | renderer->setTextureMatrix(3, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE4: | 
|  | renderer->setTextureMatrix(4, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE5: | 
|  | renderer->setTextureMatrix(5, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE6: | 
|  | renderer->setTextureMatrix(6, C * M); | 
|  | break; | 
|  | case D3DTS_TEXTURE7: | 
|  | renderer->setTextureMatrix(7, C * M); | 
|  | break; | 
|  | default: | 
|  | if(state > 256 && state < 512) | 
|  | { | 
|  | renderer->setModelMatrix(C * M, state - 256); | 
|  | } | 
|  | else ASSERT(false); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | // NOTE: sourceRect and destRect can be null, dirtyRegion has to be null | 
|  |  | 
|  | HWND windowHandle = presentParameters.hDeviceWindow ? presentParameters.hDeviceWindow : focusWindow; | 
|  |  | 
|  | if(destWindowOverride && destWindowOverride != windowHandle) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  |  | 
|  | if(dirtyRegion) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | swapChain[0]->Present(sourceRect, destRect, destWindowOverride, dirtyRegion); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer8 *destBuffer, unsigned long flags) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!destBuffer) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::Reset(D3DPRESENT_PARAMETERS *presentParameters) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!presentParameters) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(swapChain[0]) | 
|  | { | 
|  | swapChain[0]->unbind(); | 
|  | swapChain[0] = 0; | 
|  | } | 
|  |  | 
|  | if(depthStencil) | 
|  | { | 
|  | depthStencil->unbind(); | 
|  | depthStencil = 0; | 
|  | } | 
|  |  | 
|  | if(renderTarget) | 
|  | { | 
|  | renderTarget->unbind(); | 
|  | renderTarget = 0; | 
|  | } | 
|  |  | 
|  | D3DPRESENT_PARAMETERS present = *presentParameters; | 
|  |  | 
|  | if(!swapChain[0]) | 
|  | { | 
|  | swapChain[0] = new Direct3DSwapChain8(this, &present); | 
|  | swapChain[0]->bind(); | 
|  | } | 
|  | else | 
|  | { | 
|  | swapChain[0]->reset(&present); | 
|  | } | 
|  |  | 
|  | HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : focusWindow; | 
|  |  | 
|  | int width = 0; | 
|  | int height = 0; | 
|  |  | 
|  | if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0)) | 
|  | { | 
|  | RECT rectangle; | 
|  | GetClientRect(windowHandle, &rectangle); | 
|  |  | 
|  | width = rectangle.right - rectangle.left; | 
|  | height = rectangle.bottom - rectangle.top; | 
|  | } | 
|  | else | 
|  | { | 
|  | width = presentParameters->BackBufferWidth; | 
|  | height = presentParameters->BackBufferHeight; | 
|  | } | 
|  |  | 
|  | if(presentParameters->EnableAutoDepthStencil != FALSE) | 
|  | { | 
|  | depthStencil = new Direct3DSurface8(this, this, width, height, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->AutoDepthStencilFormat == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL); | 
|  | depthStencil->bind(); | 
|  | } | 
|  |  | 
|  | IDirect3DSurface8 *renderTarget; | 
|  | swapChain[0]->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget); | 
|  | SetRenderTarget(renderTarget, depthStencil); | 
|  | renderTarget->Release(); | 
|  |  | 
|  | SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE); | 
|  | SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); | 
|  | SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); | 
|  | SetRenderState(D3DRS_ZWRITEENABLE, TRUE); | 
|  | SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); | 
|  | SetRenderState(D3DRS_LASTPIXEL, TRUE); | 
|  | SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); | 
|  | SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); | 
|  | SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); | 
|  | SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); | 
|  | SetRenderState(D3DRS_ALPHAREF, 0); | 
|  | SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); | 
|  | SetRenderState(D3DRS_DITHERENABLE, FALSE); | 
|  | SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); | 
|  | SetRenderState(D3DRS_FOGENABLE, FALSE); | 
|  | SetRenderState(D3DRS_SPECULARENABLE, FALSE); | 
|  | //	SetRenderState(D3DRS_ZVISIBLE, 0); | 
|  | SetRenderState(D3DRS_FOGCOLOR, 0); | 
|  | SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); | 
|  | SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f)); | 
|  | SetRenderState(D3DRS_FOGEND, FtoDW(1.0f)); | 
|  | SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f)); | 
|  | SetRenderState(D3DRS_EDGEANTIALIAS, FALSE); | 
|  | SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); | 
|  | SetRenderState(D3DRS_ZBIAS, 0); | 
|  | SetRenderState(D3DRS_STENCILENABLE, FALSE); | 
|  | SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); | 
|  | SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); | 
|  | SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); | 
|  | SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); | 
|  | SetRenderState(D3DRS_STENCILREF, 0); | 
|  | SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF); | 
|  | SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); | 
|  | SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF); | 
|  | SetRenderState(D3DRS_WRAP0, 0); | 
|  | SetRenderState(D3DRS_WRAP1, 0); | 
|  | SetRenderState(D3DRS_WRAP2, 0); | 
|  | SetRenderState(D3DRS_WRAP3, 0); | 
|  | SetRenderState(D3DRS_WRAP4, 0); | 
|  | SetRenderState(D3DRS_WRAP5, 0); | 
|  | SetRenderState(D3DRS_WRAP6, 0); | 
|  | SetRenderState(D3DRS_WRAP7, 0); | 
|  | SetRenderState(D3DRS_CLIPPING, TRUE); | 
|  | SetRenderState(D3DRS_LIGHTING, TRUE); | 
|  | SetRenderState(D3DRS_AMBIENT, 0); | 
|  | SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE); | 
|  | SetRenderState(D3DRS_COLORVERTEX, TRUE); | 
|  | SetRenderState(D3DRS_LOCALVIEWER, TRUE); | 
|  | SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); | 
|  | SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); | 
|  | SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2); | 
|  | SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); | 
|  | SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); | 
|  | SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); | 
|  | SetRenderState(D3DRS_CLIPPLANEENABLE, 0); | 
|  | SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE); | 
|  | SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f)); | 
|  | SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.0f)); | 
|  | SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); | 
|  | SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); | 
|  | SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f)); | 
|  | SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f)); | 
|  | SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f)); | 
|  | SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); | 
|  | SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); | 
|  | SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE); | 
|  | SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE); | 
|  | SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f)); | 
|  | SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); | 
|  | SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F); | 
|  | SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f)); | 
|  | SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | 
|  | SetRenderState(D3DRS_POSITIONORDER, D3DORDER_CUBIC); | 
|  | SetRenderState(D3DRS_NORMALORDER, D3DORDER_LINEAR); | 
|  |  | 
|  | for(int i = 0; i < 8; i++) | 
|  | { | 
|  | SetTexture(i, 0); | 
|  |  | 
|  | SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE); | 
|  | SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned | 
|  | SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); | 
|  | SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE); | 
|  | SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned | 
|  | SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i); | 
|  | SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); | 
|  | SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); | 
|  | SetTextureStageState(i, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP); | 
|  | SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000); | 
|  | SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT); | 
|  | SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT); | 
|  | SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE); | 
|  | SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0); | 
|  | SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0); | 
|  | SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f)); | 
|  | SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); | 
|  | SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT); | 
|  | SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT); | 
|  | SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT); | 
|  | } | 
|  |  | 
|  | currentPalette = 0xFFFF; | 
|  |  | 
|  | delete cursor; | 
|  | showCursor = false; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::ResourceManagerDiscardBytes(unsigned long bytes) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetClipPlane(unsigned long index, const float *plane) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!plane || index > 6) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | this->plane[index][0] = plane[0]; | 
|  | this->plane[index][1] = plane[1]; | 
|  | this->plane[index][2] = plane[2]; | 
|  | this->plane[index][3] = plane[3]; | 
|  |  | 
|  | renderer->setClipPlane(index, plane); | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setClipPlane(index, plane); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetClipStatus(const D3DCLIPSTATUS8 *clipStatus) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!clipStatus) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | this->clipStatus = *clipStatus; | 
|  |  | 
|  | UNIMPLEMENTED(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetCurrentTexturePalette(unsigned int paletteNumber) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end()) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | currentPalette = paletteNumber; | 
|  |  | 
|  | sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]); | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setCurrentTexturePalette(paletteNumber); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::SetCursorPosition(int x, int y, unsigned long flags) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | POINT point = {x, y}; | 
|  | HWND window = focusWindow ? focusWindow : presentParameters.hDeviceWindow; | 
|  | ScreenToClient(window, &point); | 
|  |  | 
|  | sw::FrameBuffer::setCursorPosition(point.x, point.y); | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface8 *cursorBitmap) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!cursorBitmap) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DSURFACE_DESC desc; | 
|  | D3DLOCKED_RECT lock; | 
|  |  | 
|  | cursorBitmap->GetDesc(&desc); | 
|  | cursorBitmap->LockRect(&lock, 0, 0); | 
|  |  | 
|  | delete cursor; | 
|  | cursor = sw::Surface::create(0, desc.Width, desc.Height, 1, 0, 1, sw::FORMAT_A8R8G8B8, false, false); | 
|  |  | 
|  | void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC); | 
|  | memcpy(buffer, lock.pBits, desc.Width * desc.Height * sizeof(unsigned int)); | 
|  | cursor->unlockExternal(); | 
|  |  | 
|  | cursorBitmap->UnlockRect(); | 
|  |  | 
|  | sw::FrameBuffer::setCursorOrigin(x0, y0); | 
|  |  | 
|  | bindCursor(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::SetGammaRamp(unsigned long flags, const D3DGAMMARAMP *ramp) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!ramp) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | swapChain[0]->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetLight(unsigned long index, const D3DLIGHT8 *light) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!light) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | this->light[index] = *light; | 
|  |  | 
|  | lightsDirty = true; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setLight(index, light); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetMaterial(const D3DMATERIAL8 *material) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!material) | 
|  | { | 
|  | return INVALIDCALL();   // FIXME: Correct behaviour? | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | this->material = *material; | 
|  |  | 
|  | renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a)); | 
|  | renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a)); | 
|  | renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a)); | 
|  | renderer->setMaterialShininess(material->Power); | 
|  | renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a)); | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setMaterial(material); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(paletteNumber > 0xFFFF || !entries) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | for(int i = 0; i < 256; i++) | 
|  | { | 
|  | palette[paletteNumber].entry[i] = entries[i]; | 
|  | } | 
|  |  | 
|  | if(paletteNumber == currentPalette) | 
|  | { | 
|  | sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetPixelShader(unsigned long handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(pixelShader[handle]) | 
|  | { | 
|  | pixelShader[handle]->bind(); | 
|  | } | 
|  |  | 
|  | if(pixelShader[pixelShaderHandle]) | 
|  | { | 
|  | pixelShader[pixelShaderHandle]->unbind(); | 
|  | } | 
|  |  | 
|  | pixelShaderHandle = handle; | 
|  |  | 
|  | if(handle != 0) | 
|  | { | 
|  | renderer->setPixelShader(pixelShader[handle]->getPixelShader()); | 
|  | } | 
|  | else | 
|  | { | 
|  | renderer->setPixelShader(0); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setPixelShader(handle); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetPixelShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | for(unsigned int i = 0; i < count; i++) | 
|  | { | 
|  | pixelShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0]; | 
|  | pixelShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1]; | 
|  | pixelShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2]; | 
|  | pixelShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3]; | 
|  | } | 
|  |  | 
|  | renderer->setPixelShaderConstantF(startRegister, (const float*)constantData, count); | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setPixelShaderConstant(startRegister, constantData, count); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value) | 
|  | { | 
|  | TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value); | 
|  |  | 
|  | if(state < D3DRS_ZENABLE || state > D3DRS_NORMALORDER) | 
|  | { | 
|  | return D3D_OK;   // FIXME: Warning | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(!init && renderState[state] == value) | 
|  | { | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | renderState[state] = value; | 
|  |  | 
|  | switch(state) | 
|  | { | 
|  | case D3DRS_ZENABLE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DZB_TRUE: | 
|  | case D3DZB_USEW: | 
|  | renderer->setDepthBufferEnable(true); | 
|  | break; | 
|  | case D3DZB_FALSE: | 
|  | renderer->setDepthBufferEnable(false); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_FILLMODE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DFILL_POINT: | 
|  | renderer->setFillMode(sw::FILL_VERTEX); | 
|  | break; | 
|  | case D3DFILL_WIREFRAME: | 
|  | renderer->setFillMode(sw::FILL_WIREFRAME); | 
|  | break; | 
|  | case D3DFILL_SOLID: | 
|  | renderer->setFillMode(sw::FILL_SOLID); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_SHADEMODE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DSHADE_FLAT: | 
|  | renderer->setShadingMode(sw::SHADING_FLAT); | 
|  | break; | 
|  | case D3DSHADE_GOURAUD: | 
|  | renderer->setShadingMode(sw::SHADING_GOURAUD); | 
|  | break; | 
|  | case D3DSHADE_PHONG: | 
|  | // FIXME: Unimplemented (should set gouraud)? | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_LINEPATTERN: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_ZWRITEENABLE: | 
|  | renderer->setDepthWriteEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_ALPHATESTENABLE: | 
|  | renderer->setAlphaTestEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_LASTPIXEL: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_SRCBLEND: | 
|  | switch(value) | 
|  | { | 
|  | case D3DBLEND_ZERO: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_ZERO); | 
|  | break; | 
|  | case D3DBLEND_ONE: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_ONE); | 
|  | break; | 
|  | case D3DBLEND_SRCCOLOR: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_SOURCE); | 
|  | break; | 
|  | case D3DBLEND_INVSRCCOLOR: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE); | 
|  | break; | 
|  | case D3DBLEND_SRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_INVSRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_DESTALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA); | 
|  | break; | 
|  | case D3DBLEND_INVDESTALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA); | 
|  | break; | 
|  | case D3DBLEND_DESTCOLOR: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_DEST); | 
|  | break; | 
|  | case D3DBLEND_INVDESTCOLOR: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVDEST); | 
|  | break; | 
|  | case D3DBLEND_SRCALPHASAT: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT); | 
|  | break; | 
|  | case D3DBLEND_BOTHSRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_BOTHINVSRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_DESTBLEND: | 
|  | switch(value) | 
|  | { | 
|  | case D3DBLEND_ZERO: | 
|  | renderer->setDestBlendFactor(sw::BLEND_ZERO); | 
|  | break; | 
|  | case D3DBLEND_ONE: | 
|  | renderer->setDestBlendFactor(sw::BLEND_ONE); | 
|  | break; | 
|  | case D3DBLEND_SRCCOLOR: | 
|  | renderer->setDestBlendFactor(sw::BLEND_SOURCE); | 
|  | break; | 
|  | case D3DBLEND_INVSRCCOLOR: | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVSOURCE); | 
|  | break; | 
|  | case D3DBLEND_SRCALPHA: | 
|  | renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_INVSRCALPHA: | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_DESTALPHA: | 
|  | renderer->setDestBlendFactor(sw::BLEND_DESTALPHA); | 
|  | break; | 
|  | case D3DBLEND_INVDESTALPHA: | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA); | 
|  | break; | 
|  | case D3DBLEND_DESTCOLOR: | 
|  | renderer->setDestBlendFactor(sw::BLEND_DEST); | 
|  | break; | 
|  | case D3DBLEND_INVDESTCOLOR: | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVDEST); | 
|  | break; | 
|  | case D3DBLEND_SRCALPHASAT: | 
|  | renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT); | 
|  | break; | 
|  | case D3DBLEND_BOTHSRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | break; | 
|  | case D3DBLEND_BOTHINVSRCALPHA: | 
|  | renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
|  | renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_CULLMODE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DCULL_NONE: | 
|  | renderer->setCullMode(sw::CULL_NONE, true); | 
|  | break; | 
|  | case D3DCULL_CCW: | 
|  | renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE, true); | 
|  | break; | 
|  | case D3DCULL_CW: | 
|  | renderer->setCullMode(sw::CULL_CLOCKWISE, true); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_ZFUNC: | 
|  | switch(value) | 
|  | { | 
|  | case D3DCMP_NEVER: | 
|  | renderer->setDepthCompare(sw::DEPTH_NEVER); | 
|  | break; | 
|  | case D3DCMP_LESS: | 
|  | renderer->setDepthCompare(sw::DEPTH_LESS); | 
|  | break; | 
|  | case D3DCMP_EQUAL: | 
|  | renderer->setDepthCompare(sw::DEPTH_EQUAL); | 
|  | break; | 
|  | case D3DCMP_LESSEQUAL: | 
|  | renderer->setDepthCompare(sw::DEPTH_LESSEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATER: | 
|  | renderer->setDepthCompare(sw::DEPTH_GREATER); | 
|  | break; | 
|  | case D3DCMP_NOTEQUAL: | 
|  | renderer->setDepthCompare(sw::DEPTH_NOTEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATEREQUAL: | 
|  | renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL); | 
|  | break; | 
|  | case D3DCMP_ALWAYS: | 
|  | renderer->setDepthCompare(sw::DEPTH_ALWAYS); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_ALPHAREF: | 
|  | renderer->setAlphaReference(value & 0x000000FF); | 
|  | break; | 
|  | case D3DRS_ALPHAFUNC: | 
|  | switch(value) | 
|  | { | 
|  | case D3DCMP_NEVER: | 
|  | renderer->setAlphaCompare(sw::ALPHA_NEVER); | 
|  | break; | 
|  | case D3DCMP_LESS: | 
|  | renderer->setAlphaCompare(sw::ALPHA_LESS); | 
|  | break; | 
|  | case D3DCMP_EQUAL: | 
|  | renderer->setAlphaCompare(sw::ALPHA_EQUAL); | 
|  | break; | 
|  | case D3DCMP_LESSEQUAL: | 
|  | renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATER: | 
|  | renderer->setAlphaCompare(sw::ALPHA_GREATER); | 
|  | break; | 
|  | case D3DCMP_NOTEQUAL: | 
|  | renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATEREQUAL: | 
|  | renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL); | 
|  | break; | 
|  | case D3DCMP_ALWAYS: | 
|  | renderer->setAlphaCompare(sw::ALPHA_ALWAYS); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_DITHERENABLE: | 
|  | //	if(!init && value == 1) UNIMPLEMENTED();   // FIXME: Unimplemented | 
|  | break; | 
|  | case D3DRS_ALPHABLENDENABLE: | 
|  | renderer->setAlphaBlendEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_FOGENABLE: | 
|  | renderer->setFogEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_ZVISIBLE: | 
|  | break;   // Not supported | 
|  | case D3DRS_FOGCOLOR: | 
|  | renderer->setFogColor(value); | 
|  | break; | 
|  | case D3DRS_FOGTABLEMODE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DFOG_NONE: | 
|  | renderer->setPixelFogMode(sw::FOG_NONE); | 
|  | break; | 
|  | case D3DFOG_LINEAR: | 
|  | renderer->setPixelFogMode(sw::FOG_LINEAR); | 
|  | break; | 
|  | case D3DFOG_EXP: | 
|  | renderer->setPixelFogMode(sw::FOG_EXP); | 
|  | break; | 
|  | case D3DFOG_EXP2: | 
|  | renderer->setPixelFogMode(sw::FOG_EXP2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_FOGSTART: | 
|  | renderer->setFogStart((float&)value); | 
|  | break; | 
|  | case D3DRS_FOGEND: | 
|  | renderer->setFogEnd((float&)value); | 
|  | break; | 
|  | case D3DRS_FOGDENSITY: | 
|  | renderer->setFogDensity((float&)value); | 
|  | break; | 
|  | case D3DRS_EDGEANTIALIAS: | 
|  | if(!init) if(value != FALSE) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_ZBIAS: | 
|  | renderer->setDepthBias(-2.0e-6f * value); | 
|  | renderer->setSlopeDepthBias(0.0f); | 
|  | break; | 
|  | case D3DRS_RANGEFOGENABLE: | 
|  | renderer->setRangeFogEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_SPECULARENABLE: | 
|  | renderer->setSpecularEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_STENCILENABLE: | 
|  | renderer->setStencilEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_STENCILFAIL: | 
|  | switch(value) | 
|  | { | 
|  | case D3DSTENCILOP_KEEP: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_KEEP); | 
|  | break; | 
|  | case D3DSTENCILOP_ZERO: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_ZERO); | 
|  | break; | 
|  | case D3DSTENCILOP_REPLACE: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_REPLACE); | 
|  | break; | 
|  | case D3DSTENCILOP_INCRSAT: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_INCRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_DECRSAT: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_DECRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_INVERT: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_INVERT); | 
|  | break; | 
|  | case D3DSTENCILOP_INCR: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_INCR); | 
|  | break; | 
|  | case D3DSTENCILOP_DECR: | 
|  | renderer->setStencilFailOperation(sw::OPERATION_DECR); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_STENCILZFAIL: | 
|  | switch(value) | 
|  | { | 
|  | case D3DSTENCILOP_KEEP: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_KEEP); | 
|  | break; | 
|  | case D3DSTENCILOP_ZERO: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_ZERO); | 
|  | break; | 
|  | case D3DSTENCILOP_REPLACE: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_REPLACE); | 
|  | break; | 
|  | case D3DSTENCILOP_INCRSAT: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_DECRSAT: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_INVERT: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_INVERT); | 
|  | break; | 
|  | case D3DSTENCILOP_INCR: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_INCR); | 
|  | break; | 
|  | case D3DSTENCILOP_DECR: | 
|  | renderer->setStencilZFailOperation(sw::OPERATION_DECR); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_STENCILPASS: | 
|  | switch(value) | 
|  | { | 
|  | case D3DSTENCILOP_KEEP: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_KEEP); | 
|  | break; | 
|  | case D3DSTENCILOP_ZERO: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_ZERO); | 
|  | break; | 
|  | case D3DSTENCILOP_REPLACE: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_REPLACE); | 
|  | break; | 
|  | case D3DSTENCILOP_INCRSAT: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_INCRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_DECRSAT: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_DECRSAT); | 
|  | break; | 
|  | case D3DSTENCILOP_INVERT: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_INVERT); | 
|  | break; | 
|  | case D3DSTENCILOP_INCR: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_INCR); | 
|  | break; | 
|  | case D3DSTENCILOP_DECR: | 
|  | renderer->setStencilPassOperation(sw::OPERATION_DECR); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_STENCILFUNC: | 
|  | switch(value) | 
|  | { | 
|  | case D3DCMP_NEVER: | 
|  | renderer->setStencilCompare(sw::STENCIL_NEVER); | 
|  | break; | 
|  | case D3DCMP_LESS: | 
|  | renderer->setStencilCompare(sw::STENCIL_LESS); | 
|  | break; | 
|  | case D3DCMP_EQUAL: | 
|  | renderer->setStencilCompare(sw::STENCIL_EQUAL); | 
|  | break; | 
|  | case D3DCMP_LESSEQUAL: | 
|  | renderer->setStencilCompare(sw::STENCIL_LESSEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATER: | 
|  | renderer->setStencilCompare(sw::STENCIL_GREATER); | 
|  | break; | 
|  | case D3DCMP_NOTEQUAL: | 
|  | renderer->setStencilCompare(sw::STENCIL_NOTEQUAL); | 
|  | break; | 
|  | case D3DCMP_GREATEREQUAL: | 
|  | renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL); | 
|  | break; | 
|  | case D3DCMP_ALWAYS: | 
|  | renderer->setStencilCompare(sw::STENCIL_ALWAYS); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_STENCILREF: | 
|  | renderer->setStencilReference(value); | 
|  | renderer->setStencilReferenceCCW(value); | 
|  | break; | 
|  | case D3DRS_STENCILMASK: | 
|  | renderer->setStencilMask(value); | 
|  | renderer->setStencilMaskCCW(value); | 
|  | break; | 
|  | case D3DRS_STENCILWRITEMASK: | 
|  | renderer->setStencilWriteMask(value); | 
|  | renderer->setStencilWriteMaskCCW(value); | 
|  | break; | 
|  | case D3DRS_TEXTUREFACTOR: | 
|  | renderer->setTextureFactor(value); | 
|  | break; | 
|  | case D3DRS_WRAP0: | 
|  | renderer->setTextureWrap(0, value); | 
|  | break; | 
|  | case D3DRS_WRAP1: | 
|  | renderer->setTextureWrap(1, value); | 
|  | break; | 
|  | case D3DRS_WRAP2: | 
|  | renderer->setTextureWrap(2, value); | 
|  | break; | 
|  | case D3DRS_WRAP3: | 
|  | renderer->setTextureWrap(3, value); | 
|  | break; | 
|  | case D3DRS_WRAP4: | 
|  | renderer->setTextureWrap(4, value); | 
|  | break; | 
|  | case D3DRS_WRAP5: | 
|  | renderer->setTextureWrap(5, value); | 
|  | break; | 
|  | case D3DRS_WRAP6: | 
|  | renderer->setTextureWrap(6, value); | 
|  | break; | 
|  | case D3DRS_WRAP7: | 
|  | renderer->setTextureWrap(7, value); | 
|  | break; | 
|  | case D3DRS_CLIPPING: | 
|  | // Ignored, clipping is always performed | 
|  | break; | 
|  | case D3DRS_LIGHTING: | 
|  | renderer->setLightingEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_AMBIENT: | 
|  | renderer->setGlobalAmbient(value); | 
|  | break; | 
|  | case D3DRS_FOGVERTEXMODE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DFOG_NONE: | 
|  | renderer->setVertexFogMode(sw::FOG_NONE); | 
|  | break; | 
|  | case D3DFOG_LINEAR: | 
|  | renderer->setVertexFogMode(sw::FOG_LINEAR); | 
|  | break; | 
|  | case D3DFOG_EXP: | 
|  | renderer->setVertexFogMode(sw::FOG_EXP); | 
|  | break; | 
|  | case D3DFOG_EXP2: | 
|  | renderer->setVertexFogMode(sw::FOG_EXP2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_COLORVERTEX: | 
|  | renderer->setColorVertexEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_LOCALVIEWER: | 
|  | renderer->setLocalViewer(value != FALSE); | 
|  | break; | 
|  | case D3DRS_NORMALIZENORMALS: | 
|  | renderer->setNormalizeNormals(value != FALSE); | 
|  | break; | 
|  | case D3DRS_DIFFUSEMATERIALSOURCE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DMCS_MATERIAL: | 
|  | renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL); | 
|  | break; | 
|  | case D3DMCS_COLOR1: | 
|  | renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1); | 
|  | break; | 
|  | case D3DMCS_COLOR2: | 
|  | renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_SPECULARMATERIALSOURCE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DMCS_MATERIAL: | 
|  | renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL); | 
|  | break; | 
|  | case D3DMCS_COLOR1: | 
|  | renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1); | 
|  | break; | 
|  | case D3DMCS_COLOR2: | 
|  | renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_AMBIENTMATERIALSOURCE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DMCS_MATERIAL: | 
|  | renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL); | 
|  | break; | 
|  | case D3DMCS_COLOR1: | 
|  | renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1); | 
|  | break; | 
|  | case D3DMCS_COLOR2: | 
|  | renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_EMISSIVEMATERIALSOURCE: | 
|  | switch(value) | 
|  | { | 
|  | case D3DMCS_MATERIAL: | 
|  | renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL); | 
|  | break; | 
|  | case D3DMCS_COLOR1: | 
|  | renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1); | 
|  | break; | 
|  | case D3DMCS_COLOR2: | 
|  | renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_VERTEXBLEND: | 
|  | switch(value) | 
|  | { | 
|  | case D3DVBF_DISABLE: | 
|  | renderer->setVertexBlendMatrixCount(0); | 
|  | break; | 
|  | case D3DVBF_1WEIGHTS: | 
|  | renderer->setVertexBlendMatrixCount(2); | 
|  | break; | 
|  | case D3DVBF_2WEIGHTS: | 
|  | renderer->setVertexBlendMatrixCount(3); | 
|  | break; | 
|  | case D3DVBF_3WEIGHTS: | 
|  | renderer->setVertexBlendMatrixCount(4); | 
|  | break; | 
|  | case D3DVBF_TWEENING: | 
|  | UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DVBF_0WEIGHTS: | 
|  | renderer->setVertexBlendMatrixCount(1); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_CLIPPLANEENABLE: | 
|  | renderer->setClipFlags(value); | 
|  | break; | 
|  | case D3DRS_SOFTWAREVERTEXPROCESSING: | 
|  | break; | 
|  | case D3DRS_POINTSIZE: | 
|  | renderer->setPointSize((float&)value); | 
|  | break; | 
|  | case D3DRS_POINTSIZE_MIN: | 
|  | renderer->setPointSizeMin((float&)value); | 
|  | break; | 
|  | case D3DRS_POINTSPRITEENABLE: | 
|  | renderer->setPointSpriteEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_POINTSCALEENABLE: | 
|  | renderer->setPointScaleEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_POINTSCALE_A: | 
|  | renderer->setPointScaleA((float&)value); | 
|  | break; | 
|  | case D3DRS_POINTSCALE_B: | 
|  | renderer->setPointScaleB((float&)value); | 
|  | break; | 
|  | case D3DRS_POINTSCALE_C: | 
|  | renderer->setPointScaleC((float&)value); | 
|  | break; | 
|  | case D3DRS_MULTISAMPLEANTIALIAS: | 
|  | //	if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_MULTISAMPLEMASK: | 
|  | SetRenderTarget(renderTarget, depthStencil);   // Sets the multi-sample mask, if maskable | 
|  | break; | 
|  | case D3DRS_PATCHEDGESTYLE: | 
|  | //	if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_PATCHSEGMENTS: | 
|  | //	UNIMPLEMENTED();   // FIXME | 
|  | break; | 
|  | case D3DRS_DEBUGMONITORTOKEN: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_POINTSIZE_MAX: | 
|  | renderer->setPointSizeMax((float&)value); | 
|  | break; | 
|  | case D3DRS_INDEXEDVERTEXBLENDENABLE: | 
|  | renderer->setIndexedVertexBlendEnable(value != FALSE); | 
|  | break; | 
|  | case D3DRS_COLORWRITEENABLE: | 
|  | renderer->setColorWriteMask(0, value); | 
|  | break; | 
|  | case D3DRS_TWEENFACTOR: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_BLENDOP: | 
|  | switch(value) | 
|  | { | 
|  | case D3DBLENDOP_ADD: | 
|  | renderer->setBlendOperation(sw::BLENDOP_ADD); | 
|  | break; | 
|  | case D3DBLENDOP_SUBTRACT: | 
|  | renderer->setBlendOperation(sw::BLENDOP_SUB); | 
|  | break; | 
|  | case D3DBLENDOP_REVSUBTRACT: | 
|  | renderer->setBlendOperation(sw::BLENDOP_INVSUB); | 
|  | break; | 
|  | case D3DBLENDOP_MIN: | 
|  | renderer->setBlendOperation(sw::BLENDOP_MIN); | 
|  | break; | 
|  | case D3DBLENDOP_MAX: | 
|  | renderer->setBlendOperation(sw::BLENDOP_MAX); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DRS_POSITIONORDER: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | case D3DRS_NORMALORDER: | 
|  | if(!init) UNIMPLEMENTED(); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  | else   // stateRecorder | 
|  | { | 
|  | stateRecorder.back()->setRenderState(state, value); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetRenderTarget(IDirect3DSurface8 *newRenderTarget, IDirect3DSurface8 *newDepthStencil) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | Direct3DSurface8 *renderTarget = static_cast<Direct3DSurface8*>(newRenderTarget); | 
|  |  | 
|  | if(renderTarget)   // FIXME: Check for D3DUSAGE_RENDERTARGET | 
|  | { | 
|  | renderTarget->bind(); | 
|  | } | 
|  |  | 
|  | if(this->renderTarget) | 
|  | { | 
|  | this->renderTarget->unbind(); | 
|  | } | 
|  |  | 
|  | this->renderTarget = renderTarget; | 
|  |  | 
|  | Direct3DSurface8 *depthStencil = static_cast<Direct3DSurface8*>(newDepthStencil); | 
|  |  | 
|  | if(depthStencil)   // FIXME: Check for D3DUSAGE_DEPTHSTENCIL and D3DPOOL_DEFAULT | 
|  | { | 
|  | depthStencil->bind(); | 
|  | } | 
|  |  | 
|  | if(this->depthStencil) | 
|  | { | 
|  | this->depthStencil->unbind(); | 
|  | } | 
|  |  | 
|  | this->depthStencil = depthStencil; | 
|  |  | 
|  | // Reset viewport to size of current render target | 
|  | D3DSURFACE_DESC renderTargetDesc; | 
|  | renderTarget->GetDesc(&renderTargetDesc); | 
|  |  | 
|  | D3DVIEWPORT8 viewport; | 
|  | viewport.X = 0; | 
|  | viewport.Y = 0; | 
|  | viewport.Width = renderTargetDesc.Width; | 
|  | viewport.Height = renderTargetDesc.Height; | 
|  | viewport.MinZ = 0; | 
|  | viewport.MaxZ = 1; | 
|  |  | 
|  | SetViewport(&viewport); | 
|  |  | 
|  | // Set the multi-sample mask, if maskable | 
|  | if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE) | 
|  | { | 
|  | renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]); | 
|  | } | 
|  | else | 
|  | { | 
|  | renderer->setMultiSampleMask(0xFFFFFFFF); | 
|  | } | 
|  |  | 
|  | renderer->setRenderTarget(0, renderTarget); | 
|  | renderer->setDepthBuffer(depthStencil); | 
|  | renderer->setStencilBuffer(depthStencil); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer8 *iVertexBuffer, unsigned int stride) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | Direct3DVertexBuffer8 *vertexBuffer = static_cast<Direct3DVertexBuffer8*>(iVertexBuffer); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(vertexBuffer) | 
|  | { | 
|  | vertexBuffer->bind(); | 
|  | } | 
|  |  | 
|  | if(dataStream[stream]) | 
|  | { | 
|  | dataStream[stream]->unbind(); | 
|  | streamStride[stream] = 0; | 
|  | } | 
|  |  | 
|  | dataStream[stream] = vertexBuffer; | 
|  | streamStride[stream] = stride; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setStreamSource(stream, vertexBuffer, stride); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetTexture(unsigned long stage, IDirect3DBaseTexture8 *iBaseTexture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(stage >= 8) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | Direct3DBaseTexture8 *baseTexture = dynamic_cast<Direct3DBaseTexture8*>(iBaseTexture); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(texture[stage] == baseTexture) | 
|  | { | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | if(baseTexture) | 
|  | { | 
|  | baseTexture->bind(); | 
|  | } | 
|  |  | 
|  | if(texture[stage]) | 
|  | { | 
|  | texture[stage]->unbind(); | 
|  | } | 
|  |  | 
|  | texture[stage] = baseTexture; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setTexture(stage, baseTexture); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value) | 
|  | { | 
|  | TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value); | 
|  |  | 
|  | if(stage >= 8 || type < 0 || type > D3DTSS_RESULTARG) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(!init && textureStageState[stage][type] == value) | 
|  | { | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | textureStageState[stage][type] = value; | 
|  |  | 
|  | switch(type) | 
|  | { | 
|  | case D3DTSS_COLOROP: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTOP_DISABLE: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE); | 
|  | break; | 
|  | case D3DTOP_SELECTARG1: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1); | 
|  | break; | 
|  | case D3DTOP_SELECTARG2: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2); | 
|  | break; | 
|  | case D3DTOP_MODULATE: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE); | 
|  | break; | 
|  | case D3DTOP_MODULATE2X: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X); | 
|  | break; | 
|  | case D3DTOP_MODULATE4X: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X); | 
|  | break; | 
|  | case D3DTOP_ADD: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD); | 
|  | break; | 
|  | case D3DTOP_ADDSIGNED: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED); | 
|  | break; | 
|  | case D3DTOP_ADDSIGNED2X: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X); | 
|  | break; | 
|  | case D3DTOP_SUBTRACT: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT); | 
|  | break; | 
|  | case D3DTOP_ADDSMOOTH: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH); | 
|  | break; | 
|  | case D3DTOP_BLENDDIFFUSEALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDTEXTUREALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDFACTORALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDTEXTUREALPHAPM: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM); | 
|  | break; | 
|  | case D3DTOP_BLENDCURRENTALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA); | 
|  | break; | 
|  | case D3DTOP_PREMODULATE: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE); | 
|  | break; | 
|  | case D3DTOP_MODULATEALPHA_ADDCOLOR: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR); | 
|  | break; | 
|  | case D3DTOP_MODULATECOLOR_ADDALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA); | 
|  | break; | 
|  | case D3DTOP_MODULATEINVALPHA_ADDCOLOR: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR); | 
|  | break; | 
|  | case D3DTOP_MODULATEINVCOLOR_ADDALPHA: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA); | 
|  | break; | 
|  | case D3DTOP_BUMPENVMAP: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP); | 
|  | break; | 
|  | case D3DTOP_BUMPENVMAPLUMINANCE: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE); | 
|  | break; | 
|  | case D3DTOP_DOTPRODUCT3: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3); | 
|  | break; | 
|  | case D3DTOP_MULTIPLYADD: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD); | 
|  | break; | 
|  | case D3DTOP_LERP: | 
|  | renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_COLORARG1: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_COLORARG2: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ALPHAOP: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTOP_DISABLE: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE); | 
|  | break; | 
|  | case D3DTOP_SELECTARG1: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1); | 
|  | break; | 
|  | case D3DTOP_SELECTARG2: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2); | 
|  | break; | 
|  | case D3DTOP_MODULATE: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE); | 
|  | break; | 
|  | case D3DTOP_MODULATE2X: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X); | 
|  | break; | 
|  | case D3DTOP_MODULATE4X: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X); | 
|  | break; | 
|  | case D3DTOP_ADD: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD); | 
|  | break; | 
|  | case D3DTOP_ADDSIGNED: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED); | 
|  | break; | 
|  | case D3DTOP_ADDSIGNED2X: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X); | 
|  | break; | 
|  | case D3DTOP_SUBTRACT: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT); | 
|  | break; | 
|  | case D3DTOP_ADDSMOOTH: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH); | 
|  | break; | 
|  | case D3DTOP_BLENDDIFFUSEALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDTEXTUREALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDFACTORALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA); | 
|  | break; | 
|  | case D3DTOP_BLENDTEXTUREALPHAPM: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM); | 
|  | break; | 
|  | case D3DTOP_BLENDCURRENTALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA); | 
|  | break; | 
|  | case D3DTOP_PREMODULATE: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE); | 
|  | break; | 
|  | case D3DTOP_MODULATEALPHA_ADDCOLOR: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR); | 
|  | break; | 
|  | case D3DTOP_MODULATECOLOR_ADDALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA); | 
|  | break; | 
|  | case D3DTOP_MODULATEINVALPHA_ADDCOLOR: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR); | 
|  | break; | 
|  | case D3DTOP_MODULATEINVCOLOR_ADDALPHA: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA); | 
|  | break; | 
|  | case D3DTOP_BUMPENVMAP: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP); | 
|  | break; | 
|  | case D3DTOP_BUMPENVMAPLUMINANCE: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE); | 
|  | break; | 
|  | case D3DTOP_DOTPRODUCT3: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3); | 
|  | break; | 
|  | case D3DTOP_MULTIPLYADD: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD); | 
|  | break; | 
|  | case D3DTOP_LERP: | 
|  | renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ALPHAARG1: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ALPHAARG2: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_BUMPENVMAT00: | 
|  | renderer->setBumpmapMatrix(stage, 0, (float&)value); | 
|  | break; | 
|  | case D3DTSS_BUMPENVMAT01: | 
|  | renderer->setBumpmapMatrix(stage, 1, (float&)value); | 
|  | break; | 
|  | case D3DTSS_BUMPENVMAT10: | 
|  | renderer->setBumpmapMatrix(stage, 2, (float&)value); | 
|  | break; | 
|  | case D3DTSS_BUMPENVMAT11: | 
|  | renderer->setBumpmapMatrix(stage, 3, (float&)value); | 
|  | break; | 
|  | case D3DTSS_TEXCOORDINDEX: | 
|  | renderer->setTexCoordIndex(stage, value & 0xFFFF); | 
|  |  | 
|  | switch(value & 0xFFFF0000) | 
|  | { | 
|  | case D3DTSS_TCI_PASSTHRU: | 
|  | renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU); | 
|  | break; | 
|  | case D3DTSS_TCI_CAMERASPACENORMAL: | 
|  | renderer->setTexCoordIndex(stage, stage); | 
|  | renderer->setTexGen(stage, sw::TEXGEN_NORMAL); | 
|  | break; | 
|  | case D3DTSS_TCI_CAMERASPACEPOSITION: | 
|  | renderer->setTexCoordIndex(stage, stage); | 
|  | renderer->setTexGen(stage, sw::TEXGEN_POSITION); | 
|  | break; | 
|  | case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: | 
|  | renderer->setTexCoordIndex(stage, stage); | 
|  | renderer->setTexGen(stage, sw::TEXGEN_REFLECTION); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ADDRESSU: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTADDRESS_WRAP: | 
|  | renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP); | 
|  | break; | 
|  | case D3DTADDRESS_MIRROR: | 
|  | renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR); | 
|  | break; | 
|  | case D3DTADDRESS_CLAMP: | 
|  | renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP); | 
|  | break; | 
|  | case D3DTADDRESS_BORDER: | 
|  | renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER); | 
|  | break; | 
|  | case D3DTADDRESS_MIRRORONCE: | 
|  | renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ADDRESSV: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTADDRESS_WRAP: | 
|  | renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP); | 
|  | break; | 
|  | case D3DTADDRESS_MIRROR: | 
|  | renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR); | 
|  | break; | 
|  | case D3DTADDRESS_CLAMP: | 
|  | renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP); | 
|  | break; | 
|  | case D3DTADDRESS_BORDER: | 
|  | renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER); | 
|  | break; | 
|  | case D3DTADDRESS_MIRRORONCE: | 
|  | renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_BORDERCOLOR: | 
|  | renderer->setBorderColor(sw::SAMPLER_PIXEL, stage, value); | 
|  | break; | 
|  | case D3DTSS_MAGFILTER: | 
|  | // NOTE: SwiftShader does not differentiate between minification and magnification filter | 
|  | switch(value) | 
|  | { | 
|  | case D3DTEXF_NONE: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT); | 
|  | break; | 
|  | case D3DTEXF_POINT: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT); | 
|  | break; | 
|  | case D3DTEXF_LINEAR: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR); | 
|  | break; | 
|  | case D3DTEXF_ANISOTROPIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC); | 
|  | break; | 
|  | case D3DTEXF_FLATCUBIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | case D3DTEXF_GAUSSIANCUBIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | default: | 
|  | return INVALIDCALL(); | 
|  | }; | 
|  | break; | 
|  | case D3DTSS_MINFILTER: | 
|  | // NOTE: SwiftShader does not differentiate between minification and magnification filter | 
|  | switch(value) | 
|  | { | 
|  | case D3DTEXF_NONE: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT); | 
|  | break; | 
|  | case D3DTEXF_POINT: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT); | 
|  | break; | 
|  | case D3DTEXF_LINEAR: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR); | 
|  | break; | 
|  | case D3DTEXF_ANISOTROPIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC); | 
|  | break; | 
|  | case D3DTEXF_FLATCUBIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | case D3DTEXF_GAUSSIANCUBIC: | 
|  | renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | default: | 
|  | return INVALIDCALL(); | 
|  | }; | 
|  | break; | 
|  | case D3DTSS_MIPFILTER: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTEXF_NONE: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_NONE); | 
|  | break; | 
|  | case D3DTEXF_POINT: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_POINT); | 
|  | break; | 
|  | case D3DTEXF_LINEAR: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR); | 
|  | break; | 
|  | case D3DTEXF_ANISOTROPIC: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | case D3DTEXF_FLATCUBIC: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | case D3DTEXF_GAUSSIANCUBIC: | 
|  | renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently | 
|  | break; | 
|  | default: | 
|  | return INVALIDCALL(); | 
|  | }; | 
|  | break; | 
|  | case D3DTSS_MIPMAPLODBIAS: | 
|  | { | 
|  | float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes | 
|  | renderer->setMipmapLOD(sw::SAMPLER_PIXEL, stage, LOD); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_MAXMIPLEVEL: | 
|  | break; | 
|  | case D3DTSS_MAXANISOTROPY: | 
|  | renderer->setMaxAnisotropy(sw::SAMPLER_PIXEL, stage, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy)); | 
|  | break; | 
|  | case D3DTSS_BUMPENVLSCALE: | 
|  | renderer->setLuminanceScale(stage, (float&)value); | 
|  | break; | 
|  | case D3DTSS_BUMPENVLOFFSET: | 
|  | renderer->setLuminanceOffset(stage, (float&)value); | 
|  | break; | 
|  | case D3DTSS_TEXTURETRANSFORMFLAGS: | 
|  | switch(value & ~D3DTTFF_PROJECTED) | 
|  | { | 
|  | case D3DTTFF_DISABLE: | 
|  | renderer->setTextureTransform(stage, 0, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
|  | break; | 
|  | case D3DTTFF_COUNT1: | 
|  | renderer->setTextureTransform(stage, 1, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
|  | break; | 
|  | case D3DTTFF_COUNT2: | 
|  | renderer->setTextureTransform(stage, 2, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
|  | break; | 
|  | case D3DTTFF_COUNT3: | 
|  | renderer->setTextureTransform(stage, 3, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
|  | break; | 
|  | case D3DTTFF_COUNT4: | 
|  | renderer->setTextureTransform(stage, 4, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ADDRESSW: | 
|  | switch(value) | 
|  | { | 
|  | case D3DTADDRESS_WRAP: | 
|  | renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP); | 
|  | break; | 
|  | case D3DTADDRESS_MIRROR: | 
|  | renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR); | 
|  | break; | 
|  | case D3DTADDRESS_CLAMP: | 
|  | renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP); | 
|  | break; | 
|  | case D3DTADDRESS_BORDER: | 
|  | renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER); | 
|  | break; | 
|  | case D3DTADDRESS_MIRRORONCE: | 
|  | renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_COLORARG0: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_ALPHAARG0: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_DIFFUSE: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
|  | break; | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEXTURE: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
|  | break; | 
|  | case D3DTA_TFACTOR: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
|  | break; | 
|  | case D3DTA_SPECULAR: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(value & ~D3DTA_SELECTMASK) | 
|  | { | 
|  | case 0: | 
|  | renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT: | 
|  | renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
|  | break; | 
|  | case D3DTA_ALPHAREPLICATE: | 
|  | renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
|  | break; | 
|  | case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
|  | renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case D3DTSS_RESULTARG: | 
|  | switch(value & D3DTA_SELECTMASK) | 
|  | { | 
|  | case D3DTA_CURRENT: | 
|  | renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT); | 
|  | break; | 
|  | case D3DTA_TEMP: | 
|  | renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  | } | 
|  | else   // stateRecorder | 
|  | { | 
|  | stateRecorder.back()->setTextureStageState(stage, type, value); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!matrix || state < 0 || state > 511) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | this->matrix[state] = *matrix; | 
|  |  | 
|  | sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41, | 
|  | matrix->_12, matrix->_22, matrix->_32, matrix->_42, | 
|  | matrix->_13, matrix->_23, matrix->_33, matrix->_43, | 
|  | matrix->_14, matrix->_24, matrix->_34, matrix->_44); | 
|  |  | 
|  | switch(state) | 
|  | { | 
|  | case D3DTS_WORLD: | 
|  | renderer->setModelMatrix(M); | 
|  | break; | 
|  | case D3DTS_VIEW: | 
|  | renderer->setViewMatrix(M); | 
|  | break; | 
|  | case D3DTS_PROJECTION: | 
|  | renderer->setProjectionMatrix(M); | 
|  | break; | 
|  | case D3DTS_TEXTURE0: | 
|  | renderer->setTextureMatrix(0, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE1: | 
|  | renderer->setTextureMatrix(1, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE2: | 
|  | renderer->setTextureMatrix(2, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE3: | 
|  | renderer->setTextureMatrix(3, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE4: | 
|  | renderer->setTextureMatrix(4, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE5: | 
|  | renderer->setTextureMatrix(5, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE6: | 
|  | renderer->setTextureMatrix(6, M); | 
|  | break; | 
|  | case D3DTS_TEXTURE7: | 
|  | renderer->setTextureMatrix(7, M); | 
|  | break; | 
|  | default: | 
|  | if(state > 256 && state < 512) | 
|  | { | 
|  | renderer->setModelMatrix(M, state - 256); | 
|  | } | 
|  | else ASSERT(false); | 
|  | } | 
|  | } | 
|  | else   // stateRecorder | 
|  | { | 
|  | stateRecorder.back()->setTransform(state, matrix); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetVertexShader(unsigned long handle) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(handle & 0x00000001) | 
|  | { | 
|  | unsigned int index = handle >> 16; | 
|  |  | 
|  | if(vertexShader[index]) | 
|  | { | 
|  | vertexShader[index]->bind(); | 
|  | } | 
|  |  | 
|  | if(vertexShader[vertexShaderHandle >> 16]) | 
|  | { | 
|  | vertexShader[vertexShaderHandle >> 16]->unbind(); | 
|  | } | 
|  |  | 
|  | vertexShaderHandle = handle; | 
|  |  | 
|  | Direct3DVertexShader8 *shader = vertexShader[index]; | 
|  | renderer->setVertexShader(shader->getVertexShader()); | 
|  | declaration = shader->getDeclaration(); | 
|  |  | 
|  | FVF = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | renderer->setVertexShader(0); | 
|  | declaration = 0; | 
|  |  | 
|  | FVF = handle; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setVertexShader(handle); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetVertexShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!constantData) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | for(unsigned int i = 0; i < count; i++) | 
|  | { | 
|  | vertexShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0]; | 
|  | vertexShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1]; | 
|  | vertexShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2]; | 
|  | vertexShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3]; | 
|  | } | 
|  |  | 
|  | renderer->setVertexShaderConstantF(startRegister, (const float*)constantData, count); | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setVertexShaderConstant(startRegister, constantData, count); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetViewport(const D3DVIEWPORT8 *viewport) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!viewport) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | this->viewport = *viewport; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setViewport(viewport); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | int Direct3DDevice8::ShowCursor(int show) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | int oldValue = showCursor ? TRUE : FALSE; | 
|  |  | 
|  | showCursor = show != FALSE && cursor; | 
|  |  | 
|  | bindCursor(); | 
|  |  | 
|  | return oldValue; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::TestCooperativeLevel() | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::UpdateTexture(IDirect3DBaseTexture8 *sourceTexture, IDirect3DBaseTexture8 *destinationTexture) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!sourceTexture || !destinationTexture) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DRESOURCETYPE type = sourceTexture->GetType(); | 
|  |  | 
|  | if(type != destinationTexture->GetType()) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | switch(type) | 
|  | { | 
|  | case D3DRTYPE_TEXTURE: | 
|  | { | 
|  | IDirect3DTexture8 *source; | 
|  | IDirect3DTexture8 *dest; | 
|  |  | 
|  | sourceTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&source); | 
|  | destinationTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&dest); | 
|  |  | 
|  | ASSERT(source && dest); | 
|  |  | 
|  | for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++) | 
|  | { | 
|  | IDirect3DSurface8 *sourceSurface; | 
|  | IDirect3DSurface8 *destinationSurface; | 
|  |  | 
|  | source->GetSurfaceLevel(level, &sourceSurface); | 
|  | dest->GetSurfaceLevel(level, &destinationSurface); | 
|  |  | 
|  | updateSurface(sourceSurface, 0, destinationSurface, 0); | 
|  |  | 
|  | sourceSurface->Release(); | 
|  | destinationSurface->Release(); | 
|  | } | 
|  |  | 
|  | source->Release(); | 
|  | dest->Release(); | 
|  | } | 
|  | break; | 
|  | case D3DRTYPE_VOLUMETEXTURE: | 
|  | { | 
|  | IDirect3DVolumeTexture8 *source; | 
|  | IDirect3DVolumeTexture8 *dest; | 
|  |  | 
|  | sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&source); | 
|  | destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&dest); | 
|  |  | 
|  | ASSERT(source && dest); | 
|  |  | 
|  | for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination | 
|  | { | 
|  | IDirect3DVolume8 *sourceVolume; | 
|  | IDirect3DVolume8 *destinationVolume; | 
|  |  | 
|  | source->GetVolumeLevel(level, &sourceVolume); | 
|  | dest->GetVolumeLevel(level, &destinationVolume); | 
|  |  | 
|  | updateVolume(sourceVolume, destinationVolume); | 
|  |  | 
|  | sourceVolume->Release(); | 
|  | destinationVolume->Release(); | 
|  | } | 
|  |  | 
|  | source->Release(); | 
|  | dest->Release(); | 
|  | } | 
|  | break; | 
|  | case D3DRTYPE_CUBETEXTURE: | 
|  | { | 
|  | IDirect3DCubeTexture8 *source; | 
|  | IDirect3DCubeTexture8 *dest; | 
|  |  | 
|  | sourceTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&source); | 
|  | destinationTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&dest); | 
|  |  | 
|  | ASSERT(source && dest); | 
|  |  | 
|  | for(int face = 0; face < 6; face++) | 
|  | { | 
|  | for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++) | 
|  | { | 
|  | IDirect3DSurface8 *sourceSurface; | 
|  | IDirect3DSurface8 *destinationSurface; | 
|  |  | 
|  | source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface); | 
|  | dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface); | 
|  |  | 
|  | updateSurface(sourceSurface, 0, destinationSurface, 0); | 
|  |  | 
|  | sourceSurface->Release(); | 
|  | destinationSurface->Release(); | 
|  | } | 
|  | } | 
|  |  | 
|  | source->Release(); | 
|  | dest->Release(); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::ValidateDevice(unsigned long *numPasses) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | if(!numPasses) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | *numPasses = 1; | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::updateSurface(IDirect3DSurface8 *sourceSurface, const RECT *sourceRect, IDirect3DSurface8 *destinationSurface, const POINT *destPoint) | 
|  | { | 
|  | TRACE("IDirect3DSurface8 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface8 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint); | 
|  |  | 
|  | if(!sourceSurface || !destinationSurface) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DSURFACE_DESC sourceDescription; | 
|  | D3DSURFACE_DESC destinationDescription; | 
|  |  | 
|  | sourceSurface->GetDesc(&sourceDescription); | 
|  | destinationSurface->GetDesc(&destinationDescription); | 
|  |  | 
|  | RECT sRect; | 
|  | RECT dRect; | 
|  |  | 
|  | if(sourceRect && destPoint) | 
|  | { | 
|  | sRect.left = sourceRect->left; | 
|  | sRect.top = sourceRect->top; | 
|  | sRect.right = sourceRect->right; | 
|  | sRect.bottom = sourceRect->bottom; | 
|  |  | 
|  | dRect.left = destPoint->x; | 
|  | dRect.top = destPoint->y; | 
|  | dRect.right = destPoint->x + sourceRect->right - sourceRect->left; | 
|  | dRect.bottom = destPoint->y + sourceRect->bottom - sourceRect->top; | 
|  | } | 
|  | else | 
|  | { | 
|  | sRect.left = 0; | 
|  | sRect.top = 0; | 
|  | sRect.right = sourceDescription.Width; | 
|  | sRect.bottom = sourceDescription.Height; | 
|  |  | 
|  | dRect.left = 0; | 
|  | dRect.top = 0; | 
|  | dRect.right = destinationDescription.Width; | 
|  | dRect.bottom = destinationDescription.Height; | 
|  | } | 
|  |  | 
|  | int sWidth = sRect.right - sRect.left; | 
|  | int sHeight = sRect.bottom - sRect.top; | 
|  |  | 
|  | int dWidth = dRect.right - dRect.left; | 
|  | int dHeight = dRect.bottom - dRect.top; | 
|  |  | 
|  | if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE || | 
|  | destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE || | 
|  | // sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags | 
|  | // destinationDescription.Pool != D3DPOOL_DEFAULT || | 
|  | sourceDescription.Format != destinationDescription.Format || | 
|  | sWidth  != dWidth || | 
|  | sHeight != dHeight) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DLOCKED_RECT sourceLock; | 
|  | D3DLOCKED_RECT destinationLock; | 
|  |  | 
|  | sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY); | 
|  | destinationSurface->LockRect(&destinationLock, &dRect, 0); | 
|  |  | 
|  | unsigned int width; | 
|  | unsigned int height; | 
|  | unsigned int bytes; | 
|  |  | 
|  | switch(sourceDescription.Format) | 
|  | { | 
|  | case D3DFMT_DXT1: | 
|  | width = (dWidth + 3) / 4; | 
|  | height = (dHeight + 3) / 4; | 
|  | bytes = width * 8;   // 64 bit per 4x4 block | 
|  | break; | 
|  | case D3DFMT_DXT2: | 
|  | case D3DFMT_DXT3: | 
|  | case D3DFMT_DXT4: | 
|  | case D3DFMT_DXT5: | 
|  | width = (dWidth + 3) / 4; | 
|  | height = (dHeight + 3) / 4; | 
|  | bytes = width * 16;   // 128 bit per 4x4 block | 
|  | break; | 
|  | default: | 
|  | width = dWidth; | 
|  | height = dHeight; | 
|  | bytes = width * Direct3DSurface8::bytes(sourceDescription.Format); | 
|  | } | 
|  |  | 
|  | for(unsigned int y = 0; y < height; y++) | 
|  | { | 
|  | memcpy(destinationLock.pBits, sourceLock.pBits, bytes); | 
|  |  | 
|  | (byte*&)sourceLock.pBits += sourceLock.Pitch; | 
|  | (byte*&)destinationLock.pBits += destinationLock.Pitch; | 
|  | } | 
|  |  | 
|  | sourceSurface->UnlockRect(); | 
|  | destinationSurface->UnlockRect(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::SetIndices(IDirect3DIndexBuffer8 *iIndexBuffer, unsigned int baseVertexIndex) | 
|  | { | 
|  | TRACE(""); | 
|  |  | 
|  | Direct3DIndexBuffer8 *indexBuffer = static_cast<Direct3DIndexBuffer8*>(iIndexBuffer); | 
|  |  | 
|  | if(!recordState) | 
|  | { | 
|  | if(indexBuffer) | 
|  | { | 
|  | indexBuffer->bind(); | 
|  | } | 
|  |  | 
|  | if(this->indexData) | 
|  | { | 
|  | this->indexData->unbind(); | 
|  | } | 
|  |  | 
|  | this->indexData = indexBuffer; | 
|  | this->baseVertexIndex = baseVertexIndex; | 
|  | } | 
|  | else | 
|  | { | 
|  | stateRecorder.back()->setIndices(indexBuffer, baseVertexIndex); | 
|  | } | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | int Direct3DDevice8::FVFStride(unsigned long FVF) | 
|  | { | 
|  | int stride = 0; | 
|  |  | 
|  | switch(FVF & D3DFVF_POSITION_MASK) | 
|  | { | 
|  | case D3DFVF_XYZ:	stride += 12;	break; | 
|  | case D3DFVF_XYZRHW:	stride += 16;	break; | 
|  | case D3DFVF_XYZB1:	stride += 16;	break; | 
|  | case D3DFVF_XYZB2:	stride += 20;	break; | 
|  | case D3DFVF_XYZB3:	stride += 24;	break; | 
|  | case D3DFVF_XYZB4:	stride += 28;	break; | 
|  | case D3DFVF_XYZB5:	stride += 32;	break; | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_NORMAL)		stride += 12; | 
|  | if(FVF & D3DFVF_PSIZE)		stride += 4; | 
|  | if(FVF & D3DFVF_DIFFUSE)	stride += 4; | 
|  | if(FVF & D3DFVF_SPECULAR)	stride += 4; | 
|  |  | 
|  | switch((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) | 
|  | { | 
|  | case 8: stride += 4 + 4 * ((1 + (FVF >> 30)) % 4); | 
|  | case 7: stride += 4 + 4 * ((1 + (FVF >> 28)) % 4); | 
|  | case 6: stride += 4 + 4 * ((1 + (FVF >> 26)) % 4); | 
|  | case 5: stride += 4 + 4 * ((1 + (FVF >> 24)) % 4); | 
|  | case 4: stride += 4 + 4 * ((1 + (FVF >> 22)) % 4); | 
|  | case 3: stride += 4 + 4 * ((1 + (FVF >> 20)) % 4); | 
|  | case 2: stride += 4 + 4 * ((1 + (FVF >> 18)) % 4); | 
|  | case 1: stride += 4 + 4 * ((1 + (FVF >> 16)) % 4); | 
|  | case 0: break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | return stride; | 
|  | } | 
|  |  | 
|  | int Direct3DDevice8::typeStride(unsigned char type) | 
|  | { | 
|  | static const int LUT[] = | 
|  | { | 
|  | 4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.) | 
|  | 8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.) | 
|  | 12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.) | 
|  | 16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float | 
|  | 4,	// D3DDECLTYPE_D3DCOLOR  =  4,  // 4D packed unsigned bytes mapped to 0. to 1. range. Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) | 
|  | 4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte | 
|  | 4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.) | 
|  | 8 	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short | 
|  | }; | 
|  |  | 
|  | if(type <= 7) | 
|  | { | 
|  | return LUT[type]; | 
|  | } | 
|  | else ASSERT(false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bool Direct3DDevice8::bindData(Direct3DIndexBuffer8 *indexBuffer, int base) | 
|  | { | 
|  | if(!bindViewport()) | 
|  | { | 
|  | return false;   // Zero-area target region | 
|  | } | 
|  |  | 
|  | bindTextures(); | 
|  | bindStreams(base); | 
|  | bindIndexBuffer(indexBuffer); | 
|  | bindLights(); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::bindStreams(int base) | 
|  | { | 
|  | renderer->resetInputStreams((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW); | 
|  |  | 
|  | int stride; | 
|  |  | 
|  | if(!declaration)   // Fixed-function vertex pipeline | 
|  | { | 
|  | const void *buffer = 0; | 
|  |  | 
|  | ASSERT(dataStream[0]); | 
|  |  | 
|  | Direct3DVertexBuffer8 *stream = dataStream[0]; | 
|  | sw::Resource *resource = stream->getResource(); | 
|  | buffer = (char*)resource->data(); | 
|  | stride = FVFStride(FVF); | 
|  |  | 
|  | ASSERT(stride == streamStride[0]);   // FIXME | 
|  | ASSERT(buffer && stride); | 
|  |  | 
|  | (char*&)buffer += stride * base; | 
|  |  | 
|  | sw::Stream attribute(resource, buffer, stride); | 
|  |  | 
|  | switch(FVF & D3DFVF_POSITION_MASK) | 
|  | { | 
|  | case D3DFVF_XYZ: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  | break; | 
|  | case D3DFVF_XYZRHW: | 
|  | renderer->setInputStream(sw::PositionT, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4)); | 
|  | (char*&)buffer += 16; | 
|  | break; | 
|  | case D3DFVF_XYZB1: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  |  | 
|  | renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active? | 
|  | (char*&)buffer += 4; | 
|  | break; | 
|  | case D3DFVF_XYZB2: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  |  | 
|  | renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active? | 
|  | (char*&)buffer += 8; | 
|  | break; | 
|  | case D3DFVF_XYZB3: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  |  | 
|  | renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 2));   // FIXME: Stream type depends on indexed blending active? | 
|  | (char*&)buffer += 12; | 
|  | break; | 
|  | case D3DFVF_XYZB4: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  |  | 
|  | renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));   // FIXME: Stream type depends on indexed blending active? | 
|  | (char*&)buffer += 16; | 
|  | break; | 
|  | case D3DFVF_XYZB5: | 
|  | renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  |  | 
|  | renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4));   // FIXME: Stream type depends on indexed blending active? | 
|  | (char*&)buffer += 20; | 
|  | break; | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_LASTBETA_UBYTE4) | 
|  | { | 
|  | renderer->setInputStream(sw::BlendIndices, attribute.define((char*&)buffer - 4, sw::STREAMTYPE_INDICES, 1)); | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_NORMAL) | 
|  | { | 
|  | renderer->setInputStream(sw::Normal, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3)); | 
|  | (char*&)buffer += 12; | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_PSIZE) | 
|  | { | 
|  | renderer->setInputStream(sw::PointSize, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1)); | 
|  | (char*&)buffer += 4; | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_DIFFUSE) | 
|  | { | 
|  | renderer->setInputStream(sw::Color0, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4)); | 
|  | (char*&)buffer += 4; | 
|  | } | 
|  |  | 
|  | if(FVF & D3DFVF_SPECULAR) | 
|  | { | 
|  | renderer->setInputStream(sw::Color1, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4)); | 
|  | (char*&)buffer += 4; | 
|  | } | 
|  |  | 
|  | for(unsigned int i = 0; i < 8; i++) | 
|  | { | 
|  | if((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT >= i + 1) | 
|  | { | 
|  | renderer->setInputStream(sw::TexCoord0 + i, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1 + (1 + (FVF >> (16 + i * 2))) % 4)); | 
|  | (char*&)buffer += 4 + 4 * ((1 + (FVF >> (16 + i * 2))) % 4); | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | const unsigned long *element = declaration; | 
|  | int stream = 0; | 
|  | sw::Resource *resource; | 
|  | const void *buffer = 0; | 
|  |  | 
|  | while(*element != 0xFFFFFFFF) | 
|  | { | 
|  | switch((*element & 0xE0000000) >> 29) | 
|  | { | 
|  | case 0:   // NOP | 
|  | if(*element != 0x00000000) | 
|  | { | 
|  | ASSERT(false); | 
|  | } | 
|  | break; | 
|  | case 1:   // Stream selector | 
|  | stream = *element & 0x0000000F; | 
|  | { | 
|  | ASSERT(dataStream[stream]);   // Expected a stream | 
|  |  | 
|  | Direct3DVertexBuffer8 *streamBuffer = (Direct3DVertexBuffer8*)dataStream[stream]; | 
|  | resource = streamBuffer->getResource(); | 
|  | buffer = (char*)resource->data(); | 
|  |  | 
|  | const unsigned long *streamElement = element + 1; | 
|  | stride = 0; | 
|  |  | 
|  | while((*streamElement & 0xE0000000) >> 29 == 2)   // Data definition | 
|  | { | 
|  | if(*streamElement & 0x10000000)   // Data skip | 
|  | { | 
|  | int skip = (*streamElement & 0x000F0000) >> 16; | 
|  |  | 
|  | stride += 4 * skip; | 
|  | } | 
|  | else | 
|  | { | 
|  | stride += typeStride((unsigned char)((*streamElement & 0x000F0000) >> 16)); | 
|  | } | 
|  |  | 
|  | streamElement++; | 
|  | } | 
|  |  | 
|  | //	ASSERT(stride == streamStride[stream]);   // FIXME: Probably just ignore | 
|  |  | 
|  | (char*&)buffer += stride * base; | 
|  | } | 
|  | break; | 
|  | case 2:   // Data definition | 
|  | if(*element & 0x10000000)   // Data skip | 
|  | { | 
|  | int skip = (*element & 0x000F0000) >> 16; | 
|  |  | 
|  | (char*&)buffer += 4 * skip; | 
|  | } | 
|  | else | 
|  | { | 
|  | int type = (*element & 0x000F0000) >> 16; | 
|  | int index = (*element & 0x0000000F) >> 0; | 
|  |  | 
|  | sw::Stream attribute(resource, buffer, stride); | 
|  |  | 
|  | switch(type) | 
|  | { | 
|  | case D3DVSDT_FLOAT1:   attribute.define(sw::STREAMTYPE_FLOAT, 1); break; | 
|  | case D3DVSDT_FLOAT2:   attribute.define(sw::STREAMTYPE_FLOAT, 2); break; | 
|  | case D3DVSDT_FLOAT3:   attribute.define(sw::STREAMTYPE_FLOAT, 3); break; | 
|  | case D3DVSDT_FLOAT4:   attribute.define(sw::STREAMTYPE_FLOAT, 4); break; | 
|  | case D3DVSDT_D3DCOLOR: attribute.define(sw::STREAMTYPE_COLOR, 4); break; | 
|  | case D3DVSDT_UBYTE4:   attribute.define(sw::STREAMTYPE_BYTE, 4);  break; | 
|  | case D3DVSDT_SHORT2:   attribute.define(sw::STREAMTYPE_SHORT, 2); break; | 
|  | case D3DVSDT_SHORT4:   attribute.define(sw::STREAMTYPE_SHORT, 4); break; | 
|  | default:               attribute.define(sw::STREAMTYPE_FLOAT, 0); ASSERT(false); | 
|  | } | 
|  |  | 
|  | switch(index) | 
|  | { | 
|  | case D3DVSDE_POSITION:     renderer->setInputStream(sw::Position, attribute);     break; | 
|  | case D3DVSDE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);  break; | 
|  | case D3DVSDE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute); break; | 
|  | case D3DVSDE_NORMAL:       renderer->setInputStream(sw::Normal, attribute);       break; | 
|  | case D3DVSDE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute);    break; | 
|  | case D3DVSDE_DIFFUSE:      renderer->setInputStream(sw::Color0, attribute);       break; | 
|  | case D3DVSDE_SPECULAR:     renderer->setInputStream(sw::Color1, attribute);       break; | 
|  | case D3DVSDE_TEXCOORD0:    renderer->setInputStream(sw::TexCoord0, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD1:    renderer->setInputStream(sw::TexCoord1, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD2:    renderer->setInputStream(sw::TexCoord2, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD3:    renderer->setInputStream(sw::TexCoord3, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD4:    renderer->setInputStream(sw::TexCoord4, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD5:    renderer->setInputStream(sw::TexCoord5, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD6:    renderer->setInputStream(sw::TexCoord6, attribute);    break; | 
|  | case D3DVSDE_TEXCOORD7:    renderer->setInputStream(sw::TexCoord7, attribute);    break; | 
|  | //	case D3DVSDE_POSITION2:    renderer->setInputStream(sw::Position1, attribute);    break; | 
|  | //	case D3DVSDE_NORMAL2:      renderer->setInputStream(sw::Normal1, attribute);      break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | (char*&)buffer += typeStride(type); | 
|  | } | 
|  | break; | 
|  | case 3:   // Tesselator data | 
|  | UNIMPLEMENTED(); | 
|  | break; | 
|  | case 4:   // Constant data | 
|  | { | 
|  | int count = (*element & 0x1E000000) >> 25; | 
|  | int index = (*element & 0x0000007F) >> 0; | 
|  |  | 
|  | SetVertexShaderConstant(index, element + 1, count); | 
|  |  | 
|  | element += 4 * count; | 
|  | } | 
|  | break; | 
|  | case 5:   // Extension | 
|  | UNIMPLEMENTED(); | 
|  | break; | 
|  | default: | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | element++; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::bindIndexBuffer(Direct3DIndexBuffer8 *indexBuffer) | 
|  | { | 
|  | sw::Resource *resource = 0; | 
|  |  | 
|  | if(indexBuffer) | 
|  | { | 
|  | resource = indexBuffer->getResource(); | 
|  | } | 
|  |  | 
|  | renderer->setIndexBuffer(resource); | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::bindLights() | 
|  | { | 
|  | if(!lightsDirty) return; | 
|  |  | 
|  | Lights::iterator i = light.begin(); | 
|  | int active = 0; | 
|  |  | 
|  | // Set and enable renderer lights | 
|  | while(active < 8) | 
|  | { | 
|  | while(i != light.end() && !i->second.enable) | 
|  | { | 
|  | i++; | 
|  | } | 
|  |  | 
|  | if(i == light.end()) | 
|  | { | 
|  | break; | 
|  | } | 
|  |  | 
|  | const Light &l = i->second; | 
|  |  | 
|  | sw::Point position(l.Position.x, l.Position.y, l.Position.z); | 
|  | sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a); | 
|  | sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a); | 
|  | sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a); | 
|  | sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z); | 
|  |  | 
|  | renderer->setLightDiffuse(active, diffuse); | 
|  | renderer->setLightSpecular(active, specular); | 
|  | renderer->setLightAmbient(active, ambient); | 
|  |  | 
|  | if(l.Type == D3DLIGHT_DIRECTIONAL) | 
|  | { | 
|  | //	goto next;   // FIXME | 
|  |  | 
|  | // FIXME: Unsupported, make it a positional light far away without falloff | 
|  | renderer->setLightPosition(active, -1000 * direction); | 
|  | renderer->setLightRange(active, l.Range); | 
|  | renderer->setLightAttenuation(active, 1, 0, 0); | 
|  | } | 
|  | else if(l.Type == D3DLIGHT_SPOT) | 
|  | { | 
|  | //	goto next;   // FIXME | 
|  |  | 
|  | // FIXME: Unsupported, make it a positional light | 
|  | renderer->setLightPosition(active, position); | 
|  | renderer->setLightRange(active, l.Range); | 
|  | renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2); | 
|  | } | 
|  | else | 
|  | { | 
|  | renderer->setLightPosition(active, position); | 
|  | renderer->setLightRange(active, l.Range); | 
|  | renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2); | 
|  | } | 
|  |  | 
|  | renderer->setLightEnable(active, true); | 
|  |  | 
|  | active++; | 
|  |  | 
|  | //	next:   // FIXME | 
|  | i++; | 
|  | } | 
|  |  | 
|  | // Remaining lights are disabled | 
|  | while(active < 8) | 
|  | { | 
|  | renderer->setLightEnable(active, false); | 
|  |  | 
|  | active++; | 
|  | } | 
|  |  | 
|  | lightsDirty= false; | 
|  | } | 
|  |  | 
|  | bool Direct3DDevice8::bindViewport() | 
|  | { | 
|  | if(viewport.Width == 0 || viewport.Height == 0) | 
|  | { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | sw::Viewport view; | 
|  | view.x0 = (float)viewport.X; | 
|  | view.y0 = (float)viewport.Y + viewport.Height; | 
|  | view.width = (float)viewport.Width; | 
|  | view.height = -(float)viewport.Height; | 
|  | view.minZ = viewport.MinZ; | 
|  | view.maxZ = viewport.MaxZ; | 
|  |  | 
|  | renderer->setViewport(view); | 
|  |  | 
|  | sw::Rect scissor; | 
|  | scissor.x0 = viewport.X; | 
|  | scissor.x1 = viewport.X + viewport.Width; | 
|  | scissor.y0 = viewport.Y; | 
|  | scissor.y1 = viewport.Y + viewport.Height; | 
|  |  | 
|  | renderer->setScissor(scissor); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::bindTextures() | 
|  | { | 
|  | for(int stage = 0; stage < 8; stage++) | 
|  | { | 
|  | Direct3DBaseTexture8 *baseTexture = texture[stage]; | 
|  | sw::Resource *resource = 0; | 
|  |  | 
|  | bool textureUsed = false; | 
|  |  | 
|  | if(pixelShader[pixelShaderHandle]) | 
|  | { | 
|  | textureUsed = pixelShader[pixelShaderHandle]->getPixelShader()->usesSampler(stage); | 
|  | } | 
|  | else | 
|  | { | 
|  | textureUsed = true;   // FIXME: Check fixed-function use? | 
|  | } | 
|  |  | 
|  | if(baseTexture && textureUsed) | 
|  | { | 
|  | resource = baseTexture->getResource(); | 
|  | } | 
|  |  | 
|  | renderer->setTextureResource(stage, resource); | 
|  |  | 
|  | if(baseTexture && textureUsed) | 
|  | { | 
|  | int levelCount = baseTexture->getInternalLevelCount(); | 
|  |  | 
|  | int textureLOD = baseTexture->GetLOD(); | 
|  | int stageLOD = textureStageState[stage][D3DTSS_MAXMIPLEVEL]; | 
|  | int LOD = textureLOD > stageLOD ? textureLOD : stageLOD; | 
|  |  | 
|  | if(textureStageState[stage][D3DTSS_MIPFILTER] == D3DTEXF_NONE) | 
|  | { | 
|  | LOD = 0; | 
|  | } | 
|  |  | 
|  | switch(baseTexture->GetType()) | 
|  | { | 
|  | case D3DRTYPE_TEXTURE: | 
|  | { | 
|  | Direct3DTexture8 *texture = dynamic_cast<Direct3DTexture8*>(baseTexture); | 
|  | Direct3DSurface8 *surface; | 
|  |  | 
|  | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
|  | { | 
|  | int surfaceLevel = mipmapLevel; | 
|  |  | 
|  | if(surfaceLevel < LOD) | 
|  | { | 
|  | surfaceLevel = LOD; | 
|  | } | 
|  |  | 
|  | if(surfaceLevel < 0) | 
|  | { | 
|  | surfaceLevel = 0; | 
|  | } | 
|  | else if(surfaceLevel >= levelCount) | 
|  | { | 
|  | surfaceLevel = levelCount - 1; | 
|  | } | 
|  |  | 
|  | surface = texture->getInternalSurfaceLevel(surfaceLevel); | 
|  | renderer->setTextureLevel(stage, 0, mipmapLevel, surface, sw::TEXTURE_2D); | 
|  | } | 
|  | } | 
|  | break; | 
|  | case D3DRTYPE_CUBETEXTURE: | 
|  | for(int face = 0; face < 6; face++) | 
|  | { | 
|  | Direct3DCubeTexture8 *cubeTexture = dynamic_cast<Direct3DCubeTexture8*>(baseTexture); | 
|  | Direct3DSurface8 *surface; | 
|  |  | 
|  | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
|  | { | 
|  | int surfaceLevel = mipmapLevel; | 
|  |  | 
|  | if(surfaceLevel < LOD) | 
|  | { | 
|  | surfaceLevel = LOD; | 
|  | } | 
|  |  | 
|  | if(surfaceLevel < 0) | 
|  | { | 
|  | surfaceLevel = 0; | 
|  | } | 
|  | else if(surfaceLevel >= levelCount) | 
|  | { | 
|  | surfaceLevel = levelCount - 1; | 
|  | } | 
|  |  | 
|  | surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel); | 
|  | renderer->setTextureLevel(stage, face, mipmapLevel, surface, sw::TEXTURE_CUBE); | 
|  | } | 
|  | } | 
|  | break; | 
|  | case D3DRTYPE_VOLUMETEXTURE: | 
|  | { | 
|  | Direct3DVolumeTexture8 *volumeTexture = dynamic_cast<Direct3DVolumeTexture8*>(baseTexture); | 
|  | Direct3DVolume8 *volume; | 
|  |  | 
|  | for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
|  | { | 
|  | int surfaceLevel = mipmapLevel; | 
|  |  | 
|  | if(surfaceLevel < LOD) | 
|  | { | 
|  | surfaceLevel = LOD; | 
|  | } | 
|  |  | 
|  | if(surfaceLevel < 0) | 
|  | { | 
|  | surfaceLevel = 0; | 
|  | } | 
|  | else if(surfaceLevel >= levelCount) | 
|  | { | 
|  | surfaceLevel = levelCount - 1; | 
|  | } | 
|  |  | 
|  | volume = volumeTexture->getInternalVolumeLevel(surfaceLevel); | 
|  | renderer->setTextureLevel(stage, 0, mipmapLevel, volume, sw::TEXTURE_3D); | 
|  | } | 
|  | } | 
|  | break; | 
|  | default: | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | renderer->setTextureLevel(stage, 0, 0, 0, sw::TEXTURE_NULL); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::bindCursor() | 
|  | { | 
|  | if(showCursor) | 
|  | { | 
|  | sw::FrameBuffer::setCursorImage(cursor); | 
|  |  | 
|  | HCURSOR oldCursor = SetCursor(nullCursor); | 
|  |  | 
|  | if(oldCursor != nullCursor) | 
|  | { | 
|  | win32Cursor = oldCursor; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | sw::FrameBuffer::setCursorImage(0); | 
|  |  | 
|  | if(GetCursor() == nullCursor) | 
|  | { | 
|  | SetCursor(win32Cursor); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | long Direct3DDevice8::updateVolume(IDirect3DVolume8 *sourceVolume, IDirect3DVolume8 *destinationVolume) | 
|  | { | 
|  | TRACE("IDirect3DVolume8 *sourceVolume = 0x%0.8p, IDirect3DVolume8 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume); | 
|  |  | 
|  | if(!sourceVolume || !destinationVolume) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DVOLUME_DESC sourceDescription; | 
|  | D3DVOLUME_DESC destinationDescription; | 
|  |  | 
|  | sourceVolume->GetDesc(&sourceDescription); | 
|  | destinationVolume->GetDesc(&destinationDescription); | 
|  |  | 
|  | if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM || | 
|  | destinationDescription.Pool != D3DPOOL_DEFAULT || | 
|  | sourceDescription.Format != destinationDescription.Format || | 
|  | sourceDescription.Width  != destinationDescription.Width || | 
|  | sourceDescription.Height != destinationDescription.Height) | 
|  | { | 
|  | return INVALIDCALL(); | 
|  | } | 
|  |  | 
|  | D3DLOCKED_BOX sourceLock; | 
|  | D3DLOCKED_BOX destinationLock; | 
|  |  | 
|  | sourceVolume->LockBox(&sourceLock, 0, 0); | 
|  | destinationVolume->LockBox(&destinationLock, 0, 0); | 
|  |  | 
|  | if(sourceLock.RowPitch != destinationLock.RowPitch || | 
|  | sourceLock.SlicePitch != destinationLock.SlicePitch) | 
|  | { | 
|  | UNIMPLEMENTED(); | 
|  | } | 
|  |  | 
|  | memcpy(destinationLock.pBits, sourceLock.pBits, sourceLock.SlicePitch * sourceDescription.Depth); | 
|  |  | 
|  | sourceVolume->UnlockBox(); | 
|  | destinationVolume->UnlockBox(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | void Direct3DDevice8::configureFPU() | 
|  | { | 
|  | unsigned short cw; | 
|  |  | 
|  | __asm | 
|  | { | 
|  | fstcw cw | 
|  | and cw, 0xFCFC   // Single-precision | 
|  | or cw, 0x003F    // Mask all exceptions | 
|  | and cw, 0xF3FF   // Round to nearest | 
|  | fldcw cw | 
|  | } | 
|  | } | 
|  | } |