| // 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, 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); |
| break; |
| case D3DCULL_CCW: |
| renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE); |
| break; |
| case D3DCULL_CW: |
| renderer->setCullMode(sw::CULL_CLOCKWISE); |
| 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 |
| } |
| } |
| } |