• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Direct3DDevice9.hpp"
16 
17 #include "Direct3D9.hpp"
18 #include "Direct3DSurface9.hpp"
19 #include "Direct3DIndexBuffer9.hpp"
20 #include "Direct3DVertexBuffer9.hpp"
21 #include "Direct3DTexture9.hpp"
22 #include "Direct3DVolumeTexture9.hpp"
23 #include "Direct3DCubeTexture9.hpp"
24 #include "Direct3DVertexDeclaration9.hpp"
25 #include "Direct3DSwapChain9.hpp"
26 #include "Direct3DPixelShader9.hpp"
27 #include "Direct3DVertexShader9.hpp"
28 #include "Direct3DStateBlock9.hpp"
29 #include "Direct3DQuery9.hpp"
30 #include "Direct3DVolume9.hpp"
31 
32 #include "Debug.hpp"
33 #include "Capabilities.hpp"
34 #include "Math.hpp"
35 #include "Renderer.hpp"
36 #include "Config.hpp"
37 #include "FrameBuffer.hpp"
38 #include "Clipper.hpp"
39 #include "Configurator.hpp"
40 #include "Timer.hpp"
41 #include "Resource.hpp"
42 
43 #include <assert.h>
44 
45 bool localShaderConstants = true;
46 
47 namespace D3D9
48 {
FtoDW(float f)49 	inline unsigned long FtoDW(float f)
50 	{
51 		return (unsigned long&)f;
52 	}
53 
Direct3DDevice9(const HINSTANCE instance,Direct3D9 * d3d9,unsigned int adapter,D3DDEVTYPE deviceType,HWND focusWindow,unsigned long behaviourFlags,D3DPRESENT_PARAMETERS * presentParameters)54 	Direct3DDevice9::Direct3DDevice9(const HINSTANCE instance, Direct3D9 *d3d9, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), adapter(adapter), d3d9(d3d9), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags)
55 	{
56 		InitializeCriticalSection(&criticalSection);
57 
58 		init = true;
59 		stateRecorder = 0;
60 
61 		d3d9->AddRef();
62 
63 		context = new sw::Context();
64 		renderer = new sw::Renderer(context, sw::Direct3D, false);
65 
66 		swapChain = 0;
67 		depthStencil = 0;
68 		autoDepthStencil = 0;
69 		renderTarget[0] = 0;
70 		renderTarget[1] = 0;
71 		renderTarget[2] = 0;
72 		renderTarget[3] = 0;
73 
74 		for(int i = 0; i < 16 + 4; i++)
75 		{
76 			texture[i] = 0;
77 		}
78 
79 		cursor = 0;
80 
81 		Reset(presentParameters);
82 
83 		pixelShader = 0;
84 		vertexShader = 0;
85 
86 		lightsDirty = true;
87 		pixelShaderDirty = true;
88 		pixelShaderConstantsBDirty = 0;
89 		pixelShaderConstantsFDirty = 0;
90 		pixelShaderConstantsIDirty = 0;
91 		vertexShaderDirty = true;
92 		vertexShaderConstantsBDirty = 0;
93 		vertexShaderConstantsFDirty = 0;
94 		vertexShaderConstantsIDirty = 0;
95 
96 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
97 		{
98 			dataStream[i] = 0;
99 			streamStride[i] = 0;
100 			streamOffset[i] = 0;
101 
102 			streamSourceFreq[i] = 1;
103 		}
104 
105 		indexData = 0;
106 		vertexDeclaration = 0;
107 
108 		D3DMATERIAL9 material;
109 
110 		material.Diffuse.r = 1.0f;
111 		material.Diffuse.g = 1.0f;
112 		material.Diffuse.b = 1.0f;
113 		material.Diffuse.a = 0.0f;
114 		material.Ambient.r = 0.0f;
115 		material.Ambient.g = 0.0f;
116 		material.Ambient.b = 0.0f;
117 		material.Ambient.a = 0.0f;
118 		material.Emissive.r = 0.0f;
119 		material.Emissive.g = 0.0f;
120 		material.Emissive.b = 0.0f;
121 		material.Emissive.a = 0.0f;
122 		material.Specular.r = 0.0f;
123 		material.Specular.g = 0.0f;
124 		material.Specular.b = 0.0f;
125 		material.Specular.a = 0.0f;
126 		material.Power = 0.0f;
127 
128 		SetMaterial(&material);
129 
130 		D3DMATRIX identity = {1, 0, 0, 0,
131 		                      0, 1, 0, 0,
132 		                      0, 0, 1, 0,
133 		                      0, 0, 0, 1};
134 
135 		SetTransform(D3DTS_VIEW, &identity);
136 		SetTransform(D3DTS_PROJECTION, &identity);
137 		SetTransform(D3DTS_TEXTURE0, &identity);
138 		SetTransform(D3DTS_TEXTURE1, &identity);
139 		SetTransform(D3DTS_TEXTURE2, &identity);
140 		SetTransform(D3DTS_TEXTURE3, &identity);
141 		SetTransform(D3DTS_TEXTURE4, &identity);
142 		SetTransform(D3DTS_TEXTURE5, &identity);
143 		SetTransform(D3DTS_TEXTURE6, &identity);
144 		SetTransform(D3DTS_TEXTURE7, &identity);
145 
146 		for(int i = 0; i < 12; i++)
147 		{
148 			SetTransform(D3DTS_WORLDMATRIX(i), &identity);
149 		}
150 
151 		for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++)
152 		{
153 			float zero[4] = {0, 0, 0, 0};
154 
155 			SetPixelShaderConstantF(i, zero, 1);
156 		}
157 
158 		for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++)
159 		{
160 			float zero[4] = {0, 0, 0, 0};
161 
162 			SetVertexShaderConstantF(i, zero, 1);
163 		}
164 
165 		for(int i = 0; i < 16; i++)
166 		{
167 			int zero[4] = {0, 0, 0, 0};
168 
169 			SetPixelShaderConstantI(i, zero, 1);
170 			SetVertexShaderConstantI(i, zero, 1);
171 			SetPixelShaderConstantB(i, &zero[0], 1);
172 			SetVertexShaderConstantB(i, &zero[0], 1);
173 		}
174 
175 		init = false;
176 
177 		if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE))
178 		{
179 			configureFPU();
180 		}
181 
182 		instancingEnabled = pixelShaderVersionX >= D3DPS_VERSION(3, 0);
183 	}
184 
~Direct3DDevice9()185 	Direct3DDevice9::~Direct3DDevice9()
186 	{
187 		delete renderer;
188 		renderer = 0;
189 		delete context;
190 		context = 0;
191 
192 		d3d9->Release();
193 		d3d9 = 0;
194 
195 		swapChain->unbind();
196 		swapChain = 0;
197 
198 		if(depthStencil)
199 		{
200 			depthStencil->unbind();
201 			depthStencil = 0;
202 		}
203 
204 		if(autoDepthStencil)
205 		{
206 			autoDepthStencil->unbind();
207 			autoDepthStencil = 0;
208 		}
209 
210 		for(int index = 0; index < 4; index++)
211 		{
212 			if(renderTarget[index])
213 			{
214 				renderTarget[index]->unbind();
215 				renderTarget[index] = 0;
216 			}
217 		}
218 
219 		if(vertexDeclaration)
220 		{
221 			vertexDeclaration->unbind();
222 			vertexDeclaration = 0;
223 		}
224 
225 		for(int i = 0; i < 16 + 4; i++)
226 		{
227 			if(texture[i])
228 			{
229 				texture[i]->unbind();
230 				texture[i] = 0;
231 			}
232 		}
233 
234 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
235 		{
236 			if(dataStream[i])
237 			{
238 				dataStream[i]->unbind();
239 				dataStream[i] = 0;
240 			}
241 		}
242 
243 		if(indexData)
244 		{
245 			indexData->unbind();
246 			indexData = 0;
247 		}
248 
249 		if(pixelShader)
250 		{
251 			pixelShader->unbind();
252 			pixelShader = 0;
253 		}
254 
255 		if(vertexShader)
256 		{
257 			vertexShader->unbind();
258 			vertexShader = 0;
259 		}
260 
261 		if(stateRecorder)
262 		{
263 			stateRecorder->unbind();
264 			stateRecorder = 0;
265 		}
266 
267 		palette.clear();
268 
269 		delete cursor;
270 
271 		DeleteCriticalSection(&criticalSection);
272 	}
273 
QueryInterface(const IID & iid,void ** object)274 	long Direct3DDevice9::QueryInterface(const IID &iid, void **object)
275 	{
276 		CriticalSection cs(this);
277 
278 		TRACE("const IID &iid = 0x%0.8p, void **object = 0x%0.8p", iid, object);
279 
280 		if(iid == IID_IDirect3DDevice9 ||
281 		   iid == IID_IUnknown)
282 		{
283 			AddRef();
284 			*object = this;
285 
286 			return S_OK;
287 		}
288 
289 		*object = 0;
290 
291 		return NOINTERFACE(iid);
292 	}
293 
AddRef()294 	unsigned long Direct3DDevice9::AddRef()
295 	{
296 		TRACE("void");
297 
298 		return Unknown::AddRef();
299 	}
300 
Release()301 	unsigned long Direct3DDevice9::Release()
302 	{
303 		TRACE("void");
304 
305 		return Unknown::Release();
306 	}
307 
BeginScene()308 	long Direct3DDevice9::BeginScene()
309 	{
310 		CriticalSection cs(this);
311 
312 		TRACE("void");
313 
314 		return D3D_OK;
315 	}
316 
BeginStateBlock()317 	long Direct3DDevice9::BeginStateBlock()
318 	{
319 		CriticalSection cs(this);
320 
321 		TRACE("void");
322 
323 		if(stateRecorder)
324 		{
325 			return INVALIDCALL();
326 		}
327 
328 		stateRecorder = new Direct3DStateBlock9(this, (D3DSTATEBLOCKTYPE)0);
329 
330 		if(!stateRecorder)
331 		{
332 			return OUTOFMEMORY();
333 		}
334 
335 		stateRecorder->bind();
336 
337 		return D3D_OK;
338 	}
339 
Clear(unsigned long count,const D3DRECT * rects,unsigned long flags,unsigned long color,float z,unsigned long stencil)340 	long Direct3DDevice9::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil)
341 	{
342 		CriticalSection cs(this);
343 
344 		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);
345 
346 		if(!rects && count != 0)
347 		{
348 			return INVALIDCALL();
349 		}
350 
351 		if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil)
352 		{
353 			return INVALIDCALL();
354 		}
355 
356 		if(flags & D3DCLEAR_STENCIL)   // Check for stencil component
357 		{
358 			D3DSURFACE_DESC description;
359 			depthStencil->GetDesc(&description);
360 
361 			switch(description.Format)
362 			{
363 			case D3DFMT_D15S1:
364 			case D3DFMT_D24S8:
365 			case D3DFMT_D24X8:
366 			case D3DFMT_D24X4S4:
367 			case D3DFMT_D24FS8:
368 			case D3DFMT_S8_LOCKABLE:   // FIXME: INVALIDCALL when trying to clear depth?
369 			case D3DFMT_DF24:
370 			case D3DFMT_DF16:
371 			case D3DFMT_INTZ:
372 				break;
373 			case D3DFMT_D16_LOCKABLE:
374 			case D3DFMT_D32:
375 			case D3DFMT_D16:
376 			case D3DFMT_D32F_LOCKABLE:
377 			case D3DFMT_D32_LOCKABLE:
378 				return INVALIDCALL();
379 			default:
380 				ASSERT(false);
381 			}
382 		}
383 
384 		if(!rects)
385 		{
386 			count = 1;
387 
388 			D3DRECT rect;
389 			rect.x1 = viewport.X;
390 			rect.x2 = viewport.X + viewport.Width;
391 			rect.y1 = viewport.Y;
392 			rect.y2 = viewport.Y + viewport.Height;
393 
394 			rects = &rect;
395 		}
396 
397 		for(unsigned int i = 0; i < count; i++)
398 		{
399 			sw::Rect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
400 
401 			clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height);
402 
403 			if(scissorEnable)
404 			{
405 				clearRect.clip(scissorRect.left, scissorRect.top, scissorRect.right, scissorRect.bottom);
406 			}
407 
408 			if(flags & D3DCLEAR_TARGET)
409 			{
410 				for(int index = 0; index < 4; index++)
411 				{
412 					if(renderTarget[index])
413 					{
414 						D3DSURFACE_DESC description;
415 						renderTarget[index]->GetDesc(&description);
416 
417 						float rgba[4];
418 						rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000;
419 						rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00;
420 						rgba[2] = (float)(color & 0x000000FF) / 0x000000FF;
421 						rgba[3] = (float)(color & 0xFF000000) / 0xFF000000;
422 
423 						if(renderState[D3DRS_SRGBWRITEENABLE] != FALSE && index == 0 && Capabilities::isSRGBwritable(description.Format))
424 						{
425 							rgba[0] = sw::linearToSRGB(rgba[0]);
426 							rgba[1] = sw::linearToSRGB(rgba[1]);
427 							rgba[2] = sw::linearToSRGB(rgba[2]);
428 						}
429 
430 						renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget[index], clearRect, 0xF);
431 					}
432 				}
433 			}
434 
435 			if(flags & D3DCLEAR_ZBUFFER)
436 			{
437 				z = sw::clamp01(z);
438 				depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
439 			}
440 
441 			if(flags & D3DCLEAR_STENCIL)
442 			{
443 				depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
444 			}
445 		}
446 
447 		return D3D_OK;
448 	}
449 
ColorFill(IDirect3DSurface9 * surface,const RECT * rect,D3DCOLOR color)450 	long Direct3DDevice9::ColorFill(IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
451 	{
452 		CriticalSection cs(this);
453 
454 		TRACE("IDirect3DSurface9 *surface = 0x%0.8p, const RECT *rect = 0x%0.8p, D3DCOLOR color = 0x%0.8X", surface, rect, color);
455 
456 		if(!surface)
457 		{
458 			return INVALIDCALL();
459 		}
460 
461 		D3DSURFACE_DESC description;
462 
463 		surface->GetDesc(&description);
464 
465 		if(description.Pool != D3DPOOL_DEFAULT)
466 		{
467 			return INVALIDCALL();
468 		}
469 
470 		if(!rect)
471 		{
472 			RECT lock;
473 
474 			lock.left = 0;
475 			lock.top = 0;
476 			lock.right = description.Width;
477 			lock.bottom = description.Height;
478 
479 			rect = &lock;
480 		}
481 
482 		static_cast<Direct3DSurface9*>(surface)->fill(color, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
483 
484 		return D3D_OK;
485 	}
486 
CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS * presentParameters,IDirect3DSwapChain9 ** swapChain)487 	long Direct3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain9 **swapChain)
488 	{
489 		CriticalSection cs(this);
490 
491 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p, IDirect3DSwapChain9 **swapChain = 0x%0.8p", presentParameters, swapChain);
492 
493 		if(!swapChain)
494 		{
495 			return INVALIDCALL();
496 		}
497 
498 		*swapChain = 0;
499 
500 		if(!presentParameters)
501 		{
502 			return INVALIDCALL();
503 		}
504 
505 		if(presentParameters->BackBufferCount > 3)
506 		{
507 			return INVALIDCALL();   // Maximum of three back buffers
508 		}
509 
510 		*swapChain = new Direct3DSwapChain9(this, presentParameters);
511 
512 		if(!*swapChain)
513 		{
514 			return OUTOFMEMORY();
515 		}
516 
517 		if(GetAvailableTextureMem() == 0)
518 		{
519 			delete *swapChain;
520 			*swapChain = 0;
521 
522 			return OUTOFVIDEOMEMORY();
523 		}
524 
525 		(*swapChain)->AddRef();
526 
527 		return D3D_OK;
528 	}
529 
CreateCubeTexture(unsigned int edgeLength,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DCubeTexture9 ** cubeTexture,void ** sharedHandle)530 	long Direct3DDevice9::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture9 **cubeTexture, void **sharedHandle)
531 	{
532 		CriticalSection cs(this);
533 
534 		TRACE("unsigned int edgeLength = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DCubeTexture9 **cubeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", edgeLength, levels, usage, format, pool, cubeTexture, sharedHandle);
535 
536 		*cubeTexture = 0;
537 
538 		if(edgeLength == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK)
539 		{
540 			return INVALIDCALL();
541 		}
542 
543 		*cubeTexture = new Direct3DCubeTexture9(this, edgeLength, levels, usage, format, pool);
544 
545 		if(!*cubeTexture)
546 		{
547 			return OUTOFMEMORY();
548 		}
549 
550 		if(GetAvailableTextureMem() == 0)
551 		{
552 			delete *cubeTexture;
553 			*cubeTexture = 0;
554 
555 			return OUTOFVIDEOMEMORY();
556 		}
557 
558 		(*cubeTexture)->AddRef();
559 
560 		return D3D_OK;
561 	}
562 
CreateDepthStencilSurface(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,unsigned long multiSampleQuality,int discard,IDirect3DSurface9 ** surface,void ** sharedHandle)563 	long Direct3DDevice9::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int discard, IDirect3DSurface9 **surface, void **sharedHandle)
564 	{
565 		CriticalSection cs(this);
566 
567 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int discard = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, discard, surface, sharedHandle);
568 
569 		*surface = 0;
570 
571 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
572 		{
573 			return INVALIDCALL();
574 		}
575 
576 		bool lockable = false;
577 
578 		switch(format)
579 		{
580 		case D3DFMT_D15S1:
581 		case D3DFMT_D24S8:
582 		case D3DFMT_D24X8:
583 		case D3DFMT_D24X4S4:
584 		case D3DFMT_D24FS8:
585 		case D3DFMT_D32:
586 		case D3DFMT_D16:
587 		case D3DFMT_DF24:
588 		case D3DFMT_DF16:
589 		case D3DFMT_INTZ:
590 			lockable = false;
591 			break;
592 		case D3DFMT_S8_LOCKABLE:
593 		case D3DFMT_D16_LOCKABLE:
594 		case D3DFMT_D32F_LOCKABLE:
595 		case D3DFMT_D32_LOCKABLE:
596 			lockable = true;
597 			break;
598 		default:
599 			ASSERT(false);
600 		}
601 
602 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL);
603 
604 		if(!*surface)
605 		{
606 			return OUTOFMEMORY();
607 		}
608 
609 		if(GetAvailableTextureMem() == 0)
610 		{
611 			delete *surface;
612 			*surface = 0;
613 
614 			return OUTOFVIDEOMEMORY();
615 		}
616 
617 		(*surface)->AddRef();
618 
619 		return D3D_OK;
620 	}
621 
CreateIndexBuffer(unsigned int length,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DIndexBuffer9 ** indexBuffer,void ** sharedHandle)622 	long Direct3DDevice9::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **indexBuffer, void **sharedHandle)
623 	{
624 		CriticalSection cs(this);
625 
626 		TRACE("unsigned int length = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DIndexBuffer9 **indexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, format, pool, indexBuffer, sharedHandle);
627 
628 		*indexBuffer = new Direct3DIndexBuffer9(this, length, usage, format, pool);
629 
630 		if(!*indexBuffer)
631 		{
632 			return OUTOFMEMORY();
633 		}
634 
635 		if(GetAvailableTextureMem() == 0)
636 		{
637 			delete *indexBuffer;
638 			*indexBuffer = 0;
639 
640 			return OUTOFVIDEOMEMORY();
641 		}
642 
643 		(*indexBuffer)->AddRef();
644 
645 		return D3D_OK;
646 	}
647 
CreateOffscreenPlainSurface(unsigned int width,unsigned int height,D3DFORMAT format,D3DPOOL pool,IDirect3DSurface9 ** surface,void ** sharedHandle)648 	long Direct3DDevice9::CreateOffscreenPlainSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface, void **sharedHandle)
649 	{
650 		CriticalSection cs(this);
651 
652 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, pool, surface, sharedHandle);
653 
654 		*surface = 0;
655 
656 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK)   // FIXME: Allow all formats supported by runtime/REF
657 		{
658 			return INVALIDCALL();
659 		}
660 
661 		if(pool == D3DPOOL_MANAGED)
662 		{
663 			return INVALIDCALL();
664 		}
665 
666 		*surface = new Direct3DSurface9(this, this, width, height, format, pool, D3DMULTISAMPLE_NONE, 0, true, 0);
667 
668 		if(!*surface)
669 		{
670 			return OUTOFMEMORY();
671 		}
672 
673 		if(GetAvailableTextureMem() == 0)
674 		{
675 			delete *surface;
676 			*surface = 0;
677 
678 			return OUTOFVIDEOMEMORY();
679 		}
680 
681 		(*surface)->AddRef();
682 
683 		return D3D_OK;
684 	}
685 
CreatePixelShader(const unsigned long * function,IDirect3DPixelShader9 ** shader)686 	long Direct3DDevice9::CreatePixelShader(const unsigned long *function, IDirect3DPixelShader9 **shader)
687 	{
688 		CriticalSection cs(this);
689 
690 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DPixelShader9 **shader = 0x%0.8p", function, shader);
691 
692 		if(!shader)
693 		{
694 			return INVALIDCALL();
695 		}
696 
697 		*shader = 0;
698 
699 		if(!sw::PixelShader::validate(function) || function[0] > pixelShaderVersionX)
700 		{
701 			return INVALIDCALL();   // Shader contains unsupported operations
702 		}
703 
704 		*shader = new Direct3DPixelShader9(this, function);
705 
706 		if(!*shader)
707 		{
708 			return OUTOFMEMORY();
709 		}
710 
711 		(*shader)->AddRef();
712 
713 		return D3D_OK;
714 	}
715 
CreateQuery(D3DQUERYTYPE type,IDirect3DQuery9 ** query)716 	long Direct3DDevice9::CreateQuery(D3DQUERYTYPE type, IDirect3DQuery9 **query)
717 	{
718 		CriticalSection cs(this);
719 
720 		TRACE("D3DQUERYTYPE type = %d, IDirect3DQuery9 **query = 0x%0.8p", type, query);
721 
722 		if(query == 0)   // Support checked
723 		{
724 			switch(type)
725 			{
726 			case D3DQUERYTYPE_VCACHE:				return D3D_OK;
727 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE();
728 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE();
729 			case D3DQUERYTYPE_EVENT:				return D3D_OK;
730 			case D3DQUERYTYPE_OCCLUSION:			return D3D_OK;
731 			case D3DQUERYTYPE_TIMESTAMP:			return D3D_OK;
732 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	return D3D_OK;
733 			case D3DQUERYTYPE_TIMESTAMPFREQ:		return D3D_OK;
734 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE();
735 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE();
736 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE();
737 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE();
738 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE();
739 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE();
740 			default:								ASSERT(false);   return NOTAVAILABLE();
741 			}
742 		}
743 		else
744 		{
745 			switch(type)
746 			{
747 			case D3DQUERYTYPE_VCACHE:				break;
748 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE();
749 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE();
750 			case D3DQUERYTYPE_EVENT:				break;
751 			case D3DQUERYTYPE_OCCLUSION:			break;
752 			case D3DQUERYTYPE_TIMESTAMP:			break;
753 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	break;
754 			case D3DQUERYTYPE_TIMESTAMPFREQ:		break;
755 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE();
756 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE();
757 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE();
758 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE();
759 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE();
760 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE();
761 			default:								ASSERT(false);   return NOTAVAILABLE();
762 			}
763 
764 			*query = new Direct3DQuery9(this, type);
765 
766 			if(!*query)
767 			{
768 				return OUTOFMEMORY();
769 			}
770 
771 			(*query)->AddRef();
772 
773 			return D3D_OK;
774 		}
775 	}
776 
CreateRenderTarget(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,unsigned long multiSampleQuality,int lockable,IDirect3DSurface9 ** surface,void ** sharedHandle)777 	long Direct3DDevice9::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int lockable, IDirect3DSurface9 **surface, void **sharedHandle)
778 	{
779 		CriticalSection cs(this);
780 
781 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int lockable = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, lockable, surface, sharedHandle);
782 
783 		*surface = 0;
784 
785 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
786 		{
787 			return INVALIDCALL();
788 		}
789 
790 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable != FALSE, D3DUSAGE_RENDERTARGET);
791 
792 		if(!*surface)
793 		{
794 			return OUTOFMEMORY();
795 		}
796 
797 		if(GetAvailableTextureMem() == 0)
798 		{
799 			delete *surface;
800 			*surface = 0;
801 
802 			return OUTOFVIDEOMEMORY();
803 		}
804 
805 		(*surface)->AddRef();
806 
807 		return D3D_OK;
808 	}
809 
CreateStateBlock(D3DSTATEBLOCKTYPE type,IDirect3DStateBlock9 ** stateBlock)810 	long Direct3DDevice9::CreateStateBlock(D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateBlock)
811 	{
812 		CriticalSection cs(this);
813 
814 		TRACE("D3DSTATEBLOCKTYPE type = %d, IDirect3DStateBlock9 **stateBlock = 0x%0.8p", type, stateBlock);
815 
816 		*stateBlock = new Direct3DStateBlock9(this, type);
817 
818 		if(!*stateBlock)
819 		{
820 			return OUTOFMEMORY();
821 		}
822 
823 		(*stateBlock)->AddRef();
824 
825 		return D3D_OK;
826 	}
827 
CreateTexture(unsigned int width,unsigned int height,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DTexture9 ** texture,void ** sharedHandle)828 	long Direct3DDevice9::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9 **texture, void **sharedHandle)
829 	{
830 		CriticalSection cs(this);
831 
832 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DTexture9 **texture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, levels, usage, format, pool, texture, sharedHandle);
833 
834 		*texture = 0;
835 
836 		if(width == 0 || height == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK)
837 		{
838 			return INVALIDCALL();
839 		}
840 
841 		*texture = new Direct3DTexture9(this, width, height, levels, usage, format, pool);
842 
843 		if(!*texture)
844 		{
845 			return OUTOFMEMORY();
846 		}
847 
848 		if(GetAvailableTextureMem() == 0)
849 		{
850 			delete *texture;
851 			*texture = 0;
852 
853 			return OUTOFVIDEOMEMORY();
854 		}
855 
856 		(*texture)->AddRef();
857 
858 		return D3D_OK;
859 	}
860 
CreateVertexBuffer(unsigned int length,unsigned long usage,unsigned long FVF,D3DPOOL pool,IDirect3DVertexBuffer9 ** vertexBuffer,void ** sharedHandle)861 	long Direct3DDevice9::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer9 **vertexBuffer, void **sharedHandle)
862 	{
863 		CriticalSection cs(this);
864 
865 		TRACE("unsigned int length = %d, unsigned long usage = %d, unsigned long FVF = 0x%0.8X, D3DPOOL pool = %d, IDirect3DVertexBuffer9 **vertexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, FVF, pool, vertexBuffer, sharedHandle);
866 
867 		*vertexBuffer = new Direct3DVertexBuffer9(this, length, usage, FVF, pool);
868 
869 		if(!*vertexBuffer)
870 		{
871 			return OUTOFMEMORY();
872 		}
873 
874 		if(GetAvailableTextureMem() == 0)
875 		{
876 			delete *vertexBuffer;
877 			*vertexBuffer = 0;
878 
879 			return OUTOFVIDEOMEMORY();
880 		}
881 
882 		(*vertexBuffer)->AddRef();
883 
884 		return D3D_OK;
885 	}
886 
CreateVertexDeclaration(const D3DVERTEXELEMENT9 * vertexElements,IDirect3DVertexDeclaration9 ** declaration)887 	long Direct3DDevice9::CreateVertexDeclaration(const D3DVERTEXELEMENT9 *vertexElements, IDirect3DVertexDeclaration9 **declaration)
888 	{
889 		CriticalSection cs(this);
890 
891 		TRACE("const D3DVERTEXELEMENT9 *vertexElements = 0x%0.8p, IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", vertexElements, declaration);
892 
893 		if(!declaration)
894 		{
895 			return INVALIDCALL();
896 		}
897 
898 		const D3DVERTEXELEMENT9 *element = vertexElements;
899 
900 		while(element->Stream != 0xFF)
901 		{
902 			if(element->Type > D3DDECLTYPE_UNUSED)   // FIXME: Check other fields too
903 			{
904 				return FAIL();
905 			}
906 
907 			element++;
908 		}
909 
910 		*declaration = new Direct3DVertexDeclaration9(this, vertexElements);
911 
912 		if(!*declaration)
913 		{
914 			return OUTOFMEMORY();
915 		}
916 
917 		(*declaration)->AddRef();
918 
919 		return D3D_OK;
920 	}
921 
CreateVertexShader(const unsigned long * function,IDirect3DVertexShader9 ** shader)922 	long Direct3DDevice9::CreateVertexShader(const unsigned long *function, IDirect3DVertexShader9 **shader)
923 	{
924 		CriticalSection cs(this);
925 
926 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DVertexShader9 **shader = 0x%0.8p", function, shader);
927 
928 		if(!shader)
929 		{
930 			return INVALIDCALL();
931 		}
932 
933 		*shader = 0;
934 
935 		if(!sw::VertexShader::validate(function) || function[0] > vertexShaderVersionX)
936 		{
937 			return INVALIDCALL();   // Shader contains unsupported operations
938 		}
939 
940 		*shader = new Direct3DVertexShader9(this, function);
941 
942 		if(!*shader)
943 		{
944 			return OUTOFMEMORY();
945 		}
946 
947 		(*shader)->AddRef();
948 
949 		return D3D_OK;
950 	}
951 
CreateVolumeTexture(unsigned int width,unsigned int height,unsigned int depth,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DVolumeTexture9 ** volumeTexture,void ** sharedHandle)952 	long Direct3DDevice9::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture9 **volumeTexture, void **sharedHandle)
953 	{
954 		CriticalSection cs(this);
955 
956 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int depth = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DVolumeTexture9 **volumeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, depth, levels, usage, format, pool, volumeTexture, sharedHandle);
957 
958 		*volumeTexture = 0;
959 
960 		if(width == 0 || height == 0 || depth == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK)
961 		{
962 			return INVALIDCALL();
963 		}
964 
965 		*volumeTexture = new Direct3DVolumeTexture9(this, width, height, depth, levels, usage, format, pool);
966 
967 		if(!*volumeTexture)
968 		{
969 			return OUTOFMEMORY();
970 		}
971 
972 		if(GetAvailableTextureMem() == 0)
973 		{
974 			delete *volumeTexture;
975 			*volumeTexture = 0;
976 
977 			return OUTOFVIDEOMEMORY();
978 		}
979 
980 		(*volumeTexture)->AddRef();
981 
982 		return D3D_OK;
983 	}
984 
DeletePatch(unsigned int handle)985 	long Direct3DDevice9::DeletePatch(unsigned int handle)
986 	{
987 		CriticalSection cs(this);
988 
989 		TRACE("unsigned int handle = %d", handle);
990 
991 		UNIMPLEMENTED();
992 
993 		return D3D_OK;
994 	}
995 
DrawIndexedPrimitive(D3DPRIMITIVETYPE type,int baseVertexIndex,unsigned int minIndex,unsigned int numVertices,unsigned int startIndex,unsigned int primitiveCount)996 	long Direct3DDevice9::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, int baseVertexIndex, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount)
997 	{
998 		CriticalSection cs(this);
999 
1000 		TRACE("D3DPRIMITIVETYPE type = %d, int baseVertexIndex = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int startIndex = %d, unsigned int primitiveCount = %d", type, baseVertexIndex, minIndex, numVertices, startIndex, primitiveCount);
1001 
1002 		if(!indexData)
1003 		{
1004 			return INVALIDCALL();
1005 		}
1006 
1007 		if(!bindResources(indexData) || !primitiveCount)
1008 		{
1009 			return D3D_OK;
1010 		}
1011 
1012 		unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account
1013 
1014 		sw::DrawType drawType;
1015 
1016 		if(indexData->is32Bit())
1017 		{
1018 			switch(type)
1019 			{
1020 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
1021 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
1022 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
1023 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
1024 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
1025 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break;
1026 			default:
1027 				ASSERT(false);
1028 			}
1029 		}
1030 		else
1031 		{
1032 			switch(type)
1033 			{
1034 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
1035 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
1036 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
1037 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
1038 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
1039 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
1040 			default:
1041 				ASSERT(false);
1042 			}
1043 		}
1044 
1045 		if((streamSourceFreq[0] & D3DSTREAMSOURCE_INDEXEDDATA) && instanceData())
1046 		{
1047 			int instanceCount = (streamSourceFreq[0] & ~D3DSTREAMSOURCE_INDEXEDDATA);
1048 
1049 			for(int instance = 0; instance < instanceCount; instance++)
1050 			{
1051 				bindVertexStreams(baseVertexIndex, true, instance);
1052 				renderer->draw(drawType, indexOffset, primitiveCount, instance == 0);
1053 			}
1054 		}
1055 		else
1056 		{
1057 			bindVertexStreams(baseVertexIndex, false, 0);
1058 			renderer->draw(drawType, indexOffset, primitiveCount);
1059 		}
1060 
1061 		return D3D_OK;
1062 	}
1063 
DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type,unsigned int minIndex,unsigned int numVertices,unsigned int primitiveCount,const void * indexData,D3DFORMAT indexDataFormat,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)1064 	long Direct3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
1065 	{
1066 		CriticalSection cs(this);
1067 
1068 		TRACE("D3DPRIMITIVETYPE type = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int primitiveCount = %d, const void *indexData = 0x%0.8p, D3DFORMAT indexDataFormat = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", type, minIndex, numVertices, primitiveCount, indexData, indexDataFormat, vertexStreamZeroData, vertexStreamZeroStride);
1069 
1070 		if(!vertexStreamZeroData || !indexData)
1071 		{
1072 			return INVALIDCALL();
1073 		}
1074 
1075 		int length = (minIndex + numVertices) * vertexStreamZeroStride;
1076 
1077 		Direct3DVertexBuffer9 *vertexBuffer = new Direct3DVertexBuffer9(this, length, 0, 0, D3DPOOL_DEFAULT);
1078 
1079 		void *data;
1080 		vertexBuffer->Lock(0, 0, &data, 0);
1081 		memcpy(data, vertexStreamZeroData, length);
1082 		vertexBuffer->Unlock();
1083 
1084 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride);
1085 
1086 		switch(type)
1087 		{
1088 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
1089 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
1090 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
1091 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
1092 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
1093 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
1094 		default:
1095 			ASSERT(false);
1096 		}
1097 
1098 		length *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2;
1099 
1100 		Direct3DIndexBuffer9 *indexBuffer = new Direct3DIndexBuffer9(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT);
1101 
1102 		indexBuffer->Lock(0, 0, &data, 0);
1103 		memcpy(data, indexData, length);
1104 		indexBuffer->Unlock();
1105 
1106 		SetIndices(indexBuffer);
1107 
1108 		if(!bindResources(indexBuffer) || !primitiveCount)
1109 		{
1110 			vertexBuffer->Release();
1111 
1112 			return D3D_OK;
1113 		}
1114 
1115 		sw::DrawType drawType;
1116 
1117 		if(indexDataFormat == D3DFMT_INDEX32)
1118 		{
1119 			switch(type)
1120 			{
1121 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
1122 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
1123 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
1124 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
1125 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
1126 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break;
1127 			default:
1128 				ASSERT(false);
1129 			}
1130 		}
1131 		else
1132 		{
1133 			switch(type)
1134 			{
1135 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
1136 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
1137 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
1138 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
1139 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
1140 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
1141 			default:
1142 				ASSERT(false);
1143 			}
1144 		}
1145 
1146 		bindVertexStreams(0, false, 0);
1147 		renderer->draw(drawType, 0, primitiveCount);
1148 
1149 		SetStreamSource(0, 0, 0, 0);
1150 		SetIndices(0);
1151 
1152 		return D3D_OK;
1153 	}
1154 
DrawPrimitive(D3DPRIMITIVETYPE primitiveType,unsigned int startVertex,unsigned int primitiveCount)1155 	long Direct3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount)
1156 	{
1157 		CriticalSection cs(this);
1158 
1159 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int startVertex = %d, unsigned int primitiveCount = %d", primitiveType, startVertex, primitiveCount);
1160 
1161 		if(!bindResources(0) || !primitiveCount)
1162 		{
1163 			return D3D_OK;
1164 		}
1165 
1166 		sw::DrawType drawType;
1167 
1168 		switch(primitiveType)
1169 		{
1170 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
1171 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
1172 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
1173 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
1174 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
1175 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
1176 		default:
1177 			ASSERT(false);
1178 		}
1179 
1180 		bindVertexStreams(startVertex, false, 0);
1181 		renderer->draw(drawType, 0, primitiveCount);
1182 
1183 		return D3D_OK;
1184 	}
1185 
DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType,unsigned int primitiveCount,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)1186 	long Direct3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
1187 	{
1188 		CriticalSection cs(this);
1189 
1190 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int primitiveCount = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", primitiveType, primitiveCount, vertexStreamZeroData, vertexStreamZeroStride);
1191 
1192 		if(!vertexStreamZeroData)
1193 		{
1194 			return INVALIDCALL();
1195 		}
1196 
1197 		IDirect3DVertexBuffer9 *vertexBuffer = 0;
1198 		int length = 0;
1199 
1200 		switch(primitiveType)
1201 		{
1202 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
1203 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
1204 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
1205 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
1206 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
1207 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
1208 		default:
1209 			ASSERT(false);
1210 		}
1211 
1212 		length *= vertexStreamZeroStride;
1213 
1214 		CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer, 0);
1215 
1216 		void *data;
1217 		vertexBuffer->Lock(0, 0, &data, 0);
1218 		memcpy(data, vertexStreamZeroData, length);
1219 		vertexBuffer->Unlock();
1220 
1221 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride);
1222 
1223 		if(!bindResources(0) || !primitiveCount)
1224 		{
1225 			vertexBuffer->Release();
1226 
1227 			return D3D_OK;
1228 		}
1229 
1230 		sw::DrawType drawType;
1231 
1232 		switch(primitiveType)
1233 		{
1234 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
1235 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
1236 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
1237 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
1238 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
1239 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
1240 		default:
1241 			ASSERT(false);
1242 		}
1243 
1244 		bindVertexStreams(0, false, 0);
1245 		renderer->draw(drawType, 0, primitiveCount);
1246 
1247 		SetStreamSource(0, 0, 0, 0);
1248 		vertexBuffer->Release();
1249 
1250 		return D3D_OK;
1251 	}
1252 
DrawRectPatch(unsigned int handle,const float * numSegs,const D3DRECTPATCH_INFO * rectPatchInfo)1253 	long Direct3DDevice9::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo)
1254 	{
1255 		CriticalSection cs(this);
1256 
1257 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DRECTPATCH_INFO *rectPatchInfo = 0x%0.8p", handle, numSegs, rectPatchInfo);
1258 
1259 		if(!numSegs || !rectPatchInfo)
1260 		{
1261 			return INVALIDCALL();
1262 		}
1263 
1264 		UNIMPLEMENTED();
1265 
1266 		return D3D_OK;
1267 	}
1268 
DrawTriPatch(unsigned int handle,const float * numSegs,const D3DTRIPATCH_INFO * triPatchInfo)1269 	long Direct3DDevice9::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo)
1270 	{
1271 		CriticalSection cs(this);
1272 
1273 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DTRIPATCH_INFO *triPatchInfo = 0x%0.8p", handle, numSegs, triPatchInfo);
1274 
1275 		if(!numSegs || !triPatchInfo)
1276 		{
1277 			return INVALIDCALL();
1278 		}
1279 
1280 		UNIMPLEMENTED();
1281 
1282 		return D3D_OK;
1283 	}
1284 
EndScene()1285 	long Direct3DDevice9::EndScene()
1286 	{
1287 		CriticalSection cs(this);
1288 
1289 		TRACE("void");
1290 
1291 		return D3D_OK;
1292 	}
1293 
EndStateBlock(IDirect3DStateBlock9 ** stateBlock)1294 	long Direct3DDevice9::EndStateBlock(IDirect3DStateBlock9 **stateBlock)
1295 	{
1296 		CriticalSection cs(this);
1297 
1298 		TRACE("IDirect3DStateBlock9 **stateBlock = 0x%0.8p", stateBlock);
1299 
1300 		if(!stateBlock)
1301 		{
1302 			return INVALIDCALL();
1303 		}
1304 
1305 		*stateBlock = 0;
1306 
1307 		if(!stateRecorder)
1308 		{
1309 			return INVALIDCALL();
1310 		}
1311 
1312 		*stateBlock = stateRecorder;
1313 		stateRecorder->AddRef();
1314 		stateRecorder->unbind();
1315 		stateRecorder = 0;   // Stop recording
1316 
1317 		return D3D_OK;
1318 	}
1319 
EvictManagedResources()1320 	long Direct3DDevice9::EvictManagedResources()
1321 	{
1322 		CriticalSection cs(this);
1323 
1324 		TRACE("void");
1325 
1326 		//	UNIMPLEMENTED();   // FIXME
1327 
1328 		return D3D_OK;
1329 	}
1330 
GetAvailableTextureMem()1331 	unsigned int Direct3DDevice9::GetAvailableTextureMem()
1332 	{
1333 		CriticalSection cs(this);
1334 
1335 		TRACE("void");
1336 
1337 		int availableMemory = textureMemory - Direct3DResource9::getMemoryUsage();
1338 		if(availableMemory < 0) availableMemory = 0;
1339 
1340 		// Round to nearest MB
1341 		return (availableMemory + 0x80000) & 0xFFF00000;
1342 	}
1343 
GetBackBuffer(unsigned int swapChainIndex,unsigned int backBufferIndex,D3DBACKBUFFER_TYPE type,IDirect3DSurface9 ** backBuffer)1344 	long Direct3DDevice9::GetBackBuffer(unsigned int swapChainIndex, unsigned int backBufferIndex, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer)
1345 	{
1346 		CriticalSection cs(this);
1347 
1348 		TRACE("unsigned int swapChainIndex = %d, unsigned int backBufferIndex = %d, D3DBACKBUFFER_TYPE type = %d, IDirect3DSurface9 **backBuffer = 0x%0.8p", swapChainIndex, backBufferIndex, type, backBuffer);
1349 
1350 		if(swapChainIndex >= GetNumberOfSwapChains())
1351 		{
1352 			return INVALIDCALL();
1353 		}
1354 
1355 		return swapChain->GetBackBuffer(backBufferIndex, type, backBuffer);
1356 	}
1357 
GetClipPlane(unsigned long index,float * plane)1358 	long Direct3DDevice9::GetClipPlane(unsigned long index, float *plane)
1359 	{
1360 		CriticalSection cs(this);
1361 
1362 		TRACE("unsigned long index = %d, float *plane = 0x%0.8p", index, plane);
1363 
1364 		if(!plane || index >= 6)
1365 		{
1366 			return INVALIDCALL();
1367 		}
1368 
1369 		plane[0] = this->plane[index][0];
1370 		plane[1] = this->plane[index][1];
1371 		plane[2] = this->plane[index][2];
1372 		plane[3] = this->plane[index][3];
1373 
1374 		return D3D_OK;
1375 	}
1376 
GetClipStatus(D3DCLIPSTATUS9 * clipStatus)1377 	long Direct3DDevice9::GetClipStatus(D3DCLIPSTATUS9 *clipStatus)
1378 	{
1379 		CriticalSection cs(this);
1380 
1381 		TRACE("D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus);
1382 
1383 		if(!clipStatus)
1384 		{
1385 			return INVALIDCALL();
1386 		}
1387 
1388 		*clipStatus = this->clipStatus;
1389 
1390 		return D3D_OK;
1391 	}
1392 
GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS * parameters)1393 	long Direct3DDevice9::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters)
1394 	{
1395 		CriticalSection cs(this);
1396 
1397 		TRACE("D3DDEVICE_CREATION_PARAMETERS *parameters = 0x%0.8p", parameters);
1398 
1399 		if(!parameters)
1400 		{
1401 			return INVALIDCALL();
1402 		}
1403 
1404 		parameters->AdapterOrdinal = adapter;
1405 		parameters->BehaviorFlags = behaviourFlags;
1406 		parameters->DeviceType = deviceType;
1407 		parameters->hFocusWindow = focusWindow;
1408 
1409 		return D3D_OK;
1410 	}
1411 
GetCurrentTexturePalette(unsigned int * paletteNumber)1412 	long Direct3DDevice9::GetCurrentTexturePalette(unsigned int *paletteNumber)
1413 	{
1414 		CriticalSection cs(this);
1415 
1416 		TRACE("unsigned int *paletteNumber = 0x%0.8p", paletteNumber);
1417 
1418 		if(!paletteNumber)
1419 		{
1420 			return INVALIDCALL();
1421 		}
1422 
1423 		*paletteNumber = currentPalette;
1424 
1425 		return D3D_OK;
1426 	}
1427 
GetDepthStencilSurface(IDirect3DSurface9 ** depthStencilSurface)1428 	long Direct3DDevice9::GetDepthStencilSurface(IDirect3DSurface9 **depthStencilSurface)
1429 	{
1430 		CriticalSection cs(this);
1431 
1432 		TRACE("IDirect3DSurface9 **depthStencilSurface = 0x%0.8p", depthStencilSurface);
1433 
1434 		if(!depthStencilSurface)
1435 		{
1436 			return INVALIDCALL();
1437 		}
1438 
1439 		*depthStencilSurface = depthStencil;
1440 
1441 		if(depthStencil)
1442 		{
1443 			depthStencil->AddRef();
1444 		}
1445 		else
1446 		{
1447 			return NOTFOUND();
1448 		}
1449 
1450 		return D3D_OK;
1451 	}
1452 
GetDeviceCaps(D3DCAPS9 * caps)1453 	long Direct3DDevice9::GetDeviceCaps(D3DCAPS9 *caps)
1454 	{
1455 		CriticalSection cs(this);
1456 
1457 		TRACE("D3DCAPS9 *caps = 0x%0.8p", caps);
1458 
1459 		return d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps);
1460 	}
1461 
GetDirect3D(IDirect3D9 ** d3d9)1462 	long Direct3DDevice9::GetDirect3D(IDirect3D9 **d3d9)
1463 	{
1464 		CriticalSection cs(this);
1465 
1466 		TRACE("IDirect3D9 **d3d9 = 0x%0.8p", d3d9);
1467 
1468 		if(!d3d9)
1469 		{
1470 			return INVALIDCALL();
1471 		}
1472 
1473 		*d3d9 = this->d3d9;
1474 		this->d3d9->AddRef();
1475 
1476 		return D3D_OK;
1477 	}
1478 
GetDisplayMode(unsigned int index,D3DDISPLAYMODE * mode)1479 	long Direct3DDevice9::GetDisplayMode(unsigned int index, D3DDISPLAYMODE *mode)
1480 	{
1481 		CriticalSection cs(this);
1482 
1483 		TRACE("unsigned int index = %d, D3DDISPLAYMODE *mode = 0x%0.8p", index, mode);
1484 
1485 		if(index >= GetNumberOfSwapChains())
1486 		{
1487 			return INVALIDCALL();
1488 		}
1489 
1490 		return swapChain->GetDisplayMode(mode);
1491 	}
1492 
GetFrontBufferData(unsigned int index,IDirect3DSurface9 * destSurface)1493 	long Direct3DDevice9::GetFrontBufferData(unsigned int index, IDirect3DSurface9 *destSurface)
1494 	{
1495 		CriticalSection cs(this);
1496 
1497 		TRACE("unsigned int index = %d, IDirect3DSurface9 *destSurface = %p", index, destSurface);
1498 
1499 		if(index >= GetNumberOfSwapChains())
1500 		{
1501 			return INVALIDCALL();
1502 		}
1503 
1504 		return swapChain->GetFrontBufferData(destSurface);
1505 	}
1506 
GetFVF(unsigned long * FVF)1507 	long Direct3DDevice9::GetFVF(unsigned long *FVF)
1508 	{
1509 		CriticalSection cs(this);
1510 
1511 		TRACE("unsigned long *FVF = 0x%0.8p", FVF);
1512 
1513 		if(!FVF)
1514 		{
1515 			return INVALIDCALL();
1516 		}
1517 
1518 		if(vertexDeclaration)
1519 		{
1520 			*FVF = vertexDeclaration->getFVF();
1521 		}
1522 		else
1523 		{
1524 			*FVF = 0;
1525 		}
1526 
1527 		return D3D_OK;
1528 	}
1529 
GetGammaRamp(unsigned int index,D3DGAMMARAMP * ramp)1530 	void Direct3DDevice9::GetGammaRamp(unsigned int index, D3DGAMMARAMP *ramp)
1531 	{
1532 		CriticalSection cs(this);
1533 
1534 		TRACE("unsigned int index = %d, D3DGAMMARAMP *ramp = 0x%0.8p", index, ramp);
1535 
1536 		if(!ramp || index >= GetNumberOfSwapChains())
1537 		{
1538 			return;
1539 		}
1540 
1541 		swapChain->getGammaRamp((sw::GammaRamp*)ramp);
1542 	}
1543 
GetIndices(IDirect3DIndexBuffer9 ** indexData)1544 	long Direct3DDevice9::GetIndices(IDirect3DIndexBuffer9 **indexData)
1545 	{
1546 		CriticalSection cs(this);
1547 
1548 		TRACE("IDirect3DIndexBuffer9 **indexData = 0x%0.8p", indexData);
1549 
1550 		if(!indexData)
1551 		{
1552 			return INVALIDCALL();
1553 		}
1554 
1555 		*indexData = this->indexData;
1556 
1557 		if(this->indexData)
1558 		{
1559 			this->indexData->AddRef();
1560 		}
1561 
1562 		return D3D_OK;
1563 	}
1564 
GetLight(unsigned long index,D3DLIGHT9 * light)1565 	long Direct3DDevice9::GetLight(unsigned long index, D3DLIGHT9 *light)
1566 	{
1567 		CriticalSection cs(this);
1568 
1569 		TRACE("unsigned long index = %d, D3DLIGHT9 *light = 0x%0.8p", index, light);
1570 
1571 		if(!light)
1572 		{
1573 			return INVALIDCALL();
1574 		}
1575 
1576 		if(!this->light.exists(index))
1577 		{
1578 			return INVALIDCALL();
1579 		}
1580 
1581 		*light = this->light[index];
1582 
1583 		return D3D_OK;
1584 	}
1585 
GetLightEnable(unsigned long index,int * enable)1586 	long Direct3DDevice9::GetLightEnable(unsigned long index, int *enable)
1587 	{
1588 		CriticalSection cs(this);
1589 
1590 		TRACE("unsigned long index = %d, int *enable = 0x%0.8p", index, enable);
1591 
1592 		if(!enable)
1593 		{
1594 			return INVALIDCALL();
1595 		}
1596 
1597 		if(!light.exists(index))
1598 		{
1599 			return INVALIDCALL();
1600 		}
1601 
1602 		*enable = light[index].enable ? 128 : 0;
1603 
1604 		return D3D_OK;
1605 	}
1606 
GetMaterial(D3DMATERIAL9 * material)1607 	long Direct3DDevice9::GetMaterial(D3DMATERIAL9 *material)
1608 	{
1609 		CriticalSection cs(this);
1610 
1611 		TRACE("D3DMATERIAL9 *material = 0x%0.8p", material);
1612 
1613 		if(!material)
1614 		{
1615 			return INVALIDCALL();
1616 		}
1617 
1618 		*material = this->material;
1619 
1620 		return D3D_OK;
1621 	}
1622 
GetNPatchMode()1623 	float Direct3DDevice9::GetNPatchMode()
1624 	{
1625 		CriticalSection cs(this);
1626 
1627 		TRACE("void");
1628 
1629 		return 0.0f;   // FIXME: Unimplemented
1630 	}
1631 
GetNumberOfSwapChains()1632 	unsigned int Direct3DDevice9::GetNumberOfSwapChains()
1633 	{
1634 		CriticalSection cs(this);
1635 
1636 		TRACE("void");
1637 
1638 		return 1;
1639 	}
1640 
GetPaletteEntries(unsigned int paletteNumber,PALETTEENTRY * entries)1641 	long Direct3DDevice9::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries)
1642 	{
1643 		CriticalSection cs(this);
1644 
1645 		TRACE("unsigned int paletteNumber = %d, PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries);
1646 
1647 		if(paletteNumber > 0xFFFF || !entries)
1648 		{
1649 			return INVALIDCALL();
1650 		}
1651 
1652 		for(int i = 0; i < 256; i++)
1653 		{
1654 			entries[i] = palette[paletteNumber].entry[i];
1655 		}
1656 
1657 		return D3D_OK;
1658 	}
1659 
GetPixelShader(IDirect3DPixelShader9 ** shader)1660 	long Direct3DDevice9::GetPixelShader(IDirect3DPixelShader9 **shader)
1661 	{
1662 		CriticalSection cs(this);
1663 
1664 		TRACE("IDirect3DPixelShader9 **shader = 0x%0.8p", shader);
1665 
1666 		if(!shader)
1667 		{
1668 			return INVALIDCALL();
1669 		}
1670 
1671 		if(pixelShader)
1672 		{
1673 			pixelShader->AddRef();
1674 		}
1675 
1676 		*shader = pixelShader;
1677 
1678 		return D3D_OK;
1679 	}
1680 
GetPixelShaderConstantB(unsigned int startRegister,int * constantData,unsigned int count)1681 	long Direct3DDevice9::GetPixelShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count)
1682 	{
1683 		CriticalSection cs(this);
1684 
1685 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1686 
1687 		if(!constantData)
1688 		{
1689 			return INVALIDCALL();
1690 		}
1691 
1692 		for(unsigned int i = 0; i < count; i++)
1693 		{
1694 			constantData[i] = pixelShaderConstantB[startRegister + i];
1695 		}
1696 
1697 		return D3D_OK;
1698 	}
1699 
GetPixelShaderConstantF(unsigned int startRegister,float * constantData,unsigned int count)1700 	long Direct3DDevice9::GetPixelShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count)
1701 	{
1702 		CriticalSection cs(this);
1703 
1704 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1705 
1706 		if(!constantData)
1707 		{
1708 			return INVALIDCALL();
1709 		}
1710 
1711 		for(unsigned int i = 0; i < count; i++)
1712 		{
1713 			constantData[i * 4 + 0] = pixelShaderConstantF[startRegister + i][0];
1714 			constantData[i * 4 + 1] = pixelShaderConstantF[startRegister + i][1];
1715 			constantData[i * 4 + 2] = pixelShaderConstantF[startRegister + i][2];
1716 			constantData[i * 4 + 3] = pixelShaderConstantF[startRegister + i][3];
1717 		}
1718 
1719 		return D3D_OK;
1720 	}
1721 
GetPixelShaderConstantI(unsigned int startRegister,int * constantData,unsigned int count)1722 	long Direct3DDevice9::GetPixelShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count)
1723 	{
1724 		CriticalSection cs(this);
1725 
1726 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1727 
1728 		if(!constantData)
1729 		{
1730 			return INVALIDCALL();
1731 		}
1732 
1733 		for(unsigned int i = 0; i < count; i++)
1734 		{
1735 			constantData[i * 4 + 0] = pixelShaderConstantI[startRegister + i][0];
1736 			constantData[i * 4 + 1] = pixelShaderConstantI[startRegister + i][1];
1737 			constantData[i * 4 + 2] = pixelShaderConstantI[startRegister + i][2];
1738 			constantData[i * 4 + 3] = pixelShaderConstantI[startRegister + i][3];
1739 		}
1740 
1741 		return D3D_OK;
1742 	}
1743 
GetRasterStatus(unsigned int index,D3DRASTER_STATUS * rasterStatus)1744 	long Direct3DDevice9::GetRasterStatus(unsigned int index, D3DRASTER_STATUS *rasterStatus)
1745 	{
1746 		CriticalSection cs(this);
1747 
1748 		TRACE("unsigned int swapChain = %d, D3DRASTER_STATUS *rasterStatus = 0x%0.8p", index, rasterStatus);
1749 
1750 		if(index >= GetNumberOfSwapChains())
1751 		{
1752 			return INVALIDCALL();
1753 		}
1754 
1755 		return swapChain->GetRasterStatus(rasterStatus);
1756 	}
1757 
GetRenderState(D3DRENDERSTATETYPE state,unsigned long * value)1758 	long Direct3DDevice9::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value)
1759 	{
1760 		CriticalSection cs(this);
1761 
1762 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long *value = 0x%0.8p", state, value);
1763 
1764 		if(!value)
1765 		{
1766 			return INVALIDCALL();
1767 		}
1768 
1769 		*value = renderState[state];
1770 
1771 		return D3D_OK;
1772 	}
1773 
GetRenderTarget(unsigned long index,IDirect3DSurface9 ** renderTarget)1774 	long Direct3DDevice9::GetRenderTarget(unsigned long index, IDirect3DSurface9 **renderTarget)
1775 	{
1776 		CriticalSection cs(this);
1777 
1778 		TRACE("unsigned long index = %d, IDirect3DSurface9 **renderTarget = 0x%0.8p", index, renderTarget);
1779 
1780 		if(index >= 4 || !renderTarget)
1781 		{
1782 			return INVALIDCALL();
1783 		}
1784 
1785 		*renderTarget = 0;
1786 
1787 		if(!this->renderTarget[index])
1788 		{
1789 			return NOTFOUND();
1790 		}
1791 
1792 		*renderTarget = this->renderTarget[index];
1793 		this->renderTarget[index]->AddRef();
1794 
1795 		return D3D_OK;
1796 	}
1797 
GetRenderTargetData(IDirect3DSurface9 * renderTarget,IDirect3DSurface9 * destSurface)1798 	long Direct3DDevice9::GetRenderTargetData(IDirect3DSurface9 *renderTarget, IDirect3DSurface9 *destSurface)
1799 	{
1800 		CriticalSection cs(this);
1801 
1802 		TRACE("IDirect3DSurface9 *renderTarget = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p", renderTarget, destSurface);
1803 
1804 		if(!renderTarget || !destSurface)
1805 		{
1806 			return INVALIDCALL();
1807 		}
1808 
1809 		D3DSURFACE_DESC sourceDescription;
1810 		D3DSURFACE_DESC destinationDescription;
1811 
1812 		renderTarget->GetDesc(&sourceDescription);
1813 		destSurface->GetDesc(&destinationDescription);
1814 
1815 		if(sourceDescription.Width  != destinationDescription.Width ||
1816 		   sourceDescription.Height != destinationDescription.Height ||
1817 		   sourceDescription.Format != destinationDescription.Format ||
1818 		   sourceDescription.MultiSampleType != D3DMULTISAMPLE_NONE)
1819 		{
1820 			return INVALIDCALL();
1821 		}
1822 
1823 		if(sourceDescription.Format == D3DFMT_A8R8G8B8 ||
1824 		   sourceDescription.Format == D3DFMT_X8R8G8B8)
1825 		{
1826 			sw::Surface *source = static_cast<Direct3DSurface9*>(renderTarget);
1827 			sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface);
1828 
1829 			void *sourceBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
1830 			void *destBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
1831 
1832 			static void (__cdecl *blitFunction)(void *dst, void *src);
1833 			static sw::Routine *blitRoutine;
1834 			static sw::BlitState blitState = {};
1835 
1836 			sw::BlitState update;
1837 			update.width = sourceDescription.Width;
1838 			update.height = sourceDescription.Height;
1839 			update.sourceFormat = sw::FORMAT_A8R8G8B8;
1840 			update.sourceStride = source->getExternalPitchB();
1841 			update.destFormat = sw::FORMAT_A8R8G8B8;
1842 			update.destStride = dest->getExternalPitchB();
1843 			update.cursorHeight = 0;
1844 			update.cursorWidth = 0;
1845 
1846 			if(memcmp(&blitState, &update, sizeof(sw::BlitState)) != 0)
1847 			{
1848 				blitState = update;
1849 				delete blitRoutine;
1850 
1851 				blitRoutine = sw::FrameBuffer::copyRoutine(blitState);
1852 				blitFunction = (void(__cdecl*)(void*, void*))blitRoutine->getEntry();
1853 			}
1854 
1855 			blitFunction(destBuffer, sourceBuffer);
1856 
1857 			dest->unlockExternal();
1858 			source->unlockExternal();
1859 		}
1860 		else
1861 		{
1862 			return UpdateSurface(renderTarget, 0, destSurface, 0);
1863 		}
1864 
1865 		return D3D_OK;
1866 	}
1867 
GetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long * value)1868 	long Direct3DDevice9::GetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long *value)
1869 	{
1870 		CriticalSection cs(this);
1871 
1872 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE type = %d, unsigned long *value = 0x%0.8p", sampler, state, value);
1873 
1874 		if(!value || state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)   // FIXME: Set *value to 0?
1875 		{
1876 			return INVALIDCALL();
1877 		}
1878 
1879 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1880 		{
1881 			return INVALIDCALL();
1882 		}
1883 
1884 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
1885 		{
1886 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
1887 		}
1888 
1889 		*value = samplerState[sampler][state];
1890 
1891 		return D3D_OK;
1892 	}
1893 
GetScissorRect(RECT * rect)1894 	long Direct3DDevice9::GetScissorRect(RECT *rect)
1895 	{
1896 		CriticalSection cs(this);
1897 
1898 		TRACE("RECT *rect = 0x%0.8p", rect);
1899 
1900 		if(!rect)
1901 		{
1902 			return INVALIDCALL();
1903 		}
1904 
1905 		*rect = scissorRect;
1906 
1907 		return D3D_OK;
1908 	}
1909 
GetSoftwareVertexProcessing()1910 	int Direct3DDevice9::GetSoftwareVertexProcessing()
1911 	{
1912 		CriticalSection cs(this);
1913 
1914 		TRACE("void");
1915 
1916 		return softwareVertexProcessing ? TRUE : FALSE;
1917 	}
1918 
GetStreamSource(unsigned int streamNumber,IDirect3DVertexBuffer9 ** streamData,unsigned int * offset,unsigned int * stride)1919 	long Direct3DDevice9::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer9 **streamData, unsigned int *offset, unsigned int *stride)
1920 	{
1921 		CriticalSection cs(this);
1922 
1923 		TRACE("unsigned int streamNumber = %d, IDirect3DVertexBuffer9 **streamData = 0x%0.8p, unsigned int *offset = 0x%0.8p, unsigned int *stride = 0x%0.8p", streamNumber, streamData, offset, stride);
1924 
1925 		if(streamNumber >= 16 || !streamData || !offset || !stride)
1926 		{
1927 			return INVALIDCALL();
1928 		}
1929 
1930 		*streamData = dataStream[streamNumber];
1931 
1932 		if(dataStream[streamNumber])
1933 		{
1934 			dataStream[streamNumber]->AddRef();
1935 		}
1936 
1937 		*offset = streamOffset[streamNumber];
1938 		*stride = streamStride[streamNumber];
1939 
1940 		return D3D_OK;
1941 	}
1942 
GetStreamSourceFreq(unsigned int streamNumber,unsigned int * divider)1943 	long Direct3DDevice9::GetStreamSourceFreq(unsigned int streamNumber, unsigned int *divider)
1944 	{
1945 		CriticalSection cs(this);
1946 
1947 		TRACE("unsigned int streamNumber = %d, unsigned int *divider = 0x%0.8p", streamNumber, divider);
1948 
1949 		if(streamNumber >= 16 || !divider)
1950 		{
1951 			return INVALIDCALL();
1952 		}
1953 
1954 		*divider = streamSourceFreq[streamNumber];
1955 
1956 		return D3D_OK;
1957 	}
1958 
GetSwapChain(unsigned int index,IDirect3DSwapChain9 ** swapChain)1959 	long Direct3DDevice9::GetSwapChain(unsigned int index, IDirect3DSwapChain9 **swapChain)
1960 	{
1961 		CriticalSection cs(this);
1962 
1963 		TRACE("unsigned int index = %d, IDirect3DSwapChain9 **swapChain = 0x%0.8p", index, swapChain);
1964 
1965 		if(!swapChain || index >= GetNumberOfSwapChains())
1966 		{
1967 			return INVALIDCALL();
1968 		}
1969 
1970 		*swapChain = this->swapChain;
1971 
1972 		if(*swapChain)
1973 		{
1974 			(*swapChain)->AddRef();
1975 		}
1976 
1977 		return D3D_OK;
1978 	}
1979 
GetTexture(unsigned long sampler,IDirect3DBaseTexture9 ** texture)1980 	long Direct3DDevice9::GetTexture(unsigned long sampler, IDirect3DBaseTexture9 **texture)
1981 	{
1982 		CriticalSection cs(this);
1983 
1984 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 **texture = 0x%0.8p", sampler, texture);
1985 
1986 		if(!texture)
1987 		{
1988 			return INVALIDCALL();
1989 		}
1990 
1991 		*texture = 0;
1992 
1993 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1994 		{
1995 			return INVALIDCALL();
1996 		}
1997 
1998 		*texture = this->texture[sampler];
1999 
2000 		if(this->texture[sampler])
2001 		{
2002 			this->texture[sampler]->AddRef();
2003 		}
2004 
2005 		return D3D_OK;
2006 	}
2007 
GetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long * value)2008 	long Direct3DDevice9::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long *value)
2009 	{
2010 		CriticalSection cs(this);
2011 
2012 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long *value = 0x%0.8p", stage, type, value);
2013 
2014 		if(!value)
2015 		{
2016 			return INVALIDCALL();
2017 		}
2018 
2019 		*value = textureStageState[stage][type];
2020 
2021 		return D3D_OK;
2022 	}
2023 
GetTransform(D3DTRANSFORMSTATETYPE state,D3DMATRIX * matrix)2024 	long Direct3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
2025 	{
2026 		CriticalSection cs(this);
2027 
2028 		TRACE("D3DTRANSFORMSTATETYPE state = %d, D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2029 
2030 		if(!matrix || state < 0 || state > 511)
2031 		{
2032 			return INVALIDCALL();
2033 		}
2034 
2035 		*matrix = this->matrix[state];
2036 
2037 		return D3D_OK;
2038 	}
2039 
GetVertexDeclaration(IDirect3DVertexDeclaration9 ** declaration)2040 	long Direct3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9 **declaration)
2041 	{
2042 		CriticalSection cs(this);
2043 
2044 		TRACE("IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", declaration);
2045 
2046 		if(!declaration)
2047 		{
2048 			return INVALIDCALL();
2049 		}
2050 
2051 		*declaration = vertexDeclaration;
2052 
2053 		if(vertexDeclaration)
2054 		{
2055 			vertexDeclaration->AddRef();
2056 		}
2057 
2058 		return D3D_OK;
2059 	}
2060 
GetVertexShader(IDirect3DVertexShader9 ** shader)2061 	long Direct3DDevice9::GetVertexShader(IDirect3DVertexShader9 **shader)
2062 	{
2063 		CriticalSection cs(this);
2064 
2065 		TRACE("IDirect3DVertexShader9 **shader = 0x%0.8p", shader);
2066 
2067 		if(!shader)
2068 		{
2069 			return INVALIDCALL();
2070 		}
2071 
2072 		*shader = vertexShader;
2073 
2074 		if(vertexShader)
2075 		{
2076 			vertexShader->AddRef();
2077 		}
2078 
2079 		return D3D_OK;
2080 	}
2081 
GetVertexShaderConstantB(unsigned int startRegister,int * constantData,unsigned int count)2082 	long Direct3DDevice9::GetVertexShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count)
2083 	{
2084 		CriticalSection cs(this);
2085 
2086 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2087 
2088 		if(!constantData)
2089 		{
2090 			return INVALIDCALL();
2091 		}
2092 
2093 		for(unsigned int i = 0; i < count; i++)
2094 		{
2095 			constantData[i] = vertexShaderConstantB[startRegister + i];
2096 		}
2097 
2098 		return D3D_OK;
2099 	}
2100 
GetVertexShaderConstantF(unsigned int startRegister,float * constantData,unsigned int count)2101 	long Direct3DDevice9::GetVertexShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count)
2102 	{
2103 		CriticalSection cs(this);
2104 
2105 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2106 
2107 		if(!constantData)
2108 		{
2109 			return INVALIDCALL();
2110 		}
2111 
2112 		for(unsigned int i = 0; i < count; i++)
2113 		{
2114 			constantData[i * 4 + 0] = vertexShaderConstantF[startRegister + i][0];
2115 			constantData[i * 4 + 1] = vertexShaderConstantF[startRegister + i][1];
2116 			constantData[i * 4 + 2] = vertexShaderConstantF[startRegister + i][2];
2117 			constantData[i * 4 + 3] = vertexShaderConstantF[startRegister + i][3];
2118 		}
2119 
2120 		return D3D_OK;
2121 	}
2122 
GetVertexShaderConstantI(unsigned int startRegister,int * constantData,unsigned int count)2123 	long Direct3DDevice9::GetVertexShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count)
2124 	{
2125 		CriticalSection cs(this);
2126 
2127 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2128 
2129 		if(!constantData)
2130 		{
2131 			return INVALIDCALL();
2132 		}
2133 
2134 		for(unsigned int i = 0; i < count; i++)
2135 		{
2136 			constantData[i * 4 + 0] = vertexShaderConstantI[startRegister + i][0];
2137 			constantData[i * 4 + 1] = vertexShaderConstantI[startRegister + i][1];
2138 			constantData[i * 4 + 2] = vertexShaderConstantI[startRegister + i][2];
2139 			constantData[i * 4 + 3] = vertexShaderConstantI[startRegister + i][3];
2140 		}
2141 
2142 		return D3D_OK;
2143 	}
2144 
GetViewport(D3DVIEWPORT9 * viewport)2145 	long Direct3DDevice9::GetViewport(D3DVIEWPORT9 *viewport)
2146 	{
2147 		CriticalSection cs(this);
2148 
2149 		TRACE("D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
2150 
2151 		if(!viewport)
2152 		{
2153 			return INVALIDCALL();
2154 		}
2155 
2156 		*viewport = this->viewport;
2157 
2158 		return D3D_OK;
2159 	}
2160 
LightEnable(unsigned long index,int enable)2161 	long Direct3DDevice9::LightEnable(unsigned long index, int enable)
2162 	{
2163 		CriticalSection cs(this);
2164 
2165 		TRACE("unsigned long index = %d, int enable = %d", index, enable);
2166 
2167 		if(!light.exists(index))   // Insert default light
2168 		{
2169 			D3DLIGHT9 light;
2170 
2171 			light.Type = D3DLIGHT_DIRECTIONAL;
2172 			light.Diffuse.r = 1;
2173 			light.Diffuse.g = 1;
2174 			light.Diffuse.b = 1;
2175 			light.Diffuse.a = 0;
2176 			light.Specular.r = 0;
2177 			light.Specular.g = 0;
2178 			light.Specular.b = 0;
2179 			light.Specular.a = 0;
2180 			light.Ambient.r = 0;
2181 			light.Ambient.g = 0;
2182 			light.Ambient.b = 0;
2183 			light.Ambient.a = 0;
2184 			light.Position.x = 0;
2185 			light.Position.y = 0;
2186 			light.Position.z = 0;
2187 			light.Direction.x = 0;
2188 			light.Direction.y = 0;
2189 			light.Direction.z = 1;
2190 			light.Range = 0;
2191 			light.Falloff = 0;
2192 			light.Attenuation0 = 0;
2193 			light.Attenuation1 = 0;
2194 			light.Attenuation2 = 0;
2195 			light.Theta = 0;
2196 			light.Phi = 0;
2197 
2198 			this->light[index] = light;
2199 			this->light[index].enable = false;
2200 		}
2201 
2202 		if(!stateRecorder)
2203 		{
2204 			light[index].enable = (enable != FALSE);
2205 
2206 			lightsDirty = true;
2207 		}
2208 		else
2209 		{
2210 			stateRecorder->lightEnable(index, enable);
2211 		}
2212 
2213 		return D3D_OK;
2214 	}
2215 
MultiplyTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)2216 	long Direct3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
2217 	{
2218 		CriticalSection cs(this);
2219 
2220 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2221 
2222 		if(!matrix)
2223 		{
2224 			return INVALIDCALL();
2225 		}
2226 
2227 		D3DMATRIX *current = &this->matrix[state];
2228 
2229 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41,
2230 		             current->_12, current->_22, current->_32, current->_42,
2231 		             current->_13, current->_23, current->_33, current->_43,
2232 		             current->_14, current->_24, current->_34, current->_44);
2233 
2234 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
2235 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
2236 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
2237 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
2238 
2239 		switch(state)
2240 		{
2241 		case D3DTS_WORLD:
2242 			renderer->setModelMatrix(C * M);
2243 			break;
2244 		case D3DTS_VIEW:
2245 			renderer->setViewMatrix(C * M);
2246 			break;
2247 		case D3DTS_PROJECTION:
2248 			renderer->setProjectionMatrix(C * M);
2249 			break;
2250 		case D3DTS_TEXTURE0:
2251 			renderer->setTextureMatrix(0, C * M);
2252 			break;
2253 		case D3DTS_TEXTURE1:
2254 			renderer->setTextureMatrix(1, C * M);
2255 			break;
2256 		case D3DTS_TEXTURE2:
2257 			renderer->setTextureMatrix(2, C * M);
2258 			break;
2259 		case D3DTS_TEXTURE3:
2260 			renderer->setTextureMatrix(3, C * M);
2261 			break;
2262 		case D3DTS_TEXTURE4:
2263 			renderer->setTextureMatrix(4, C * M);
2264 			break;
2265 		case D3DTS_TEXTURE5:
2266 			renderer->setTextureMatrix(5, C * M);
2267 			break;
2268 		case D3DTS_TEXTURE6:
2269 			renderer->setTextureMatrix(6, C * M);
2270 			break;
2271 		case D3DTS_TEXTURE7:
2272 			renderer->setTextureMatrix(7, C * M);
2273 			break;
2274 		default:
2275 			if(state > 256 && state < 512)
2276 			{
2277 				renderer->setModelMatrix(C * M, state - 256);
2278 			}
2279 			else ASSERT(false);
2280 		}
2281 
2282 		return D3D_OK;
2283 	}
2284 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion)2285 	long Direct3DDevice9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
2286 	{
2287 		CriticalSection cs(this);
2288 
2289 		TRACE("const RECT *sourceRect = 0x%0.8p, const RECT *destRect = 0x%0.8p, HWND destWindowOverride = %d, const RGNDATA *dirtyRegion = 0x%0.8p", sourceRect, destRect, destWindowOverride, dirtyRegion);
2290 
2291 		return swapChain->Present(sourceRect, destRect, destWindowOverride, dirtyRegion, 0);
2292 	}
2293 
ProcessVertices(unsigned int srcStartIndex,unsigned int destIndex,unsigned int vertexCount,IDirect3DVertexBuffer9 * destBuffer,IDirect3DVertexDeclaration9 * vertexDeclaration,unsigned long flags)2294 	long Direct3DDevice9::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer9 *destBuffer, IDirect3DVertexDeclaration9 *vertexDeclaration, unsigned long flags)
2295 	{
2296 		CriticalSection cs(this);
2297 
2298 		TRACE("unsigned int srcStartIndex = %d, unsigned int destIndex = %d, unsigned int vertexCount = %d, IDirect3DVertexBuffer9 *destBuffer = 0x%0.8p, IDirect3DVertexDeclaration9 *vertexDeclaration = 0x%0.8p, unsigned long flags = %d", srcStartIndex, destIndex, vertexCount, destBuffer, vertexDeclaration, flags);
2299 
2300 		if(!destBuffer)
2301 		{
2302 			return INVALIDCALL();
2303 		}
2304 
2305 		UNIMPLEMENTED();
2306 
2307 		return D3D_OK;
2308 	}
2309 
Reset(D3DPRESENT_PARAMETERS * presentParameters)2310 	long Direct3DDevice9::Reset(D3DPRESENT_PARAMETERS *presentParameters)
2311 	{
2312 		CriticalSection cs(this);
2313 
2314 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p", presentParameters);
2315 
2316 		if(!presentParameters)
2317 		{
2318 			return INVALIDCALL();
2319 		}
2320 
2321 		deviceWindow = presentParameters->hDeviceWindow;
2322 
2323 		if(depthStencil)
2324 		{
2325 			depthStencil->unbind();
2326 			depthStencil = 0;
2327 		}
2328 
2329 		if(autoDepthStencil)
2330 		{
2331 			autoDepthStencil->unbind();
2332 			autoDepthStencil = 0;
2333 		}
2334 
2335 		for(int index = 0; index < 4; index++)
2336 		{
2337 			if(renderTarget[index])
2338 			{
2339 				renderTarget[index]->unbind();
2340 				renderTarget[index] = 0;
2341 			}
2342 		}
2343 
2344 		if(!swapChain)
2345 		{
2346 			swapChain = new Direct3DSwapChain9(this, presentParameters);
2347 			swapChain->bind();
2348 		}
2349 		else
2350 		{
2351 			swapChain->reset(presentParameters);
2352 		}
2353 
2354 		if(presentParameters->EnableAutoDepthStencil != FALSE)
2355 		{
2356 			bool lockable = false;
2357 
2358 			switch(presentParameters->AutoDepthStencilFormat)
2359 			{
2360 			case D3DFMT_D15S1:
2361 			case D3DFMT_D24S8:
2362 			case D3DFMT_D24X8:
2363 			case D3DFMT_D24X4S4:
2364 			case D3DFMT_D24FS8:
2365 			case D3DFMT_D32:
2366 			case D3DFMT_D16:
2367 			case D3DFMT_DF24:
2368 			case D3DFMT_DF16:
2369 			case D3DFMT_INTZ:
2370 				lockable = false;
2371 				break;
2372 			case D3DFMT_S8_LOCKABLE:
2373 			case D3DFMT_D16_LOCKABLE:
2374 			case D3DFMT_D32F_LOCKABLE:
2375 			case D3DFMT_D32_LOCKABLE:
2376 				lockable = true;
2377 				break;
2378 			default:
2379 				ASSERT(false);
2380 			}
2381 
2382 			autoDepthStencil = new Direct3DSurface9(this, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL);
2383 			autoDepthStencil->bind();
2384 
2385 			SetDepthStencilSurface(autoDepthStencil);
2386 		}
2387 
2388 		IDirect3DSurface9 *renderTarget;
2389 		swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget);
2390 		SetRenderTarget(0, renderTarget);
2391 		renderTarget->Release();
2392 
2393 		SetRenderTarget(1, 0);
2394 		SetRenderTarget(2, 0);
2395 		SetRenderTarget(3, 0);
2396 
2397 		softwareVertexProcessing = (behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == D3DCREATE_SOFTWARE_VERTEXPROCESSING;
2398 
2399 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE);
2400 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2401 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
2402 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2403 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2404 		SetRenderState(D3DRS_LASTPIXEL, TRUE);
2405 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
2406 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
2407 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
2408 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2409 		SetRenderState(D3DRS_ALPHAREF, 0);
2410 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
2411 		SetRenderState(D3DRS_DITHERENABLE, FALSE);
2412 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2413 		SetRenderState(D3DRS_FOGENABLE, FALSE);
2414 		SetRenderState(D3DRS_SPECULARENABLE, FALSE);
2415 	//	SetRenderState(D3DRS_ZVISIBLE, 0);
2416 		SetRenderState(D3DRS_FOGCOLOR, 0);
2417 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
2418 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f));
2419 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f));
2420 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f));
2421 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
2422 		SetRenderState(D3DRS_STENCILENABLE, FALSE);
2423 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
2424 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
2425 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
2426 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2427 		SetRenderState(D3DRS_STENCILREF, 0);
2428 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
2429 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
2430 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
2431 		SetRenderState(D3DRS_WRAP0, 0);
2432 		SetRenderState(D3DRS_WRAP1, 0);
2433 		SetRenderState(D3DRS_WRAP2, 0);
2434 		SetRenderState(D3DRS_WRAP3, 0);
2435 		SetRenderState(D3DRS_WRAP4, 0);
2436 		SetRenderState(D3DRS_WRAP5, 0);
2437 		SetRenderState(D3DRS_WRAP6, 0);
2438 		SetRenderState(D3DRS_WRAP7, 0);
2439 		SetRenderState(D3DRS_CLIPPING, TRUE);
2440 		SetRenderState(D3DRS_LIGHTING, TRUE);
2441 		SetRenderState(D3DRS_AMBIENT, 0);
2442 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
2443 		SetRenderState(D3DRS_COLORVERTEX, TRUE);
2444 		SetRenderState(D3DRS_LOCALVIEWER, TRUE);
2445 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
2446 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
2447 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
2448 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
2449 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
2450 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
2451 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2452 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f));
2453 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
2454 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
2455 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
2456 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f));
2457 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
2458 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
2459 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
2460 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
2461 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
2462 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
2463 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f));
2464 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
2465 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F);
2466 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f));
2467 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
2468 		SetRenderState(D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC);
2469 		SetRenderState(D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR);
2470 		SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
2471 		SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FtoDW(0.0f));
2472 		SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
2473 		SetRenderState(D3DRS_MINTESSELLATIONLEVEL, FtoDW(1.0f));
2474 		SetRenderState(D3DRS_MAXTESSELLATIONLEVEL, FtoDW(1.0f));
2475 		SetRenderState(D3DRS_ADAPTIVETESS_X, FtoDW(0.0f));
2476 		SetRenderState(D3DRS_ADAPTIVETESS_Y, FtoDW(0.0f));
2477 		SetRenderState(D3DRS_ADAPTIVETESS_Z, FtoDW(1.0f));
2478 		SetRenderState(D3DRS_ADAPTIVETESS_W, FtoDW(0.0f));
2479 		SetRenderState(D3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
2480 		SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2481 		SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
2482 		SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
2483 		SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
2484 		SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
2485 		SetRenderState(D3DRS_COLORWRITEENABLE1, 0x0000000F);
2486 		SetRenderState(D3DRS_COLORWRITEENABLE2, 0x0000000F);
2487 		SetRenderState(D3DRS_COLORWRITEENABLE3, 0x0000000F);
2488 		SetRenderState(D3DRS_BLENDFACTOR, 0xFFFFFFFF);
2489 		SetRenderState(D3DRS_SRGBWRITEENABLE, 0);
2490 		SetRenderState(D3DRS_DEPTHBIAS, FtoDW(0.0f));
2491 		SetRenderState(D3DRS_WRAP8, 0);
2492 		SetRenderState(D3DRS_WRAP9, 0);
2493 		SetRenderState(D3DRS_WRAP10, 0);
2494 		SetRenderState(D3DRS_WRAP11, 0);
2495 		SetRenderState(D3DRS_WRAP12, 0);
2496 		SetRenderState(D3DRS_WRAP13, 0);
2497 		SetRenderState(D3DRS_WRAP14, 0);
2498 		SetRenderState(D3DRS_WRAP15, 0);
2499 		SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
2500 		SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
2501 		SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
2502 		SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
2503 
2504 		for(int i = 0; i < 8; i++)
2505 		{
2506 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE);
2507 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2508 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
2509 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE);
2510 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
2511 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
2512 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f));
2513 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f));
2514 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f));
2515 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f));
2516 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
2517 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f));
2518 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f));
2519 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2520 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
2521 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
2522 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
2523 			SetTextureStageState(i, D3DTSS_CONSTANT, 0x00000000);
2524 		}
2525 
2526 		for(int i = 0; i <= D3DVERTEXTEXTURESAMPLER3; i = (i != 15) ? (i + 1) : D3DVERTEXTEXTURESAMPLER0)
2527 		{
2528 			SetTexture(i, 0);
2529 
2530 			SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
2531 			SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
2532 			SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
2533 			SetSamplerState(i, D3DSAMP_BORDERCOLOR, 0x00000000);
2534 			SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2535 			SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2536 			SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2537 			SetSamplerState(i, D3DSAMP_MIPMAPLODBIAS, 0);
2538 			SetSamplerState(i, D3DSAMP_MAXMIPLEVEL, 0);
2539 			SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 1);
2540 			SetSamplerState(i, D3DSAMP_SRGBTEXTURE, 0);
2541 			SetSamplerState(i, D3DSAMP_ELEMENTINDEX, 0);
2542 			SetSamplerState(i, D3DSAMP_DMAPOFFSET, 0);
2543 		}
2544 
2545 		for(int i = 0; i < 6; i++)
2546 		{
2547 			float plane[4] = {0, 0, 0, 0};
2548 
2549 			SetClipPlane(i, plane);
2550 		}
2551 
2552 		currentPalette = 0xFFFF;
2553 
2554 		ShowCursor(FALSE);
2555 		delete cursor;
2556 		cursor = 0;
2557 
2558 		return D3D_OK;
2559 	}
2560 
SetClipPlane(unsigned long index,const float * plane)2561 	long Direct3DDevice9::SetClipPlane(unsigned long index, const float *plane)
2562 	{
2563 		CriticalSection cs(this);
2564 
2565 		TRACE("unsigned long index = %d, const float *plane = 0x%0.8p", index, plane);
2566 
2567 		if(!plane || index >= 6)
2568 		{
2569 			return INVALIDCALL();
2570 		}
2571 
2572 		if(!stateRecorder)
2573 		{
2574 			this->plane[index][0] = plane[0];
2575 			this->plane[index][1] = plane[1];
2576 			this->plane[index][2] = plane[2];
2577 			this->plane[index][3] = plane[3];
2578 
2579 			renderer->setClipPlane(index, plane);
2580 		}
2581 		else
2582 		{
2583 			stateRecorder->setClipPlane(index, plane);
2584 		}
2585 
2586 		return D3D_OK;
2587 	}
2588 
SetClipStatus(const D3DCLIPSTATUS9 * clipStatus)2589 	long Direct3DDevice9::SetClipStatus(const D3DCLIPSTATUS9 *clipStatus)
2590 	{
2591 		CriticalSection cs(this);
2592 
2593 		TRACE("const D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus);
2594 
2595 		if(!clipStatus)
2596 		{
2597 			return INVALIDCALL();
2598 		}
2599 
2600 		this->clipStatus = *clipStatus;
2601 
2602 		UNIMPLEMENTED();
2603 
2604 		return D3D_OK;
2605 	}
2606 
SetCurrentTexturePalette(unsigned int paletteNumber)2607 	long Direct3DDevice9::SetCurrentTexturePalette(unsigned int paletteNumber)
2608 	{
2609 		CriticalSection cs(this);
2610 
2611 		TRACE("unsigned int paletteNumber = %d", paletteNumber);
2612 
2613 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end())
2614 		{
2615 			return INVALIDCALL();
2616 		}
2617 
2618 		if(!stateRecorder)
2619 		{
2620 			currentPalette = paletteNumber;
2621 
2622 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2623 		}
2624 		else
2625 		{
2626 			stateRecorder->setCurrentTexturePalette(paletteNumber);
2627 		}
2628 
2629 		return D3D_OK;
2630 	}
2631 
SetCursorPosition(int x,int y,unsigned long flags)2632 	void Direct3DDevice9::SetCursorPosition(int x, int y, unsigned long flags)
2633 	{
2634 		CriticalSection cs(this);
2635 
2636 		TRACE("int x = %d, int y = %d, unsigned long flags = 0x%0.8X", x, y, flags);
2637 
2638 		POINT point = {x, y};
2639 		HWND window = deviceWindow ? deviceWindow : focusWindow;
2640 		ScreenToClient(window, &point);
2641 
2642 		sw::FrameBuffer::setCursorPosition(point.x, point.y);
2643 	}
2644 
SetCursorProperties(unsigned int x0,unsigned int y0,IDirect3DSurface9 * cursorBitmap)2645 	long Direct3DDevice9::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface9 *cursorBitmap)
2646 	{
2647 		CriticalSection cs(this);
2648 
2649 		TRACE("unsigned int x0 = %d, unsigned int y0 = %d, IDirect3DSurface9 *cursorBitmap = 0x%0.8p", x0, y0, cursorBitmap);
2650 
2651 		if(!cursorBitmap)
2652 		{
2653 			return INVALIDCALL();
2654 		}
2655 
2656 		sw::Surface *cursorSurface = static_cast<Direct3DSurface9*>(cursorBitmap);
2657 
2658 		int width = cursorSurface->getWidth();
2659 		int height = cursorSurface->getHeight();
2660 		void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
2661 
2662 		delete cursor;
2663 		cursor = sw::Surface::create(nullptr, width, height, 1, 0, 1, sw::FORMAT_A8R8G8B8, false, false);
2664 
2665 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
2666 		memcpy(buffer, bitmap, width * height * sizeof(unsigned int));
2667 		cursor->unlockExternal();
2668 
2669 		cursorSurface->unlockExternal();
2670 
2671 		if(showCursor)
2672 		{
2673 			sw::FrameBuffer::setCursorImage(cursor);
2674 		}
2675 		else
2676 		{
2677 			sw::FrameBuffer::setCursorImage(nullptr);
2678 		}
2679 
2680 		sw::FrameBuffer::setCursorOrigin(x0, y0);
2681 
2682 		return D3D_OK;
2683 	}
2684 
SetDepthStencilSurface(IDirect3DSurface9 * iDepthStencil)2685 	long Direct3DDevice9::SetDepthStencilSurface(IDirect3DSurface9 *iDepthStencil)
2686 	{
2687 		CriticalSection cs(this);
2688 
2689 		TRACE("IDirect3DSurface9 *newDepthStencil = 0x%0.8p", iDepthStencil);
2690 
2691 		Direct3DSurface9 *depthStencil = static_cast<Direct3DSurface9*>(iDepthStencil);
2692 
2693 		if(this->depthStencil == depthStencil)
2694 		{
2695 			return D3D_OK;
2696 		}
2697 
2698 		if(depthStencil)
2699 		{
2700 			depthStencil->bind();
2701 		}
2702 
2703 		if(this->depthStencil)
2704 		{
2705 			this->depthStencil->unbind();
2706 		}
2707 
2708 		this->depthStencil = depthStencil;
2709 
2710 		renderer->setDepthBuffer(depthStencil);
2711 		renderer->setStencilBuffer(depthStencil);
2712 
2713 		return D3D_OK;
2714 	}
2715 
SetDialogBoxMode(int enableDialogs)2716 	long Direct3DDevice9::SetDialogBoxMode(int enableDialogs)
2717 	{
2718 		CriticalSection cs(this);
2719 
2720 		TRACE("int enableDialogs = %d", enableDialogs);
2721 
2722 		UNIMPLEMENTED();
2723 
2724 		return D3D_OK;
2725 	}
2726 
SetFVF(unsigned long FVF)2727 	long Direct3DDevice9::SetFVF(unsigned long FVF)
2728 	{
2729 		CriticalSection cs(this);
2730 
2731 		TRACE("unsigned long FVF = 0x%0.8X", FVF);
2732 
2733 		if(!stateRecorder)
2734 		{
2735 			if(FVF != 0 || !this->vertexDeclaration)
2736 			{
2737 				Direct3DVertexDeclaration9 *vertexDeclaration = new Direct3DVertexDeclaration9(this, FVF);
2738 				vertexDeclaration->bind();
2739 
2740 				if(this->vertexDeclaration)
2741 				{
2742 					this->vertexDeclaration->unbind();
2743 				}
2744 
2745 				this->vertexDeclaration = vertexDeclaration;
2746 			}
2747 		}
2748 		else
2749 		{
2750 			stateRecorder->setFVF(FVF);
2751 		}
2752 
2753 		return D3D_OK;
2754 	}
2755 
SetGammaRamp(unsigned int index,unsigned long flags,const D3DGAMMARAMP * ramp)2756 	void Direct3DDevice9::SetGammaRamp(unsigned int index, unsigned long flags, const D3DGAMMARAMP *ramp)
2757 	{
2758 		CriticalSection cs(this);
2759 
2760 		TRACE("unsigned int index = %d, unsigned long flags = 0x%0.8X, const D3DGAMMARAMP *ramp = 0x%0.8p", index, flags, ramp);
2761 
2762 		if(!ramp || index >= GetNumberOfSwapChains())
2763 		{
2764 			return;
2765 		}
2766 
2767 		swapChain->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE);
2768 	}
2769 
SetIndices(IDirect3DIndexBuffer9 * iIndexBuffer)2770 	long Direct3DDevice9::SetIndices(IDirect3DIndexBuffer9* iIndexBuffer)
2771 	{
2772 		CriticalSection cs(this);
2773 
2774 		TRACE("IDirect3DIndexBuffer9* indexData = 0x%0.8p", iIndexBuffer);
2775 
2776 		Direct3DIndexBuffer9 *indexBuffer = static_cast<Direct3DIndexBuffer9*>(iIndexBuffer);
2777 
2778 		if(!stateRecorder)
2779 		{
2780 			if(this->indexData == indexBuffer)
2781 			{
2782 				return D3D_OK;
2783 			}
2784 
2785 			if(indexBuffer)
2786 			{
2787 				indexBuffer->bind();
2788 			}
2789 
2790 			if(this->indexData)
2791 			{
2792 				this->indexData->unbind();
2793 			}
2794 
2795 			this->indexData = indexBuffer;
2796 		}
2797 		else
2798 		{
2799 			stateRecorder->setIndices(indexBuffer);
2800 		}
2801 
2802 		return D3D_OK;
2803 	}
2804 
SetLight(unsigned long index,const D3DLIGHT9 * light)2805 	long Direct3DDevice9::SetLight(unsigned long index, const D3DLIGHT9 *light)
2806 	{
2807 		CriticalSection cs(this);
2808 
2809 		TRACE("unsigned long index = %d, const D3DLIGHT9 *light = 0x%0.8p", index, light);
2810 
2811 		if(!light)
2812 		{
2813 			return INVALIDCALL();
2814 		}
2815 
2816 		if(!stateRecorder)
2817 		{
2818 			this->light[index] = *light;
2819 
2820 			lightsDirty = true;
2821 		}
2822 		else
2823 		{
2824 			stateRecorder->setLight(index, light);
2825 		}
2826 
2827 		return D3D_OK;
2828 	}
2829 
SetMaterial(const D3DMATERIAL9 * material)2830 	long Direct3DDevice9::SetMaterial(const D3DMATERIAL9 *material)
2831 	{
2832 		CriticalSection cs(this);
2833 
2834 		TRACE("const D3DMATERIAL9 *material = 0x%0.8p", material);
2835 
2836 		if(!material)
2837 		{
2838 			return INVALIDCALL();   // FIXME: Correct behaviour?
2839 		}
2840 
2841 		if(!stateRecorder)
2842 		{
2843 			this->material = *material;
2844 
2845 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a));
2846 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a));
2847 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a));
2848 			renderer->setMaterialShininess(material->Power);
2849 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a));
2850 		}
2851 		else
2852 		{
2853 			stateRecorder->setMaterial(material);
2854 		}
2855 
2856 		return D3D_OK;
2857 	}
2858 
SetNPatchMode(float segments)2859 	long Direct3DDevice9::SetNPatchMode(float segments)
2860 	{
2861 		CriticalSection cs(this);
2862 
2863 		TRACE("float segments = %f", segments);
2864 
2865 		if(!stateRecorder)
2866 		{
2867 			if(segments < 1)
2868 			{
2869 				// NOTE: Disable
2870 			}
2871 			else
2872 			{
2873 				UNIMPLEMENTED();
2874 			}
2875 		}
2876 		else
2877 		{
2878 			stateRecorder->setNPatchMode(segments);
2879 		}
2880 
2881 		return D3D_OK;
2882 	}
2883 
SetPaletteEntries(unsigned int paletteNumber,const PALETTEENTRY * entries)2884 	long Direct3DDevice9::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries)
2885 	{
2886 		CriticalSection cs(this);
2887 
2888 		TRACE("unsigned int paletteNumber = %d, const PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries);
2889 
2890 		if(paletteNumber > 0xFFFF || !entries)
2891 		{
2892 			return INVALIDCALL();
2893 		}
2894 
2895 		for(int i = 0; i < 256; i++)
2896 		{
2897 			palette[paletteNumber].entry[i] = entries[i];
2898 		}
2899 
2900 		if(paletteNumber == currentPalette)
2901 		{
2902 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2903 		}
2904 
2905 		return D3D_OK;
2906 	}
2907 
SetPixelShader(IDirect3DPixelShader9 * iPixelShader)2908 	long Direct3DDevice9::SetPixelShader(IDirect3DPixelShader9 *iPixelShader)
2909 	{
2910 		CriticalSection cs(this);
2911 
2912 		TRACE("IDirect3DPixelShader9 *shader = 0x%0.8p", iPixelShader);
2913 
2914 		Direct3DPixelShader9 *pixelShader = static_cast<Direct3DPixelShader9*>(iPixelShader);
2915 
2916 		if(!stateRecorder)
2917 		{
2918 			if(this->pixelShader == pixelShader)
2919 			{
2920 				return D3D_OK;
2921 			}
2922 
2923 			if(pixelShader)
2924 			{
2925 				pixelShader->bind();
2926 			}
2927 
2928 			if(this->pixelShader)
2929 			{
2930 				this->pixelShader->unbind();
2931 			}
2932 
2933 			this->pixelShader = pixelShader;
2934 			pixelShaderDirty = true;
2935 		}
2936 		else
2937 		{
2938 			stateRecorder->setPixelShader(pixelShader);
2939 		}
2940 
2941 		return D3D_OK;
2942 	}
2943 
SetPixelShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)2944 	long Direct3DDevice9::SetPixelShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
2945 	{
2946 		CriticalSection cs(this);
2947 
2948 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2949 
2950 		if(!stateRecorder)
2951 		{
2952 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
2953 			{
2954 				pixelShaderConstantB[startRegister + i] = constantData[i];
2955 			}
2956 
2957 			pixelShaderConstantsBDirty = sw::max(startRegister + count, pixelShaderConstantsBDirty);
2958 			pixelShaderDirty = true;   // Reload DEF constants
2959 		}
2960 		else
2961 		{
2962 			stateRecorder->setPixelShaderConstantB(startRegister, constantData, count);
2963 		}
2964 
2965 		return D3D_OK;
2966 	}
2967 
SetPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)2968 	long Direct3DDevice9::SetPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
2969 	{
2970 		CriticalSection cs(this);
2971 
2972 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2973 
2974 		if(!stateRecorder)
2975 		{
2976 			for(unsigned int i = 0; i < count && startRegister + i < MAX_PIXEL_SHADER_CONST; i++)
2977 			{
2978 				pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
2979 				pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
2980 				pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
2981 				pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
2982 			}
2983 
2984 			pixelShaderConstantsFDirty = sw::max(startRegister + count, pixelShaderConstantsFDirty);
2985 			pixelShaderDirty = true;   // Reload DEF constants
2986 		}
2987 		else
2988 		{
2989 			stateRecorder->setPixelShaderConstantF(startRegister, constantData, count);
2990 		}
2991 
2992 		return D3D_OK;
2993 	}
2994 
SetPixelShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)2995 	long Direct3DDevice9::SetPixelShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
2996 	{
2997 		CriticalSection cs(this);
2998 
2999 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
3000 
3001 		if(!stateRecorder)
3002 		{
3003 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
3004 			{
3005 				pixelShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
3006 				pixelShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
3007 				pixelShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
3008 				pixelShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
3009 			}
3010 
3011 			pixelShaderConstantsIDirty = sw::max(startRegister + count, pixelShaderConstantsIDirty);
3012 			pixelShaderDirty = true;   // Reload DEF constants
3013 		}
3014 		else
3015 		{
3016 			stateRecorder->setPixelShaderConstantI(startRegister, constantData, count);
3017 		}
3018 
3019 		return D3D_OK;
3020 	}
3021 
SetRenderState(D3DRENDERSTATETYPE state,unsigned long value)3022 	long Direct3DDevice9::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value)
3023 	{
3024 		CriticalSection cs(this);
3025 
3026 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value);
3027 
3028 		if(state < D3DRS_ZENABLE || state > D3DRS_BLENDOPALPHA)
3029 		{
3030 			return D3D_OK;   // FIXME: Warning
3031 		}
3032 
3033 		if(!stateRecorder)
3034 		{
3035 			if(!init && renderState[state] == value)
3036 			{
3037 				return D3D_OK;
3038 			}
3039 
3040 			renderState[state] = value;
3041 
3042 			switch(state)
3043 			{
3044 			case D3DRS_ZENABLE:
3045 				switch(value)
3046 				{
3047 				case D3DZB_TRUE:
3048 				case D3DZB_USEW:
3049 					renderer->setDepthBufferEnable(true);
3050 					break;
3051 				case D3DZB_FALSE:
3052 					renderer->setDepthBufferEnable(false);
3053 					break;
3054 				default:
3055 					ASSERT(false);
3056 				}
3057 				break;
3058 			case D3DRS_FILLMODE:
3059 				switch(value)
3060 				{
3061 				case D3DFILL_POINT:
3062 					renderer->setFillMode(sw::FILL_VERTEX);
3063 					break;
3064 				case D3DFILL_WIREFRAME:
3065 					renderer->setFillMode(sw::FILL_WIREFRAME);
3066 					break;
3067 				case D3DFILL_SOLID:
3068 					renderer->setFillMode(sw::FILL_SOLID);
3069 					break;
3070 				default:
3071 					ASSERT(false);
3072 				}
3073 				break;
3074 			case D3DRS_SHADEMODE:
3075 				switch(value)
3076 				{
3077 				case D3DSHADE_FLAT:
3078 					renderer->setShadingMode(sw::SHADING_FLAT);
3079 					break;
3080 				case D3DSHADE_GOURAUD:
3081 					renderer->setShadingMode(sw::SHADING_GOURAUD);
3082 					break;
3083 				case D3DSHADE_PHONG:
3084 					break;
3085 				default:
3086 					ASSERT(false);
3087 				}
3088 				break;
3089 			case D3DRS_ZWRITEENABLE:
3090 				renderer->setDepthWriteEnable(value != FALSE);
3091 				break;
3092 			case D3DRS_ALPHATESTENABLE:
3093 				renderer->setAlphaTestEnable(value != FALSE);
3094 				break;
3095 			case D3DRS_LASTPIXEL:
3096 			//	if(!init) UNIMPLEMENTED();   // FIXME
3097 				break;
3098 			case D3DRS_SRCBLEND:
3099 				switch(value)
3100 				{
3101 				case D3DBLEND_ZERO:
3102 					renderer->setSourceBlendFactor(sw::BLEND_ZERO);
3103 					break;
3104 				case D3DBLEND_ONE:
3105 					renderer->setSourceBlendFactor(sw::BLEND_ONE);
3106 					break;
3107 				case D3DBLEND_SRCCOLOR:
3108 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE);
3109 					break;
3110 				case D3DBLEND_INVSRCCOLOR:
3111 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE);
3112 					break;
3113 				case D3DBLEND_SRCALPHA:
3114 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3115 					break;
3116 				case D3DBLEND_INVSRCALPHA:
3117 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3118 					break;
3119 				case D3DBLEND_DESTALPHA:
3120 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA);
3121 					break;
3122 				case D3DBLEND_INVDESTALPHA:
3123 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA);
3124 					break;
3125 				case D3DBLEND_DESTCOLOR:
3126 					renderer->setSourceBlendFactor(sw::BLEND_DEST);
3127 					break;
3128 				case D3DBLEND_INVDESTCOLOR:
3129 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST);
3130 					break;
3131 				case D3DBLEND_SRCALPHASAT:
3132 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT);
3133 					break;
3134 				case D3DBLEND_BOTHSRCALPHA:
3135 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3136 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3137 					break;
3138 				case D3DBLEND_BOTHINVSRCALPHA:
3139 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3140 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3141 					break;
3142 				case D3DBLEND_BLENDFACTOR:
3143 					renderer->setSourceBlendFactor(sw::BLEND_CONSTANT);
3144 					break;
3145 				case D3DBLEND_INVBLENDFACTOR:
3146 					renderer->setSourceBlendFactor(sw::BLEND_INVCONSTANT);
3147 					break;
3148 				default:
3149 					ASSERT(false);
3150 				}
3151 				break;
3152 			case D3DRS_DESTBLEND:
3153 				switch(value)
3154 				{
3155 				case D3DBLEND_ZERO:
3156 					renderer->setDestBlendFactor(sw::BLEND_ZERO);
3157 					break;
3158 				case D3DBLEND_ONE:
3159 					renderer->setDestBlendFactor(sw::BLEND_ONE);
3160 					break;
3161 				case D3DBLEND_SRCCOLOR:
3162 					renderer->setDestBlendFactor(sw::BLEND_SOURCE);
3163 					break;
3164 				case D3DBLEND_INVSRCCOLOR:
3165 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE);
3166 					break;
3167 				case D3DBLEND_SRCALPHA:
3168 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3169 					break;
3170 				case D3DBLEND_INVSRCALPHA:
3171 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3172 					break;
3173 				case D3DBLEND_DESTALPHA:
3174 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA);
3175 					break;
3176 				case D3DBLEND_INVDESTALPHA:
3177 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA);
3178 					break;
3179 				case D3DBLEND_DESTCOLOR:
3180 					renderer->setDestBlendFactor(sw::BLEND_DEST);
3181 					break;
3182 				case D3DBLEND_INVDESTCOLOR:
3183 					renderer->setDestBlendFactor(sw::BLEND_INVDEST);
3184 					break;
3185 				case D3DBLEND_SRCALPHASAT:
3186 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT);
3187 					break;
3188 				case D3DBLEND_BOTHSRCALPHA:
3189 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3190 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3191 					break;
3192 				case D3DBLEND_BOTHINVSRCALPHA:
3193 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3194 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3195 					break;
3196 				case D3DBLEND_BLENDFACTOR:
3197 					renderer->setDestBlendFactor(sw::BLEND_CONSTANT);
3198 					break;
3199 				case D3DBLEND_INVBLENDFACTOR:
3200 					renderer->setDestBlendFactor(sw::BLEND_INVCONSTANT);
3201 					break;
3202 				default:
3203 					ASSERT(false);
3204 				}
3205 				break;
3206 			case D3DRS_CULLMODE:
3207 				switch(value)
3208 				{
3209 				case D3DCULL_NONE:
3210 					renderer->setCullMode(sw::CULL_NONE, true);
3211 					break;
3212 				case D3DCULL_CCW:
3213 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE, true);
3214 					break;
3215 				case D3DCULL_CW:
3216 					renderer->setCullMode(sw::CULL_CLOCKWISE, true);
3217 					break;
3218 				default:
3219 					ASSERT(false);
3220 				}
3221 				break;
3222 			case D3DRS_ZFUNC:
3223 				switch(value)
3224 				{
3225 				case D3DCMP_NEVER:
3226 					renderer->setDepthCompare(sw::DEPTH_NEVER);
3227 					break;
3228 				case D3DCMP_LESS:
3229 					renderer->setDepthCompare(sw::DEPTH_LESS);
3230 					break;
3231 				case D3DCMP_EQUAL:
3232 					renderer->setDepthCompare(sw::DEPTH_EQUAL);
3233 					break;
3234 				case D3DCMP_LESSEQUAL:
3235 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL);
3236 					break;
3237 				case D3DCMP_GREATER:
3238 					renderer->setDepthCompare(sw::DEPTH_GREATER);
3239 					break;
3240 				case D3DCMP_NOTEQUAL:
3241 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL);
3242 					break;
3243 				case D3DCMP_GREATEREQUAL:
3244 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL);
3245 					break;
3246 				case D3DCMP_ALWAYS:
3247 					renderer->setDepthCompare(sw::DEPTH_ALWAYS);
3248 					break;
3249 				default:
3250 					ASSERT(false);
3251 				}
3252 				break;
3253 			case D3DRS_ALPHAREF:
3254 				renderer->setAlphaReference(value & 0x000000FF);
3255 				break;
3256 			case D3DRS_ALPHAFUNC:
3257 				switch(value)
3258 				{
3259 				case D3DCMP_NEVER:
3260 					renderer->setAlphaCompare(sw::ALPHA_NEVER);
3261 					break;
3262 				case D3DCMP_LESS:
3263 					renderer->setAlphaCompare(sw::ALPHA_LESS);
3264 					break;
3265 				case D3DCMP_EQUAL:
3266 					renderer->setAlphaCompare(sw::ALPHA_EQUAL);
3267 					break;
3268 				case D3DCMP_LESSEQUAL:
3269 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL);
3270 					break;
3271 				case D3DCMP_GREATER:
3272 					renderer->setAlphaCompare(sw::ALPHA_GREATER);
3273 					break;
3274 				case D3DCMP_NOTEQUAL:
3275 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL);
3276 					break;
3277 				case D3DCMP_GREATEREQUAL:
3278 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL);
3279 					break;
3280 				case D3DCMP_ALWAYS:
3281 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS);
3282 					break;
3283 				default:
3284 					ASSERT(false);
3285 				}
3286 				break;
3287 			case D3DRS_DITHERENABLE:
3288 			//	if(!init) UNIMPLEMENTED();
3289 				break;
3290 			case D3DRS_ALPHABLENDENABLE:
3291 				renderer->setAlphaBlendEnable(value != FALSE);
3292 				break;
3293 			case D3DRS_FOGENABLE:
3294 				renderer->setFogEnable(value != FALSE);
3295 				break;
3296 			case D3DRS_FOGCOLOR:
3297 				renderer->setFogColor(value);
3298 				break;
3299 			case D3DRS_FOGTABLEMODE:
3300 				switch(value)
3301 				{
3302 				case D3DFOG_NONE:
3303 					renderer->setPixelFogMode(sw::FOG_NONE);
3304 					break;
3305 				case D3DFOG_LINEAR:
3306 					renderer->setPixelFogMode(sw::FOG_LINEAR);
3307 					break;
3308 				case D3DFOG_EXP:
3309 					renderer->setPixelFogMode(sw::FOG_EXP);
3310 					break;
3311 				case D3DFOG_EXP2:
3312 					renderer->setPixelFogMode(sw::FOG_EXP2);
3313 					break;
3314 				default:
3315 					ASSERT(false);
3316 				}
3317 				break;
3318 			case D3DRS_FOGSTART:
3319 				renderer->setFogStart((float&)value);
3320 				break;
3321 			case D3DRS_FOGEND:
3322 				renderer->setFogEnd((float&)value);
3323 				break;
3324 			case D3DRS_FOGDENSITY:
3325 				renderer->setFogDensity((float&)value);
3326 				break;
3327 			case D3DRS_RANGEFOGENABLE:
3328 				renderer->setRangeFogEnable(value != FALSE);
3329 				break;
3330 			case D3DRS_SPECULARENABLE:
3331 				renderer->setSpecularEnable(value != FALSE);
3332 				break;
3333 			case D3DRS_STENCILENABLE:
3334 				renderer->setStencilEnable(value != FALSE);
3335 				break;
3336 			case D3DRS_STENCILFAIL:
3337 				switch(value)
3338 				{
3339 				case D3DSTENCILOP_KEEP:
3340 					renderer->setStencilFailOperation(sw::OPERATION_KEEP);
3341 					break;
3342 				case D3DSTENCILOP_ZERO:
3343 					renderer->setStencilFailOperation(sw::OPERATION_ZERO);
3344 					break;
3345 				case D3DSTENCILOP_REPLACE:
3346 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE);
3347 					break;
3348 				case D3DSTENCILOP_INCRSAT:
3349 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT);
3350 					break;
3351 				case D3DSTENCILOP_DECRSAT:
3352 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT);
3353 					break;
3354 				case D3DSTENCILOP_INVERT:
3355 					renderer->setStencilFailOperation(sw::OPERATION_INVERT);
3356 					break;
3357 				case D3DSTENCILOP_INCR:
3358 					renderer->setStencilFailOperation(sw::OPERATION_INCR);
3359 					break;
3360 				case D3DSTENCILOP_DECR:
3361 					renderer->setStencilFailOperation(sw::OPERATION_DECR);
3362 					break;
3363 				default:
3364 					ASSERT(false);
3365 				}
3366 				break;
3367 			case D3DRS_STENCILZFAIL:
3368 				switch(value)
3369 				{
3370 				case D3DSTENCILOP_KEEP:
3371 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP);
3372 					break;
3373 				case D3DSTENCILOP_ZERO:
3374 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO);
3375 					break;
3376 				case D3DSTENCILOP_REPLACE:
3377 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE);
3378 					break;
3379 				case D3DSTENCILOP_INCRSAT:
3380 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT);
3381 					break;
3382 				case D3DSTENCILOP_DECRSAT:
3383 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT);
3384 					break;
3385 				case D3DSTENCILOP_INVERT:
3386 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT);
3387 					break;
3388 				case D3DSTENCILOP_INCR:
3389 					renderer->setStencilZFailOperation(sw::OPERATION_INCR);
3390 					break;
3391 				case D3DSTENCILOP_DECR:
3392 					renderer->setStencilZFailOperation(sw::OPERATION_DECR);
3393 					break;
3394 				default:
3395 					ASSERT(false);
3396 				}
3397 				break;
3398 			case D3DRS_STENCILPASS:
3399 				switch(value)
3400 				{
3401 				case D3DSTENCILOP_KEEP:
3402 					renderer->setStencilPassOperation(sw::OPERATION_KEEP);
3403 					break;
3404 				case D3DSTENCILOP_ZERO:
3405 					renderer->setStencilPassOperation(sw::OPERATION_ZERO);
3406 					break;
3407 				case D3DSTENCILOP_REPLACE:
3408 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE);
3409 					break;
3410 				case D3DSTENCILOP_INCRSAT:
3411 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT);
3412 					break;
3413 				case D3DSTENCILOP_DECRSAT:
3414 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT);
3415 					break;
3416 				case D3DSTENCILOP_INVERT:
3417 					renderer->setStencilPassOperation(sw::OPERATION_INVERT);
3418 					break;
3419 				case D3DSTENCILOP_INCR:
3420 					renderer->setStencilPassOperation(sw::OPERATION_INCR);
3421 					break;
3422 				case D3DSTENCILOP_DECR:
3423 					renderer->setStencilPassOperation(sw::OPERATION_DECR);
3424 					break;
3425 				default:
3426 					ASSERT(false);
3427 				}
3428 				break;
3429 			case D3DRS_STENCILFUNC:
3430 				switch(value)
3431 				{
3432 				case D3DCMP_NEVER:
3433 					renderer->setStencilCompare(sw::STENCIL_NEVER);
3434 					break;
3435 				case D3DCMP_LESS:
3436 					renderer->setStencilCompare(sw::STENCIL_LESS);
3437 					break;
3438 				case D3DCMP_EQUAL:
3439 					renderer->setStencilCompare(sw::STENCIL_EQUAL);
3440 					break;
3441 				case D3DCMP_LESSEQUAL:
3442 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL);
3443 					break;
3444 				case D3DCMP_GREATER:
3445 					renderer->setStencilCompare(sw::STENCIL_GREATER);
3446 					break;
3447 				case D3DCMP_NOTEQUAL:
3448 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL);
3449 					break;
3450 				case D3DCMP_GREATEREQUAL:
3451 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL);
3452 					break;
3453 				case D3DCMP_ALWAYS:
3454 					renderer->setStencilCompare(sw::STENCIL_ALWAYS);
3455 					break;
3456 				default:
3457 					ASSERT(false);
3458 				}
3459 				break;
3460 			case D3DRS_STENCILREF:
3461 				renderer->setStencilReference(value);
3462 				renderer->setStencilReferenceCCW(value);
3463 				break;
3464 			case D3DRS_STENCILMASK:
3465 				renderer->setStencilMask(value);
3466 				renderer->setStencilMaskCCW(value);
3467 				break;
3468 			case D3DRS_STENCILWRITEMASK:
3469 				renderer->setStencilWriteMask(value);
3470 				renderer->setStencilWriteMaskCCW(value);
3471 				break;
3472 			case D3DRS_TEXTUREFACTOR:
3473 				renderer->setTextureFactor(value);
3474 				break;
3475 			case D3DRS_WRAP0:
3476 				renderer->setTextureWrap(0, value);
3477 				break;
3478 			case D3DRS_WRAP1:
3479 				renderer->setTextureWrap(1, value);
3480 				break;
3481 			case D3DRS_WRAP2:
3482 				renderer->setTextureWrap(2, value);
3483 				break;
3484 			case D3DRS_WRAP3:
3485 				renderer->setTextureWrap(3, value);
3486 				break;
3487 			case D3DRS_WRAP4:
3488 				renderer->setTextureWrap(4, value);
3489 				break;
3490 			case D3DRS_WRAP5:
3491 				renderer->setTextureWrap(5, value);
3492 				break;
3493 			case D3DRS_WRAP6:
3494 				renderer->setTextureWrap(6, value);
3495 				break;
3496 			case D3DRS_WRAP7:
3497 				renderer->setTextureWrap(7, value);
3498 				break;
3499 			case D3DRS_CLIPPING:
3500 				// Ignored, clipping is always performed
3501 				break;
3502 			case D3DRS_LIGHTING:
3503 				renderer->setLightingEnable(value != FALSE);
3504 				break;
3505 			case D3DRS_AMBIENT:
3506 				renderer->setGlobalAmbient(value);
3507 				break;
3508 			case D3DRS_FOGVERTEXMODE:
3509 				switch(value)
3510 				{
3511 				case D3DFOG_NONE:
3512 					renderer->setVertexFogMode(sw::FOG_NONE);
3513 					break;
3514 				case D3DFOG_LINEAR:
3515 					renderer->setVertexFogMode(sw::FOG_LINEAR);
3516 					break;
3517 				case D3DFOG_EXP:
3518 					renderer->setVertexFogMode(sw::FOG_EXP);
3519 					break;
3520 				case D3DFOG_EXP2:
3521 					renderer->setVertexFogMode(sw::FOG_EXP2);
3522 					break;
3523 				default:
3524 					ASSERT(false);
3525 				}
3526 				break;
3527 			case D3DRS_COLORVERTEX:
3528 				renderer->setColorVertexEnable(value != FALSE);
3529 				break;
3530 			case D3DRS_LOCALVIEWER:
3531 				renderer->setLocalViewer(value != FALSE);
3532 				break;
3533 			case D3DRS_NORMALIZENORMALS:
3534 				renderer->setNormalizeNormals(value != FALSE);
3535 				break;
3536 			case D3DRS_DIFFUSEMATERIALSOURCE:
3537 				switch(value)
3538 				{
3539 				case D3DMCS_MATERIAL:
3540 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);
3541 					break;
3542 				case D3DMCS_COLOR1:
3543 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
3544 					break;
3545 				case D3DMCS_COLOR2:
3546 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2);
3547 					break;
3548 				default:
3549 					ASSERT(false);
3550 				}
3551 				break;
3552 			case D3DRS_SPECULARMATERIALSOURCE:
3553 				switch(value)
3554 				{
3555 				case D3DMCS_MATERIAL:
3556 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
3557 					break;
3558 				case D3DMCS_COLOR1:
3559 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1);
3560 					break;
3561 				case D3DMCS_COLOR2:
3562 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2);
3563 					break;
3564 				default:
3565 					ASSERT(false);
3566 				}
3567 				break;
3568 			case D3DRS_AMBIENTMATERIALSOURCE:
3569 				switch(value)
3570 				{
3571 				case D3DMCS_MATERIAL:
3572 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
3573 					break;
3574 				case D3DMCS_COLOR1:
3575 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1);
3576 					break;
3577 				case D3DMCS_COLOR2:
3578 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2);
3579 					break;
3580 				default:
3581 					ASSERT(false);
3582 				}
3583 				break;
3584 			case D3DRS_EMISSIVEMATERIALSOURCE:
3585 				switch(value)
3586 				{
3587 				case D3DMCS_MATERIAL:
3588 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
3589 					break;
3590 				case D3DMCS_COLOR1:
3591 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1);
3592 					break;
3593 				case D3DMCS_COLOR2:
3594 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2);
3595 					break;
3596 				default:
3597 					ASSERT(false);
3598 				}
3599 				break;
3600 			case D3DRS_VERTEXBLEND:
3601 				switch(value)
3602 				{
3603 				case D3DVBF_DISABLE:
3604 					renderer->setVertexBlendMatrixCount(0);
3605 					break;
3606 				case D3DVBF_1WEIGHTS:
3607 					renderer->setVertexBlendMatrixCount(2);
3608 					break;
3609 				case D3DVBF_2WEIGHTS:
3610 					renderer->setVertexBlendMatrixCount(3);
3611 					break;
3612 				case D3DVBF_3WEIGHTS:
3613 					renderer->setVertexBlendMatrixCount(4);
3614 					break;
3615 				case D3DVBF_TWEENING:
3616 					UNIMPLEMENTED();
3617 					break;
3618 				case D3DVBF_0WEIGHTS:
3619 					renderer->setVertexBlendMatrixCount(1);
3620 					break;
3621 				default:
3622 					ASSERT(false);
3623 				}
3624 				break;
3625 			case D3DRS_CLIPPLANEENABLE:
3626 				renderer->setClipFlags(value);
3627 				break;
3628 			case D3DRS_POINTSIZE:
3629 				if(value == D3DFMT_INST && pixelShaderVersionX >= D3DPS_VERSION(2, 0))   // ATI hack to enable instancing on SM 2.0 hardware
3630 				{
3631 					instancingEnabled = true;
3632 				}
3633 				else if(value == D3DFMT_A2M1)   // ATI hack to enable transparency anti-aliasing
3634 				{
3635 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3636 					renderer->setAlphaTestEnable(true);
3637 				}
3638 				else if(value == D3DFMT_A2M0)   // ATI hack to disable transparency anti-aliasing
3639 				{
3640 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3641 					renderer->setAlphaTestEnable(false);
3642 				}
3643 				else
3644 				{
3645 					renderer->setPointSize((float&)value);
3646 				}
3647 				break;
3648 			case D3DRS_POINTSIZE_MIN:
3649 				renderer->setPointSizeMin((float&)value);
3650 				break;
3651 			case D3DRS_POINTSPRITEENABLE:
3652 				renderer->setPointSpriteEnable(value != FALSE);
3653 				break;
3654 			case D3DRS_POINTSCALEENABLE:
3655 				renderer->setPointScaleEnable(value != FALSE);
3656 				break;
3657 			case D3DRS_POINTSCALE_A:
3658 				renderer->setPointScaleA((float&)value);
3659 				break;
3660 			case D3DRS_POINTSCALE_B:
3661 				renderer->setPointScaleB((float&)value);
3662 				break;
3663 			case D3DRS_POINTSCALE_C:
3664 				renderer->setPointScaleC((float&)value);
3665 				break;
3666 			case D3DRS_MULTISAMPLEANTIALIAS:
3667 			//	if(!init) UNIMPLEMENTED();
3668 				break;
3669 			case D3DRS_MULTISAMPLEMASK:
3670 				SetRenderTarget(0, renderTarget[0]);   // Sets the multi-sample mask, if maskable
3671 				break;
3672 			case D3DRS_PATCHEDGESTYLE:
3673 				if(!init) if(value != D3DPATCHEDGE_DISCRETE) UNIMPLEMENTED();
3674 				break;
3675 			case D3DRS_DEBUGMONITORTOKEN:
3676 				if(!init) UNIMPLEMENTED();
3677 				break;
3678 			case D3DRS_POINTSIZE_MAX:
3679 				renderer->setPointSizeMax((float&)value);
3680 				break;
3681 			case D3DRS_INDEXEDVERTEXBLENDENABLE:
3682 				renderer->setIndexedVertexBlendEnable(value != FALSE);
3683 				break;
3684 			case D3DRS_COLORWRITEENABLE:
3685 				renderer->setColorWriteMask(0, value & 0x0000000F);
3686 				break;
3687 			case D3DRS_TWEENFACTOR:
3688 				if(!init) UNIMPLEMENTED();
3689 				break;
3690 			case D3DRS_BLENDOP:
3691 				switch(value)
3692 				{
3693 				case D3DBLENDOP_ADD:
3694 					renderer->setBlendOperation(sw::BLENDOP_ADD);
3695 					break;
3696 				case D3DBLENDOP_SUBTRACT:
3697 					renderer->setBlendOperation(sw::BLENDOP_SUB);
3698 					break;
3699 				case D3DBLENDOP_REVSUBTRACT:
3700 					renderer->setBlendOperation(sw::BLENDOP_INVSUB);
3701 					break;
3702 				case D3DBLENDOP_MIN:
3703 					renderer->setBlendOperation(sw::BLENDOP_MIN);
3704 					break;
3705 				case D3DBLENDOP_MAX:
3706 					renderer->setBlendOperation(sw::BLENDOP_MAX);
3707 					break;
3708 				default:
3709 					ASSERT(false);
3710 				}
3711 				break;
3712 			case D3DRS_POSITIONDEGREE:
3713 				if(!init) UNIMPLEMENTED();
3714 				break;
3715 			case D3DRS_NORMALDEGREE:
3716 				if(!init) UNIMPLEMENTED();
3717 				break;
3718 			case D3DRS_SCISSORTESTENABLE:
3719 				scissorEnable = (value != FALSE);
3720 				break;
3721 			case D3DRS_SLOPESCALEDEPTHBIAS:
3722 				renderer->setSlopeDepthBias((float&)value);
3723 				break;
3724 			case D3DRS_ANTIALIASEDLINEENABLE:
3725 				if(!init) if(value != FALSE) UNIMPLEMENTED();
3726 				break;
3727 			case D3DRS_MINTESSELLATIONLEVEL:
3728 				if(!init) UNIMPLEMENTED();
3729 				break;
3730 			case D3DRS_MAXTESSELLATIONLEVEL:
3731 				if(!init) UNIMPLEMENTED();
3732 				break;
3733 			case D3DRS_ADAPTIVETESS_X:
3734 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3735 				break;
3736 			case D3DRS_ADAPTIVETESS_Y:
3737 				if(value == D3DFMT_ATOC)   // NVIDIA hack to enable transparency anti-aliasing
3738 				{
3739 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3740 				}
3741 				else if(value == D3DFMT_UNKNOWN)   // NVIDIA hack to disable transparency anti-aliasing
3742 				{
3743 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3744 				}
3745 				else
3746 				{
3747 					if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3748 				}
3749 				break;
3750 			case D3DRS_ADAPTIVETESS_Z:
3751 				if(!init) if((float&)value != 1.0f) UNIMPLEMENTED();
3752 				break;
3753 			case D3DRS_ADAPTIVETESS_W:
3754 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3755 				break;
3756 			case D3DRS_ENABLEADAPTIVETESSELLATION:
3757 				if(!init) UNIMPLEMENTED();
3758 				break;
3759 			case D3DRS_TWOSIDEDSTENCILMODE:
3760 				renderer->setTwoSidedStencil(value != FALSE);
3761 				break;
3762 			case D3DRS_CCW_STENCILFAIL:
3763 				switch(value)
3764 				{
3765 				case D3DSTENCILOP_KEEP:
3766 					renderer->setStencilFailOperationCCW(sw::OPERATION_KEEP);
3767 					break;
3768 				case D3DSTENCILOP_ZERO:
3769 					renderer->setStencilFailOperationCCW(sw::OPERATION_ZERO);
3770 					break;
3771 				case D3DSTENCILOP_REPLACE:
3772 					renderer->setStencilFailOperationCCW(sw::OPERATION_REPLACE);
3773 					break;
3774 				case D3DSTENCILOP_INCRSAT:
3775 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCRSAT);
3776 					break;
3777 				case D3DSTENCILOP_DECRSAT:
3778 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECRSAT);
3779 					break;
3780 				case D3DSTENCILOP_INVERT:
3781 					renderer->setStencilFailOperationCCW(sw::OPERATION_INVERT);
3782 					break;
3783 				case D3DSTENCILOP_INCR:
3784 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCR);
3785 					break;
3786 				case D3DSTENCILOP_DECR:
3787 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECR);
3788 					break;
3789 				default:
3790 					ASSERT(false);
3791 				}
3792 				break;
3793 			case D3DRS_CCW_STENCILZFAIL:
3794 				switch(value)
3795 				{
3796 				case D3DSTENCILOP_KEEP:
3797 					renderer->setStencilZFailOperationCCW(sw::OPERATION_KEEP);
3798 					break;
3799 				case D3DSTENCILOP_ZERO:
3800 					renderer->setStencilZFailOperationCCW(sw::OPERATION_ZERO);
3801 					break;
3802 				case D3DSTENCILOP_REPLACE:
3803 					renderer->setStencilZFailOperationCCW(sw::OPERATION_REPLACE);
3804 					break;
3805 				case D3DSTENCILOP_INCRSAT:
3806 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCRSAT);
3807 					break;
3808 				case D3DSTENCILOP_DECRSAT:
3809 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECRSAT);
3810 					break;
3811 				case D3DSTENCILOP_INVERT:
3812 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INVERT);
3813 					break;
3814 				case D3DSTENCILOP_INCR:
3815 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCR);
3816 					break;
3817 				case D3DSTENCILOP_DECR:
3818 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECR);
3819 					break;
3820 				default:
3821 					ASSERT(false);
3822 				}
3823 				break;
3824 			case D3DRS_CCW_STENCILPASS:
3825 				switch(value)
3826 				{
3827 				case D3DSTENCILOP_KEEP:
3828 					renderer->setStencilPassOperationCCW(sw::OPERATION_KEEP);
3829 					break;
3830 				case D3DSTENCILOP_ZERO:
3831 					renderer->setStencilPassOperationCCW(sw::OPERATION_ZERO);
3832 					break;
3833 				case D3DSTENCILOP_REPLACE:
3834 					renderer->setStencilPassOperationCCW(sw::OPERATION_REPLACE);
3835 					break;
3836 				case D3DSTENCILOP_INCRSAT:
3837 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCRSAT);
3838 					break;
3839 				case D3DSTENCILOP_DECRSAT:
3840 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECRSAT);
3841 					break;
3842 				case D3DSTENCILOP_INVERT:
3843 					renderer->setStencilPassOperationCCW(sw::OPERATION_INVERT);
3844 					break;
3845 				case D3DSTENCILOP_INCR:
3846 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCR);
3847 					break;
3848 				case D3DSTENCILOP_DECR:
3849 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECR);
3850 					break;
3851 				default:
3852 					ASSERT(false);
3853 				}
3854 				break;
3855 			case D3DRS_CCW_STENCILFUNC:
3856 				switch(value)
3857 				{
3858 				case D3DCMP_NEVER:
3859 					renderer->setStencilCompareCCW(sw::STENCIL_NEVER);
3860 					break;
3861 				case D3DCMP_LESS:
3862 					renderer->setStencilCompareCCW(sw::STENCIL_LESS);
3863 					break;
3864 				case D3DCMP_EQUAL:
3865 					renderer->setStencilCompareCCW(sw::STENCIL_EQUAL);
3866 					break;
3867 				case D3DCMP_LESSEQUAL:
3868 					renderer->setStencilCompareCCW(sw::STENCIL_LESSEQUAL);
3869 					break;
3870 				case D3DCMP_GREATER:
3871 					renderer->setStencilCompareCCW(sw::STENCIL_GREATER);
3872 					break;
3873 				case D3DCMP_NOTEQUAL:
3874 					renderer->setStencilCompareCCW(sw::STENCIL_NOTEQUAL);
3875 					break;
3876 				case D3DCMP_GREATEREQUAL:
3877 					renderer->setStencilCompareCCW(sw::STENCIL_GREATEREQUAL);
3878 					break;
3879 				case D3DCMP_ALWAYS:
3880 					renderer->setStencilCompareCCW(sw::STENCIL_ALWAYS);
3881 					break;
3882 				default:
3883 					ASSERT(false);
3884 				}
3885 				break;
3886 			case D3DRS_COLORWRITEENABLE1:
3887 				renderer->setColorWriteMask(1, value);
3888 				break;
3889 			case D3DRS_COLORWRITEENABLE2:
3890 				renderer->setColorWriteMask(2, value);
3891 				break;
3892 			case D3DRS_COLORWRITEENABLE3:
3893 				renderer->setColorWriteMask(3, value);
3894 				break;
3895 			case D3DRS_BLENDFACTOR:
3896 				renderer->setBlendConstant(sw::Color<float>(value));
3897 				break;
3898 			case D3DRS_SRGBWRITEENABLE:
3899 				renderer->setWriteSRGB(value != FALSE);
3900 				break;
3901 			case D3DRS_DEPTHBIAS:
3902 				renderer->setDepthBias((float&)value);
3903 				break;
3904 			case D3DRS_WRAP8:
3905 				renderer->setTextureWrap(8, value);
3906 				break;
3907 			case D3DRS_WRAP9:
3908 				renderer->setTextureWrap(9, value);
3909 				break;
3910 			case D3DRS_WRAP10:
3911 				renderer->setTextureWrap(10, value);
3912 				break;
3913 			case D3DRS_WRAP11:
3914 				renderer->setTextureWrap(11, value);
3915 				break;
3916 			case D3DRS_WRAP12:
3917 				renderer->setTextureWrap(12, value);
3918 				break;
3919 			case D3DRS_WRAP13:
3920 				renderer->setTextureWrap(13, value);
3921 				break;
3922 			case D3DRS_WRAP14:
3923 				renderer->setTextureWrap(14, value);
3924 				break;
3925 			case D3DRS_WRAP15:
3926 				renderer->setTextureWrap(15, value);
3927 				break;
3928 			case D3DRS_SEPARATEALPHABLENDENABLE:
3929 				renderer->setSeparateAlphaBlendEnable(value != FALSE);
3930 				break;
3931 			case D3DRS_SRCBLENDALPHA:
3932 				switch(value)
3933 				{
3934 				case D3DBLEND_ZERO:
3935 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ZERO);
3936 					break;
3937 				case D3DBLEND_ONE:
3938 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ONE);
3939 					break;
3940 				case D3DBLEND_SRCCOLOR:
3941 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCE);
3942 					break;
3943 				case D3DBLEND_INVSRCCOLOR:
3944 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCE);
3945 					break;
3946 				case D3DBLEND_SRCALPHA:
3947 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3948 					break;
3949 				case D3DBLEND_INVSRCALPHA:
3950 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3951 					break;
3952 				case D3DBLEND_DESTALPHA:
3953 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DESTALPHA);
3954 					break;
3955 				case D3DBLEND_INVDESTALPHA:
3956 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
3957 					break;
3958 				case D3DBLEND_DESTCOLOR:
3959 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DEST);
3960 					break;
3961 				case D3DBLEND_INVDESTCOLOR:
3962 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDEST);
3963 					break;
3964 				case D3DBLEND_SRCALPHASAT:
3965 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
3966 					break;
3967 				case D3DBLEND_BOTHSRCALPHA:
3968 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3969 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3970 					break;
3971 				case D3DBLEND_BOTHINVSRCALPHA:
3972 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3973 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3974 					break;
3975 				case D3DBLEND_BLENDFACTOR:
3976 					renderer->setSourceBlendFactorAlpha(sw::BLEND_CONSTANT);
3977 					break;
3978 				case D3DBLEND_INVBLENDFACTOR:
3979 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVCONSTANT);
3980 					break;
3981 				default:
3982 					ASSERT(false);
3983 				}
3984 				break;
3985 			case D3DRS_DESTBLENDALPHA:
3986 				switch(value)
3987 				{
3988 				case D3DBLEND_ZERO:
3989 					renderer->setDestBlendFactorAlpha(sw::BLEND_ZERO);
3990 					break;
3991 				case D3DBLEND_ONE:
3992 					renderer->setDestBlendFactorAlpha(sw::BLEND_ONE);
3993 					break;
3994 				case D3DBLEND_SRCCOLOR:
3995 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCE);
3996 					break;
3997 				case D3DBLEND_INVSRCCOLOR:
3998 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCE);
3999 					break;
4000 				case D3DBLEND_SRCALPHA:
4001 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4002 					break;
4003 				case D3DBLEND_INVSRCALPHA:
4004 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4005 					break;
4006 				case D3DBLEND_DESTALPHA:
4007 					renderer->setDestBlendFactorAlpha(sw::BLEND_DESTALPHA);
4008 					break;
4009 				case D3DBLEND_INVDESTALPHA:
4010 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
4011 					break;
4012 				case D3DBLEND_DESTCOLOR:
4013 					renderer->setDestBlendFactorAlpha(sw::BLEND_DEST);
4014 					break;
4015 				case D3DBLEND_INVDESTCOLOR:
4016 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDEST);
4017 					break;
4018 				case D3DBLEND_SRCALPHASAT:
4019 					renderer->setDestBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
4020 					break;
4021 				case D3DBLEND_BOTHSRCALPHA:
4022 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4023 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4024 					break;
4025 				case D3DBLEND_BOTHINVSRCALPHA:
4026 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4027 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4028 					break;
4029 				case D3DBLEND_BLENDFACTOR:
4030 					renderer->setDestBlendFactorAlpha(sw::BLEND_CONSTANT);
4031 					break;
4032 				case D3DBLEND_INVBLENDFACTOR:
4033 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVCONSTANT);
4034 					break;
4035 				default:
4036 					ASSERT(false);
4037 				}
4038 				break;
4039 			case D3DRS_BLENDOPALPHA:
4040 				switch(value)
4041 				{
4042 				case D3DBLENDOP_ADD:
4043 					renderer->setBlendOperationAlpha(sw::BLENDOP_ADD);
4044 					break;
4045 				case D3DBLENDOP_SUBTRACT:
4046 					renderer->setBlendOperationAlpha(sw::BLENDOP_SUB);
4047 					break;
4048 				case D3DBLENDOP_REVSUBTRACT:
4049 					renderer->setBlendOperationAlpha(sw::BLENDOP_INVSUB);
4050 					break;
4051 				case D3DBLENDOP_MIN:
4052 					renderer->setBlendOperationAlpha(sw::BLENDOP_MIN);
4053 					break;
4054 				case D3DBLENDOP_MAX:
4055 					renderer->setBlendOperationAlpha(sw::BLENDOP_MAX);
4056 					break;
4057 				default:
4058 					ASSERT(false);
4059 				}
4060 				break;
4061 			default:
4062 				ASSERT(false);
4063 			}
4064 		}
4065 		else   // stateRecorder
4066 		{
4067 			stateRecorder->setRenderState(state, value);
4068 		}
4069 
4070 		return D3D_OK;
4071 	}
4072 
SetRenderTarget(unsigned long index,IDirect3DSurface9 * iRenderTarget)4073 	long Direct3DDevice9::SetRenderTarget(unsigned long index, IDirect3DSurface9 *iRenderTarget)
4074 	{
4075 		CriticalSection cs(this);
4076 
4077 		TRACE("unsigned long index = %d, IDirect3DSurface9 *newRenderTarget = 0x%0.8p", index, iRenderTarget);
4078 
4079 		// FIXME: Check for D3DUSAGE_RENDERTARGET
4080 
4081 		if(index >= 4 || (index == 0 && !iRenderTarget))
4082 		{
4083 			return INVALIDCALL();
4084 		}
4085 
4086 		Direct3DSurface9 *renderTarget = static_cast<Direct3DSurface9*>(iRenderTarget);
4087 
4088 		if(renderTarget)
4089 		{
4090 			renderTarget->bind();
4091 		}
4092 
4093 		if(this->renderTarget[index])
4094 		{
4095 			this->renderTarget[index]->unbind();
4096 		}
4097 
4098 		this->renderTarget[index] = renderTarget;
4099 
4100 		if(renderTarget && index == 0)
4101 		{
4102 			D3DSURFACE_DESC renderTargetDesc;
4103 			renderTarget->GetDesc(&renderTargetDesc);
4104 
4105 			// Reset viewport to size of current render target
4106 			viewport.X = 0;
4107 			viewport.Y = 0;
4108 			viewport.Width = renderTargetDesc.Width;
4109 			viewport.Height = renderTargetDesc.Height;
4110 			viewport.MinZ = 0;
4111 			viewport.MaxZ = 1;
4112 
4113 			// Reset scissor rectangle to size of current render target
4114 			scissorRect.left = 0;
4115 			scissorRect.top = 0;
4116 			scissorRect.right = renderTargetDesc.Width;
4117 			scissorRect.bottom = renderTargetDesc.Height;
4118 
4119 			// Set the multi-sample mask, if maskable
4120 			if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE &&
4121 			   renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONMASKABLE)
4122 			{
4123 				renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]);
4124 			}
4125 			else
4126 			{
4127 				renderer->setMultiSampleMask(0xFFFFFFFF);
4128 			}
4129 		}
4130 
4131 		renderer->setRenderTarget(index, renderTarget);
4132 
4133 		return D3D_OK;
4134 	}
4135 
SetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long value)4136 	long Direct3DDevice9::SetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long value)
4137 	{
4138 		CriticalSection cs(this);
4139 
4140 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE state = %d, unsigned long value = %d", sampler, state, value);
4141 
4142 		if(state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)
4143 		{
4144 			return INVALIDCALL();
4145 		}
4146 
4147 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4148 		{
4149 			return INVALIDCALL();
4150 		}
4151 
4152 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4153 		{
4154 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4155 		}
4156 
4157 		if(!stateRecorder)
4158 		{
4159 			if(!init && samplerState[sampler][state] == value)
4160 			{
4161 				return D3D_OK;
4162 			}
4163 
4164 			samplerState[sampler][state] = value;
4165 
4166 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX;
4167 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group
4168 
4169 			switch(state)
4170 			{
4171 			case D3DSAMP_ADDRESSU:
4172 				switch(value)
4173 				{
4174 				case D3DTADDRESS_WRAP:
4175 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_WRAP);
4176 					break;
4177 				case D3DTADDRESS_MIRROR:
4178 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRROR);
4179 					break;
4180 				case D3DTADDRESS_CLAMP:
4181 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_CLAMP);
4182 					break;
4183 				case D3DTADDRESS_BORDER:
4184 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_BORDER);
4185 					break;
4186 				case D3DTADDRESS_MIRRORONCE:
4187 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRRORONCE);
4188 					break;
4189 				default:
4190 					ASSERT(false);
4191 				}
4192 				break;
4193 			case D3DSAMP_ADDRESSV:
4194 				switch(value)
4195 				{
4196 				case D3DTADDRESS_WRAP:
4197 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_WRAP);
4198 					break;
4199 				case D3DTADDRESS_MIRROR:
4200 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRROR);
4201 					break;
4202 				case D3DTADDRESS_CLAMP:
4203 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_CLAMP);
4204 					break;
4205 				case D3DTADDRESS_BORDER:
4206 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_BORDER);
4207 					break;
4208 				case D3DTADDRESS_MIRRORONCE:
4209 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRRORONCE);
4210 					break;
4211 				default:
4212 					ASSERT(false);
4213 				}
4214 				break;
4215 			case D3DSAMP_ADDRESSW:
4216 				switch(value)
4217 				{
4218 				case D3DTADDRESS_WRAP:
4219 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_WRAP);
4220 					break;
4221 				case D3DTADDRESS_MIRROR:
4222 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRROR);
4223 					break;
4224 				case D3DTADDRESS_CLAMP:
4225 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_CLAMP);
4226 					break;
4227 				case D3DTADDRESS_BORDER:
4228 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_BORDER);
4229 					break;
4230 				case D3DTADDRESS_MIRRORONCE:
4231 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRRORONCE);
4232 					break;
4233 				default:
4234 					ASSERT(false);
4235 				}
4236 				break;
4237 			case D3DSAMP_BORDERCOLOR:
4238 				renderer->setBorderColor(type, index, value);
4239 				break;
4240 			case D3DSAMP_MAGFILTER:
4241 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4242 				switch(value)
4243 				{
4244 				case D3DTEXF_NONE:
4245 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4246 					break;
4247 				case D3DTEXF_POINT:
4248 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4249 					break;
4250 				case D3DTEXF_LINEAR:
4251 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4252 					break;
4253 				case D3DTEXF_ANISOTROPIC:
4254 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4255 					break;
4256 				case D3DTEXF_PYRAMIDALQUAD:
4257 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4258 					break;
4259 				case D3DTEXF_GAUSSIANQUAD:
4260 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4261 					break;
4262 				default:
4263 					return INVALIDCALL();
4264 				};
4265 				break;
4266 			case D3DSAMP_MINFILTER:
4267 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4268 				switch(value)
4269 				{
4270 				case D3DTEXF_NONE:
4271 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4272 					break;
4273 				case D3DTEXF_POINT:
4274 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4275 					break;
4276 				case D3DTEXF_LINEAR:
4277 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4278 					break;
4279 				case D3DTEXF_ANISOTROPIC:
4280 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4281 					break;
4282 				case D3DTEXF_PYRAMIDALQUAD:
4283 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4284 					break;
4285 				case D3DTEXF_GAUSSIANQUAD:
4286 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4287 					break;
4288 				default:
4289 					return INVALIDCALL();
4290 				};
4291 				break;
4292 			case D3DSAMP_MIPFILTER:
4293 				switch(value)
4294 				{
4295 				case D3DTEXF_NONE:
4296 					renderer->setMipmapFilter(type, index, sw::MIPMAP_NONE);
4297 					break;
4298 				case D3DTEXF_POINT:
4299 					renderer->setMipmapFilter(type, index, sw::MIPMAP_POINT);
4300 					break;
4301 				case D3DTEXF_LINEAR:
4302 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);
4303 					break;
4304 				case D3DTEXF_ANISOTROPIC:
4305 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4306 					break;
4307 				case D3DTEXF_PYRAMIDALQUAD:
4308 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4309 					break;
4310 				case D3DTEXF_GAUSSIANQUAD:
4311 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4312 					break;
4313 				default:
4314 					return INVALIDCALL();
4315 				};
4316 				break;
4317 			case D3DSAMP_MIPMAPLODBIAS:
4318 				if(value == D3DFMT_GET4)   // ATI hack to enable Fetch4
4319 				{
4320 					renderer->setGatherEnable(type, index, true);
4321 				}
4322 				else if(value == D3DFMT_GET1)   // ATI hack to disable Fetch4
4323 				{
4324 					renderer->setGatherEnable(type, index, false);
4325 				}
4326 				else
4327 				{
4328 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes
4329 					renderer->setMipmapLOD(type, index, LOD);
4330 				}
4331 				break;
4332 			case D3DSAMP_MAXMIPLEVEL:
4333 				break;
4334 			case D3DSAMP_MAXANISOTROPY:
4335 				renderer->setMaxAnisotropy(type, index, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy));
4336 				break;
4337 			case D3DSAMP_SRGBTEXTURE:
4338 				renderer->setReadSRGB(type, index, value != FALSE);
4339 				break;
4340 			case D3DSAMP_ELEMENTINDEX:
4341 				if(!init) UNIMPLEMENTED();   // Multi-element textures deprecated in favor of multiple render targets
4342 				break;
4343 			case D3DSAMP_DMAPOFFSET:
4344 			//	if(!init) UNIMPLEMENTED();
4345 				break;
4346 			default:
4347 				ASSERT(false);
4348 			}
4349 		}
4350 		else   // stateRecorder
4351 		{
4352 			stateRecorder->setSamplerState(sampler, state, value);
4353 		}
4354 
4355 		return D3D_OK;
4356 	}
4357 
SetScissorRect(const RECT * rect)4358 	long Direct3DDevice9::SetScissorRect(const RECT *rect)
4359 	{
4360 		CriticalSection cs(this);
4361 
4362 		TRACE("const RECT *rect = 0x%0.8p", rect);
4363 
4364 		if(!rect)
4365 		{
4366 			return INVALIDCALL();
4367 		}
4368 
4369 		if(!stateRecorder)
4370 		{
4371 			scissorRect = *rect;
4372 		}
4373 		else
4374 		{
4375 			stateRecorder->setScissorRect(rect);
4376 		}
4377 
4378 		return D3D_OK;
4379 	}
4380 
SetSoftwareVertexProcessing(int software)4381 	long Direct3DDevice9::SetSoftwareVertexProcessing(int software)
4382 	{
4383 		CriticalSection cs(this);
4384 
4385 		TRACE("int software = %d", software);
4386 
4387 		if(behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING && software == FALSE)
4388 		{
4389 			return INVALIDCALL();
4390 		}
4391 
4392 		if(behaviourFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING && software == TRUE)
4393 		{
4394 			return INVALIDCALL();
4395 		}
4396 
4397 		softwareVertexProcessing = (software != FALSE);
4398 
4399 		return D3D_OK;
4400 	}
4401 
SetStreamSource(unsigned int stream,IDirect3DVertexBuffer9 * iVertexBuffer,unsigned int offset,unsigned int stride)4402 	long Direct3DDevice9::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer9 *iVertexBuffer, unsigned int offset, unsigned int stride)
4403 	{
4404 		CriticalSection cs(this);
4405 
4406 		TRACE("unsigned int stream = %d, IDirect3DVertexBuffer9 *data = 0x%0.8p, unsigned int offset = %d, unsigned int stride = %d", stream, iVertexBuffer, offset, stride);
4407 
4408 		Direct3DVertexBuffer9 *vertexBuffer = static_cast<Direct3DVertexBuffer9*>(iVertexBuffer);
4409 
4410 		if(!stateRecorder)
4411 		{
4412 			if(dataStream[stream] == vertexBuffer && streamOffset[stream] == offset && streamStride[stream] == stride)
4413 			{
4414 				return D3D_OK;
4415 			}
4416 
4417 			if(vertexBuffer)
4418 			{
4419 				vertexBuffer->bind();
4420 			}
4421 
4422 			if(dataStream[stream])
4423 			{
4424 				dataStream[stream]->unbind();
4425 			}
4426 
4427 			dataStream[stream] = vertexBuffer;
4428 			streamOffset[stream] = offset;
4429 			streamStride[stream] = stride;
4430 		}
4431 		else
4432 		{
4433 			stateRecorder->setStreamSource(stream, vertexBuffer, offset, stride);
4434 		}
4435 
4436 		return D3D_OK;
4437 	}
4438 
SetStreamSourceFreq(unsigned int streamNumber,unsigned int divider)4439 	long Direct3DDevice9::SetStreamSourceFreq(unsigned int streamNumber, unsigned int divider)
4440 	{
4441 		CriticalSection cs(this);
4442 
4443 		TRACE("unsigned int streamNumber = %d, unsigned int divider = %d", streamNumber, divider);
4444 
4445 		if(!instancingEnabled)
4446 		{
4447 			return INVALIDCALL();
4448 		}
4449 
4450 		if(!stateRecorder)
4451 		{
4452 			streamSourceFreq[streamNumber] = divider;
4453 		}
4454 		else
4455 		{
4456 			stateRecorder->setStreamSourceFreq(streamNumber, divider);
4457 		}
4458 
4459 		return D3D_OK;
4460 	}
4461 
SetTexture(unsigned long sampler,IDirect3DBaseTexture9 * iBaseTexture)4462 	long Direct3DDevice9::SetTexture(unsigned long sampler, IDirect3DBaseTexture9 *iBaseTexture)
4463 	{
4464 		CriticalSection cs(this);
4465 
4466 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 *texture = 0x%0.8p", sampler, iBaseTexture);
4467 
4468 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4469 		{
4470 			return INVALIDCALL();
4471 		}
4472 
4473 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4474 		{
4475 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4476 		}
4477 
4478 		Direct3DBaseTexture9 *baseTexture = dynamic_cast<Direct3DBaseTexture9*>(iBaseTexture);
4479 
4480 		if(!stateRecorder)
4481 		{
4482 			if(texture[sampler] == baseTexture)
4483 			{
4484 				return D3D_OK;
4485 			}
4486 
4487 			if(baseTexture)
4488 			{
4489 				baseTexture->bind();   // FIXME: Bind individual sub-surfaces?
4490 			}
4491 
4492 			if(texture[sampler])
4493 			{
4494 				texture[sampler]->unbind();
4495 			}
4496 
4497 			texture[sampler] = baseTexture;
4498 		}
4499 		else
4500 		{
4501 			stateRecorder->setTexture(sampler, baseTexture);
4502 		}
4503 
4504 		return D3D_OK;
4505 	}
4506 
SetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long value)4507 	long Direct3DDevice9::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value)
4508 	{
4509 		CriticalSection cs(this);
4510 
4511 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value);
4512 
4513 		if(stage < 0 || stage >= 8 || type < D3DTSS_COLOROP || type > D3DTSS_CONSTANT)
4514 		{
4515 			return INVALIDCALL();
4516 		}
4517 
4518 		if(!stateRecorder)
4519 		{
4520 			if(!init && textureStageState[stage][type] == value)
4521 			{
4522 				return D3D_OK;
4523 			}
4524 
4525 			textureStageState[stage][type] = value;
4526 
4527 			switch(type)
4528 			{
4529 			case D3DTSS_COLOROP:
4530 				switch(value)
4531 				{
4532 				case D3DTOP_DISABLE:
4533 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE);
4534 					break;
4535 				case D3DTOP_SELECTARG1:
4536 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1);
4537 					break;
4538 				case D3DTOP_SELECTARG2:
4539 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2);
4540 					break;
4541 				case D3DTOP_MODULATE:
4542 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE);
4543 					break;
4544 				case D3DTOP_MODULATE2X:
4545 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X);
4546 					break;
4547 				case D3DTOP_MODULATE4X:
4548 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X);
4549 					break;
4550 				case D3DTOP_ADD:
4551 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD);
4552 					break;
4553 				case D3DTOP_ADDSIGNED:
4554 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED);
4555 					break;
4556 				case D3DTOP_ADDSIGNED2X:
4557 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4558 					break;
4559 				case D3DTOP_SUBTRACT:
4560 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT);
4561 					break;
4562 				case D3DTOP_ADDSMOOTH:
4563 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4564 					break;
4565 				case D3DTOP_BLENDDIFFUSEALPHA:
4566 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4567 					break;
4568 				case D3DTOP_BLENDTEXTUREALPHA:
4569 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4570 					break;
4571 				case D3DTOP_BLENDFACTORALPHA:
4572 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4573 					break;
4574 				case D3DTOP_BLENDTEXTUREALPHAPM:
4575 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4576 					break;
4577 				case D3DTOP_BLENDCURRENTALPHA:
4578 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4579 					break;
4580 				case D3DTOP_PREMODULATE:
4581 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE);
4582 					break;
4583 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4584 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4585 					break;
4586 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4587 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4588 					break;
4589 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4590 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4591 					break;
4592 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4593 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4594 					break;
4595 				case D3DTOP_BUMPENVMAP:
4596 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4597 					break;
4598 				case D3DTOP_BUMPENVMAPLUMINANCE:
4599 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4600 					break;
4601 				case D3DTOP_DOTPRODUCT3:
4602 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3);
4603 					break;
4604 				case D3DTOP_MULTIPLYADD:
4605 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4606 					break;
4607 				case D3DTOP_LERP:
4608 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP);
4609 					break;
4610 				default:
4611 					ASSERT(false);
4612 				}
4613 				break;
4614 			case D3DTSS_COLORARG1:
4615 				switch(value & D3DTA_SELECTMASK)
4616 				{
4617 				case D3DTA_DIFFUSE:
4618 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4619 					break;
4620 				case D3DTA_CURRENT:
4621 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4622 					break;
4623 				case D3DTA_TEXTURE:
4624 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4625 					break;
4626 				case D3DTA_TFACTOR:
4627 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4628 					break;
4629 				case D3DTA_SPECULAR:
4630 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4631 					break;
4632 				case D3DTA_TEMP:
4633 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP);
4634 					break;
4635 				case D3DTA_CONSTANT:
4636 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4637 					break;
4638 				default:
4639 					ASSERT(false);
4640 				}
4641 
4642 				switch(value & ~D3DTA_SELECTMASK)
4643 				{
4644 				case 0:
4645 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4646 					break;
4647 				case D3DTA_COMPLEMENT:
4648 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4649 					break;
4650 				case D3DTA_ALPHAREPLICATE:
4651 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4652 					break;
4653 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4654 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4655 					break;
4656 				default:
4657 					ASSERT(false);
4658 				}
4659 				break;
4660 			case D3DTSS_COLORARG2:
4661 				switch(value & D3DTA_SELECTMASK)
4662 				{
4663 				case D3DTA_DIFFUSE:
4664 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4665 					break;
4666 				case D3DTA_CURRENT:
4667 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4668 					break;
4669 				case D3DTA_TEXTURE:
4670 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4671 					break;
4672 				case D3DTA_TFACTOR:
4673 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4674 					break;
4675 				case D3DTA_SPECULAR:
4676 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4677 					break;
4678 				case D3DTA_TEMP:
4679 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP);
4680 					break;
4681 				case D3DTA_CONSTANT:
4682 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4683 					break;
4684 				default:
4685 					ASSERT(false);
4686 				}
4687 
4688 				switch(value & ~D3DTA_SELECTMASK)
4689 				{
4690 				case 0:
4691 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4692 					break;
4693 				case D3DTA_COMPLEMENT:
4694 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4695 					break;
4696 				case D3DTA_ALPHAREPLICATE:
4697 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4698 					break;
4699 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4700 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4701 					break;
4702 				default:
4703 					ASSERT(false);
4704 				}
4705 				break;
4706 			case D3DTSS_ALPHAOP:
4707 				switch(value)
4708 				{
4709 				case D3DTOP_DISABLE:
4710 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE);
4711 					break;
4712 				case D3DTOP_SELECTARG1:
4713 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1);
4714 					break;
4715 				case D3DTOP_SELECTARG2:
4716 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2);
4717 					break;
4718 				case D3DTOP_MODULATE:
4719 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE);
4720 					break;
4721 				case D3DTOP_MODULATE2X:
4722 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X);
4723 					break;
4724 				case D3DTOP_MODULATE4X:
4725 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X);
4726 					break;
4727 				case D3DTOP_ADD:
4728 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD);
4729 					break;
4730 				case D3DTOP_ADDSIGNED:
4731 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED);
4732 					break;
4733 				case D3DTOP_ADDSIGNED2X:
4734 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4735 					break;
4736 				case D3DTOP_SUBTRACT:
4737 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT);
4738 					break;
4739 				case D3DTOP_ADDSMOOTH:
4740 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4741 					break;
4742 				case D3DTOP_BLENDDIFFUSEALPHA:
4743 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4744 					break;
4745 				case D3DTOP_BLENDTEXTUREALPHA:
4746 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4747 					break;
4748 				case D3DTOP_BLENDFACTORALPHA:
4749 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4750 					break;
4751 				case D3DTOP_BLENDTEXTUREALPHAPM:
4752 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4753 					break;
4754 				case D3DTOP_BLENDCURRENTALPHA:
4755 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4756 					break;
4757 				case D3DTOP_PREMODULATE:
4758 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE);
4759 					break;
4760 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4761 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4762 					break;
4763 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4764 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4765 					break;
4766 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4767 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4768 					break;
4769 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4770 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4771 					break;
4772 				case D3DTOP_BUMPENVMAP:
4773 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4774 					break;
4775 				case D3DTOP_BUMPENVMAPLUMINANCE:
4776 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4777 					break;
4778 				case D3DTOP_DOTPRODUCT3:
4779 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3);
4780 					break;
4781 				case D3DTOP_MULTIPLYADD:
4782 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4783 					break;
4784 				case D3DTOP_LERP:
4785 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP);
4786 					break;
4787 				default:
4788 					ASSERT(false);
4789 				}
4790 				break;
4791 			case D3DTSS_ALPHAARG1:
4792 				switch(value & D3DTA_SELECTMASK)
4793 				{
4794 				case D3DTA_DIFFUSE:
4795 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4796 					break;
4797 				case D3DTA_CURRENT:
4798 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4799 					break;
4800 				case D3DTA_TEXTURE:
4801 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4802 					break;
4803 				case D3DTA_TFACTOR:
4804 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4805 					break;
4806 				case D3DTA_SPECULAR:
4807 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4808 					break;
4809 				case D3DTA_TEMP:
4810 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4811 					break;
4812 				case D3DTA_CONSTANT:
4813 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4814 					break;
4815 				default:
4816 					ASSERT(false);
4817 				}
4818 
4819 				switch(value & ~D3DTA_SELECTMASK)
4820 				{
4821 				case 0:
4822 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4823 					break;
4824 				case D3DTA_COMPLEMENT:
4825 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4826 					break;
4827 				case D3DTA_ALPHAREPLICATE:
4828 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4829 					break;
4830 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4831 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4832 					break;
4833 				default:
4834 					ASSERT(false);
4835 				}
4836 				break;
4837 			case D3DTSS_ALPHAARG2:
4838 				switch(value & D3DTA_SELECTMASK)
4839 				{
4840 				case D3DTA_DIFFUSE:
4841 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4842 					break;
4843 				case D3DTA_CURRENT:
4844 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4845 					break;
4846 				case D3DTA_TEXTURE:
4847 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4848 					break;
4849 				case D3DTA_TFACTOR:
4850 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4851 					break;
4852 				case D3DTA_SPECULAR:
4853 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4854 					break;
4855 				case D3DTA_TEMP:
4856 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4857 					break;
4858 				case D3DTA_CONSTANT:
4859 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4860 					break;
4861 				default:
4862 					ASSERT(false);
4863 				}
4864 
4865 				switch(value & ~D3DTA_SELECTMASK)
4866 				{
4867 				case 0:
4868 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4869 					break;
4870 				case D3DTA_COMPLEMENT:
4871 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4872 					break;
4873 				case D3DTA_ALPHAREPLICATE:
4874 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4875 					break;
4876 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4877 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
4878 					break;
4879 				default:
4880 					ASSERT(false);
4881 				}
4882 				break;
4883 			case D3DTSS_BUMPENVMAT00:
4884 				renderer->setBumpmapMatrix(stage, 0, (float&)value);
4885 				break;
4886 			case D3DTSS_BUMPENVMAT01:
4887 				renderer->setBumpmapMatrix(stage, 1, (float&)value);
4888 				break;
4889 			case D3DTSS_BUMPENVMAT10:
4890 				renderer->setBumpmapMatrix(stage, 2, (float&)value);
4891 				break;
4892 			case D3DTSS_BUMPENVMAT11:
4893 				renderer->setBumpmapMatrix(stage, 3, (float&)value);
4894 				break;
4895 			case D3DTSS_TEXCOORDINDEX:
4896 				renderer->setTexCoordIndex(stage, value & 0x0000FFFF);
4897 
4898 				switch(value & 0xFFFF0000)
4899 				{
4900 				case D3DTSS_TCI_PASSTHRU:
4901 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU);
4902 					break;
4903 				case D3DTSS_TCI_CAMERASPACENORMAL:
4904 					renderer->setTexCoordIndex(stage, stage);
4905 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL);
4906 					break;
4907 				case D3DTSS_TCI_CAMERASPACEPOSITION:
4908 					renderer->setTexCoordIndex(stage, stage);
4909 					renderer->setTexGen(stage, sw::TEXGEN_POSITION);
4910 					break;
4911 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4912 					renderer->setTexCoordIndex(stage, stage);
4913 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION);
4914 					break;
4915 				case D3DTSS_TCI_SPHEREMAP:
4916 					renderer->setTexCoordIndex(stage, stage);
4917 					renderer->setTexGen(stage, sw::TEXGEN_SPHEREMAP);
4918 					break;
4919 				default:
4920 					ASSERT(false);
4921 				}
4922 				break;
4923 			case D3DTSS_BUMPENVLSCALE:
4924 				renderer->setLuminanceScale(stage, (float&)value);
4925 				break;
4926 			case D3DTSS_BUMPENVLOFFSET:
4927 				renderer->setLuminanceOffset(stage, (float&)value);
4928 				break;
4929 			case D3DTSS_TEXTURETRANSFORMFLAGS:
4930 				switch(value & ~D3DTTFF_PROJECTED)
4931 				{
4932 				case D3DTTFF_DISABLE:
4933 					renderer->setTextureTransform(stage, 0, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4934 					break;
4935 				case D3DTTFF_COUNT1:
4936 					renderer->setTextureTransform(stage, 1, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4937 					break;
4938 				case D3DTTFF_COUNT2:
4939 					renderer->setTextureTransform(stage, 2, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4940 					break;
4941 				case D3DTTFF_COUNT3:
4942 					renderer->setTextureTransform(stage, 3, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4943 					break;
4944 				case D3DTTFF_COUNT4:
4945 					renderer->setTextureTransform(stage, 4, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4946 					break;
4947 				default:
4948 					ASSERT(false);
4949 				}
4950 				break;
4951 			case D3DTSS_COLORARG0:
4952 				switch(value & D3DTA_SELECTMASK)
4953 				{
4954 				case D3DTA_CURRENT:
4955 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4956 					break;
4957 				case D3DTA_DIFFUSE:
4958 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4959 					break;
4960 				case D3DTA_SPECULAR:
4961 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4962 					break;
4963 				case D3DTA_TEMP:
4964 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP);
4965 					break;
4966 				case D3DTA_TEXTURE:
4967 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4968 					break;
4969 				case D3DTA_TFACTOR:
4970 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4971 					break;
4972 				default:
4973 					ASSERT(false);
4974 				}
4975 
4976 				switch(value & ~D3DTA_SELECTMASK)
4977 				{
4978 				case 0:
4979 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4980 					break;
4981 				case D3DTA_COMPLEMENT:
4982 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4983 					break;
4984 				case D3DTA_ALPHAREPLICATE:
4985 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4986 					break;
4987 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4988 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4989 					break;
4990 				default:
4991 					ASSERT(false);
4992 				}
4993 				break;
4994 			case D3DTSS_ALPHAARG0:
4995 				switch(value & D3DTA_SELECTMASK)
4996 				{
4997 				case D3DTA_DIFFUSE:
4998 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4999 					break;
5000 				case D3DTA_CURRENT:
5001 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
5002 					break;
5003 				case D3DTA_TEXTURE:
5004 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
5005 					break;
5006 				case D3DTA_TFACTOR:
5007 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
5008 					break;
5009 				case D3DTA_SPECULAR:
5010 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
5011 					break;
5012 				case D3DTA_TEMP:
5013 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
5014 					break;
5015 				case D3DTA_CONSTANT:
5016 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
5017 					break;
5018 				default:
5019 					ASSERT(false);
5020 				}
5021 
5022 				switch(value & ~D3DTA_SELECTMASK)
5023 				{
5024 				case 0:
5025 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
5026 					break;
5027 				case D3DTA_COMPLEMENT:
5028 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
5029 					break;
5030 				case D3DTA_ALPHAREPLICATE:
5031 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
5032 					break;
5033 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
5034 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
5035 					break;
5036 				default:
5037 					ASSERT(false);
5038 				}
5039 				break;
5040 			case D3DTSS_RESULTARG:
5041 				switch(value & D3DTA_SELECTMASK)
5042 				{
5043 				case D3DTA_CURRENT:
5044 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT);
5045 					break;
5046 				case D3DTA_TEMP:
5047 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP);
5048 					break;
5049 				default:
5050 					ASSERT(false);
5051 				}
5052 				break;
5053 			case D3DTSS_CONSTANT:
5054 				renderer->setConstantColor(stage, value);
5055 				break;
5056 			default:
5057 				ASSERT(false);
5058 			}
5059 		}
5060 		else   // stateRecorder
5061 		{
5062 			stateRecorder->setTextureStageState(stage, type, value);
5063 		}
5064 
5065 		return D3D_OK;
5066 	}
5067 
SetTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)5068 	long Direct3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
5069 	{
5070 		CriticalSection cs(this);
5071 
5072 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
5073 
5074 		if(!matrix)
5075 		{
5076 			return INVALIDCALL();
5077 		}
5078 
5079 		if(!stateRecorder)
5080 		{
5081 			this->matrix[state] = *matrix;
5082 
5083 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
5084 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
5085 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
5086 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
5087 
5088 			switch(state)
5089 			{
5090 			case D3DTS_WORLD:
5091 				renderer->setModelMatrix(M);
5092 				break;
5093 			case D3DTS_VIEW:
5094 				renderer->setViewMatrix(M);
5095 				break;
5096 			case D3DTS_PROJECTION:
5097 				renderer->setProjectionMatrix(M);
5098 				break;
5099 			case D3DTS_TEXTURE0:
5100 				renderer->setTextureMatrix(0, M);
5101 				break;
5102 			case D3DTS_TEXTURE1:
5103 				renderer->setTextureMatrix(1, M);
5104 				break;
5105 			case D3DTS_TEXTURE2:
5106 				renderer->setTextureMatrix(2, M);
5107 				break;
5108 			case D3DTS_TEXTURE3:
5109 				renderer->setTextureMatrix(3, M);
5110 				break;
5111 			case D3DTS_TEXTURE4:
5112 				renderer->setTextureMatrix(4, M);
5113 				break;
5114 			case D3DTS_TEXTURE5:
5115 				renderer->setTextureMatrix(5, M);
5116 				break;
5117 			case D3DTS_TEXTURE6:
5118 				renderer->setTextureMatrix(6, M);
5119 				break;
5120 			case D3DTS_TEXTURE7:
5121 				renderer->setTextureMatrix(7, M);
5122 				break;
5123 			default:
5124 				if(state > 256 && state < 512)
5125 				{
5126 					renderer->setModelMatrix(M, state - 256);
5127 				}
5128 				else ASSERT(false);
5129 			}
5130 		}
5131 		else   // stateRecorder
5132 		{
5133 			stateRecorder->setTransform(state, matrix);
5134 		}
5135 
5136 		return D3D_OK;
5137 	}
5138 
SetVertexDeclaration(IDirect3DVertexDeclaration9 * iVertexDeclaration)5139 	long Direct3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9 *iVertexDeclaration)
5140 	{
5141 		CriticalSection cs(this);
5142 
5143 		TRACE("IDirect3DVertexDeclaration9 *declaration = 0x%0.8p", iVertexDeclaration);
5144 
5145 		Direct3DVertexDeclaration9 *vertexDeclaration = static_cast<Direct3DVertexDeclaration9*>(iVertexDeclaration);
5146 
5147 		if(!stateRecorder)
5148 		{
5149 			if(this->vertexDeclaration == vertexDeclaration)
5150 			{
5151 				return D3D_OK;
5152 			}
5153 
5154 			if(vertexDeclaration)
5155 			{
5156 				vertexDeclaration->bind();
5157 			}
5158 
5159 			if(this->vertexDeclaration)
5160 			{
5161 				this->vertexDeclaration->unbind();
5162 			}
5163 
5164 			this->vertexDeclaration = vertexDeclaration;
5165 		}
5166 		else
5167 		{
5168 			stateRecorder->setVertexDeclaration(vertexDeclaration);
5169 		}
5170 
5171 		return D3D_OK;
5172 	}
5173 
SetVertexShader(IDirect3DVertexShader9 * iVertexShader)5174 	long Direct3DDevice9::SetVertexShader(IDirect3DVertexShader9 *iVertexShader)
5175 	{
5176 		CriticalSection cs(this);
5177 
5178 		TRACE("IDirect3DVertexShader9 *shader = 0x%0.8p", iVertexShader);
5179 
5180 		Direct3DVertexShader9 *vertexShader = static_cast<Direct3DVertexShader9*>(iVertexShader);
5181 
5182 		if(!stateRecorder)
5183 		{
5184 			if(this->vertexShader == vertexShader)
5185 			{
5186 				return D3D_OK;
5187 			}
5188 
5189 			if(vertexShader)
5190 			{
5191 				vertexShader->bind();
5192 			}
5193 
5194 			if(this->vertexShader)
5195 			{
5196 				this->vertexShader->unbind();
5197 			}
5198 
5199 			this->vertexShader = vertexShader;
5200 			vertexShaderDirty = true;
5201 		}
5202 		else
5203 		{
5204 			stateRecorder->setVertexShader(vertexShader);
5205 		}
5206 
5207 		return D3D_OK;
5208 	}
5209 
SetVertexShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)5210 	long Direct3DDevice9::SetVertexShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
5211 	{
5212 		CriticalSection cs(this);
5213 
5214 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5215 
5216 		if(!constantData)
5217 		{
5218 			return INVALIDCALL();
5219 		}
5220 
5221 		if(!stateRecorder)
5222 		{
5223 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5224 			{
5225 				vertexShaderConstantB[startRegister + i] = constantData[i];
5226 			}
5227 
5228 			vertexShaderConstantsBDirty = sw::max(startRegister + count, vertexShaderConstantsBDirty);
5229 			vertexShaderDirty = true;   // Reload DEF constants
5230 		}
5231 		else
5232 		{
5233 			stateRecorder->setVertexShaderConstantB(startRegister, constantData, count);
5234 		}
5235 
5236 		return D3D_OK;
5237 	}
5238 
SetVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)5239 	long Direct3DDevice9::SetVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
5240 	{
5241 		CriticalSection cs(this);
5242 
5243 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5244 
5245 		if(!constantData)
5246 		{
5247 			return INVALIDCALL();
5248 		}
5249 
5250 		if(!stateRecorder)
5251 		{
5252 			for(unsigned int i = 0; i < count && startRegister + i < MAX_VERTEX_SHADER_CONST; i++)
5253 			{
5254 				vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
5255 				vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
5256 				vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
5257 				vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
5258 			}
5259 
5260 			vertexShaderConstantsFDirty = sw::max(startRegister + count, vertexShaderConstantsFDirty);
5261 			vertexShaderDirty = true;   // Reload DEF constants
5262 		}
5263 		else
5264 		{
5265 			stateRecorder->setVertexShaderConstantF(startRegister, constantData, count);
5266 		}
5267 
5268 		return D3D_OK;
5269 	}
5270 
SetVertexShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)5271 	long Direct3DDevice9::SetVertexShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
5272 	{
5273 		CriticalSection cs(this);
5274 
5275 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5276 
5277 		if(!constantData)
5278 		{
5279 			return INVALIDCALL();
5280 		}
5281 
5282 		if(!stateRecorder)
5283 		{
5284 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5285 			{
5286 				vertexShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
5287 				vertexShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
5288 				vertexShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
5289 				vertexShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
5290 			}
5291 
5292 			vertexShaderConstantsIDirty = sw::max(startRegister + count, vertexShaderConstantsIDirty);
5293 			vertexShaderDirty = true;   // Reload DEF constants
5294 		}
5295 		else
5296 		{
5297 			stateRecorder->setVertexShaderConstantI(startRegister, constantData, count);
5298 		}
5299 
5300 		return D3D_OK;
5301 	}
5302 
SetViewport(const D3DVIEWPORT9 * viewport)5303 	long Direct3DDevice9::SetViewport(const D3DVIEWPORT9 *viewport)
5304 	{
5305 		CriticalSection cs(this);
5306 
5307 		TRACE("const D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
5308 
5309 		if(!viewport)   // FIXME: Check if valid
5310 		{
5311 			return INVALIDCALL();
5312 		}
5313 
5314 		if(!stateRecorder)
5315 		{
5316 			this->viewport = *viewport;
5317 		}
5318 		else
5319 		{
5320 			stateRecorder->setViewport(viewport);
5321 		}
5322 
5323 		return D3D_OK;
5324 	}
5325 
ShowCursor(int show)5326 	int Direct3DDevice9::ShowCursor(int show)
5327 	{
5328 		CriticalSection cs(this);
5329 
5330 		TRACE("int show = %d", show);
5331 
5332 		int oldValue = showCursor ? TRUE : FALSE;
5333 		showCursor = show != FALSE;
5334 
5335 		if(showCursor)
5336 		{
5337 			sw::FrameBuffer::setCursorImage(cursor);
5338 		}
5339 		else
5340 		{
5341 			sw::FrameBuffer::setCursorImage(0);
5342 		}
5343 
5344 		return oldValue;
5345 	}
5346 
StretchRect(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destSurface,const RECT * destRect,D3DTEXTUREFILTERTYPE filter)5347 	long Direct3DDevice9::StretchRect(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destSurface, const RECT *destRect, D3DTEXTUREFILTERTYPE filter)
5348 	{
5349 		CriticalSection cs(this);
5350 
5351 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p, const RECT *destRect = 0x%0.8p, D3DTEXTUREFILTERTYPE filter = %d", sourceSurface, sourceRect, destSurface, destRect, filter);
5352 
5353 		if(!sourceSurface || !destSurface || !validRectangle(sourceRect, sourceSurface) || !validRectangle(destRect, destSurface))
5354 		{
5355 			return INVALIDCALL();
5356 		}
5357 
5358 		D3DSURFACE_DESC sourceDescription;
5359 		D3DSURFACE_DESC destDescription;
5360 
5361 		sourceSurface->GetDesc(&sourceDescription);
5362 		destSurface->GetDesc(&destDescription);
5363 
5364 		if(sourceDescription.Pool != D3DPOOL_DEFAULT || destDescription.Pool != D3DPOOL_DEFAULT)
5365 		{
5366 			return INVALIDCALL();
5367 		}
5368 
5369 		Direct3DSurface9 *source = static_cast<Direct3DSurface9*>(sourceSurface);
5370 		Direct3DSurface9 *dest = static_cast<Direct3DSurface9*>(destSurface);
5371 
5372 		stretchRect(source, sourceRect, dest, destRect, filter);
5373 
5374 		return D3D_OK;
5375 	}
5376 
TestCooperativeLevel()5377 	long Direct3DDevice9::TestCooperativeLevel()
5378 	{
5379 		CriticalSection cs(this);
5380 
5381 		TRACE("void");
5382 
5383 		return D3D_OK;
5384 	}
5385 
UpdateSurface(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destinationSurface,const POINT * destPoint)5386 	long Direct3DDevice9::UpdateSurface(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destinationSurface, const POINT *destPoint)
5387 	{
5388 		CriticalSection cs(this);
5389 
5390 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint);
5391 
5392 		if(!sourceSurface || !destinationSurface)
5393 		{
5394 			return INVALIDCALL();
5395 		}
5396 
5397 		D3DSURFACE_DESC sourceDescription;
5398 		D3DSURFACE_DESC destinationDescription;
5399 
5400 		sourceSurface->GetDesc(&sourceDescription);
5401 		destinationSurface->GetDesc(&destinationDescription);
5402 
5403 		RECT sRect;
5404 		RECT dRect;
5405 
5406 		if(sourceRect)
5407 		{
5408 			sRect.left = sourceRect->left;
5409 			sRect.top = sourceRect->top;
5410 			sRect.right = sourceRect->right;
5411 			sRect.bottom = sourceRect->bottom;
5412 		}
5413 		else
5414 		{
5415 			sRect.left = 0;
5416 			sRect.top = 0;
5417 			sRect.right = sourceDescription.Width;
5418 			sRect.bottom = sourceDescription.Height;
5419 		}
5420 
5421 		if(destPoint)
5422 		{
5423 			dRect.left = destPoint->x;
5424 			dRect.top = destPoint->y;
5425 			dRect.right = destPoint->x + sRect.right - sRect.left;
5426 			dRect.bottom = destPoint->y + sRect.bottom - sRect.top;
5427 		}
5428 		else
5429 		{
5430 			dRect.left = 0;
5431 			dRect.top = 0;
5432 			dRect.right = sRect.right - sRect.left;
5433 			dRect.bottom = sRect.bottom - sRect.top;
5434 		}
5435 
5436 		if(!validRectangle(&sRect, sourceSurface) || !validRectangle(&dRect, destinationSurface))
5437 		{
5438 			return INVALIDCALL();
5439 		}
5440 
5441 		int sWidth = sRect.right - sRect.left;
5442 		int sHeight = sRect.bottom - sRect.top;
5443 
5444 		int dWidth = dRect.right - dRect.left;
5445 		int dHeight = dRect.bottom - dRect.top;
5446 
5447 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE ||
5448 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE ||
5449 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags
5450 		// destinationDescription.Pool != D3DPOOL_DEFAULT ||
5451 		   sourceDescription.Format != destinationDescription.Format)
5452 		{
5453 			return INVALIDCALL();
5454 		}
5455 
5456 		sw::Surface *source = static_cast<Direct3DSurface9*>(sourceSurface);
5457 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destinationSurface);
5458 
5459 		unsigned char *sBuffer = (unsigned char*)source->lockExternal(sRect.left, sRect.top, 0, sw::LOCK_READONLY, sw::PUBLIC);
5460 		unsigned char *dBuffer = (unsigned char*)dest->lockExternal(dRect.left, dRect.top, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
5461 		int sPitch = source->getExternalPitchB();
5462 		int dPitch = dest->getExternalPitchB();
5463 
5464 		unsigned int width;
5465 		unsigned int height;
5466 		unsigned int bytes;
5467 
5468 		switch(sourceDescription.Format)
5469 		{
5470 		case D3DFMT_DXT1:
5471 		case D3DFMT_ATI1:
5472 			width = (dWidth + 3) / 4;
5473 			height = (dHeight + 3) / 4;
5474 			bytes = width * 8;   // 64 bit per 4x4 block
5475 			break;
5476 		case D3DFMT_DXT2:
5477 		case D3DFMT_DXT3:
5478 		case D3DFMT_DXT4:
5479 		case D3DFMT_DXT5:
5480 		case D3DFMT_ATI2:
5481 			width = (dWidth + 3) / 4;
5482 			height = (dHeight + 3) / 4;
5483 			bytes = width * 16;   // 128 bit per 4x4 block
5484 			break;
5485 		default:
5486 			width = dWidth;
5487 			height = dHeight;
5488 			bytes = width * Direct3DSurface9::bytes(sourceDescription.Format);
5489 		}
5490 
5491 		if(sourceDescription.Format == D3DFMT_ATI1 || sourceDescription.Format == D3DFMT_ATI2)
5492 		{
5493 			// Make the pitch correspond to 4 rows
5494 			sPitch *= 4;
5495 			dPitch *= 4;
5496 		}
5497 
5498 		for(unsigned int y = 0; y < height; y++)
5499 		{
5500 			memcpy(dBuffer, sBuffer, bytes);
5501 
5502 			sBuffer += sPitch;
5503 			dBuffer += dPitch;
5504 		}
5505 
5506 		source->unlockExternal();
5507 		dest->unlockExternal();
5508 
5509 		return D3D_OK;
5510 	}
5511 
UpdateTexture(IDirect3DBaseTexture9 * sourceTexture,IDirect3DBaseTexture9 * destinationTexture)5512 	long Direct3DDevice9::UpdateTexture(IDirect3DBaseTexture9 *sourceTexture, IDirect3DBaseTexture9 *destinationTexture)
5513 	{
5514 		CriticalSection cs(this);
5515 
5516 		TRACE("IDirect3DBaseTexture9 *sourceTexture = 0x%0.8p, IDirect3DBaseTexture9 *destinationTexture = 0x%0.8p", sourceTexture, destinationTexture);
5517 
5518 		if(!sourceTexture || !destinationTexture)
5519 		{
5520 			return INVALIDCALL();
5521 		}
5522 
5523 		// FIXME: Check memory pools
5524 
5525 		D3DRESOURCETYPE type = sourceTexture->GetType();
5526 
5527 		if(type != destinationTexture->GetType())
5528 		{
5529 			return INVALIDCALL();
5530 		}
5531 
5532 		switch(type)
5533 		{
5534 		case D3DRTYPE_TEXTURE:
5535 			{
5536 				IDirect3DTexture9 *source;
5537 				IDirect3DTexture9 *dest;
5538 
5539 				sourceTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&source);
5540 				destinationTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&dest);
5541 
5542 				ASSERT(source && dest);
5543 
5544 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5545 				{
5546 					IDirect3DSurface9 *sourceSurface;
5547 					IDirect3DSurface9 *destinationSurface;
5548 
5549 					source->GetSurfaceLevel(level, &sourceSurface);
5550 					dest->GetSurfaceLevel(level, &destinationSurface);
5551 
5552 					UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5553 
5554 					sourceSurface->Release();
5555 					destinationSurface->Release();
5556 				}
5557 
5558 				source->Release();
5559 				dest->Release();
5560 			}
5561 			break;
5562 		case D3DRTYPE_VOLUMETEXTURE:
5563 			{
5564 				IDirect3DVolumeTexture9 *source;
5565 				IDirect3DVolumeTexture9 *dest;
5566 
5567 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&source);
5568 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&dest);
5569 
5570 				ASSERT(source && dest);
5571 
5572 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5573 				{
5574 					IDirect3DVolume9 *sourceVolume;
5575 					IDirect3DVolume9 *destinationVolume;
5576 
5577 					source->GetVolumeLevel(level, &sourceVolume);
5578 					dest->GetVolumeLevel(level, &destinationVolume);
5579 
5580 					updateVolume(sourceVolume, destinationVolume);
5581 
5582 					sourceVolume->Release();
5583 					destinationVolume->Release();
5584 				}
5585 
5586 				source->Release();
5587 				dest->Release();
5588 			}
5589 			break;
5590 		case D3DRTYPE_CUBETEXTURE:
5591 			{
5592 				IDirect3DCubeTexture9 *source;
5593 				IDirect3DCubeTexture9 *dest;
5594 
5595 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&source);
5596 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&dest);
5597 
5598 				ASSERT(source && dest);
5599 
5600 				for(int face = 0; face < 6; face++)
5601 				{
5602 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5603 					{
5604 						IDirect3DSurface9 *sourceSurface;
5605 						IDirect3DSurface9 *destinationSurface;
5606 
5607 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface);
5608 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface);
5609 
5610 						UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5611 
5612 						sourceSurface->Release();
5613 						destinationSurface->Release();
5614 					}
5615 				}
5616 
5617 				source->Release();
5618 				dest->Release();
5619 			}
5620 			break;
5621 		default:
5622 			UNIMPLEMENTED();
5623 		}
5624 
5625 		return D3D_OK;
5626 	}
5627 
ValidateDevice(unsigned long * numPasses)5628 	long Direct3DDevice9::ValidateDevice(unsigned long *numPasses)
5629 	{
5630 		CriticalSection cs(this);
5631 
5632 		TRACE("unsigned long *numPasses = 0x%0.8p", numPasses);
5633 
5634 		if(!numPasses)
5635 		{
5636 			return INVALIDCALL();
5637 		}
5638 
5639 		*numPasses = 1;
5640 
5641 		return D3D_OK;
5642 	}
5643 
getAdapterDisplayMode(unsigned int adapter,D3DDISPLAYMODE * mode)5644 	long Direct3DDevice9::getAdapterDisplayMode(unsigned int adapter, D3DDISPLAYMODE *mode)
5645 	{
5646 		return d3d9->GetAdapterDisplayMode(adapter, mode);
5647 	}
5648 
typeStride(unsigned char streamType)5649 	int Direct3DDevice9::typeStride(unsigned char streamType)
5650 	{
5651 		static int LUT[] =
5652 		{
5653 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.)
5654 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.)
5655 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.)
5656 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float
5657 			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)
5658 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte
5659 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.)
5660 			8,	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short
5661 			4,	// D3DDECLTYPE_UBYTE4N   =  8,  // Each of 4 bytes is normalized by dividing to 255.0
5662 			4,	// D3DDECLTYPE_SHORT2N   =  9,  // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
5663 			8,	// D3DDECLTYPE_SHORT4N   = 10,  // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
5664 			4,	// D3DDECLTYPE_USHORT2N  = 11,  // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
5665 			8,	// D3DDECLTYPE_USHORT4N  = 12,  // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
5666 			4,	// D3DDECLTYPE_UDEC3     = 13,  // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
5667 			4,	// D3DDECLTYPE_DEC3N     = 14,  // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
5668 			4,	// D3DDECLTYPE_FLOAT16_2 = 15,  // Two 16-bit floating point values, expanded to (value, value, 0, 1)
5669 			8,	// D3DDECLTYPE_FLOAT16_4 = 16,  // Four 16-bit floating point values
5670 			0,	// D3DDECLTYPE_UNUSED    = 17,  // When the type field in a decl is unused.
5671 		};
5672 
5673 		return LUT[streamType];
5674 	}
5675 
instanceData()5676 	bool Direct3DDevice9::instanceData()
5677 	{
5678 		ASSERT(vertexDeclaration);
5679 
5680 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5681 		unsigned int numElements;
5682 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5683 
5684 		bool instanceData = false;
5685 
5686 		for(unsigned int i = 0; i < numElements - 1; i++)
5687 		{
5688 			unsigned short stream = vertexElement[i].Stream;
5689 
5690 			if(stream != 0)
5691 			{
5692 				instanceData = instanceData || (streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA) != 0;
5693 			}
5694 		}
5695 
5696 		return instanceData;
5697 	}
5698 
bindResources(Direct3DIndexBuffer9 * indexBuffer)5699 	bool Direct3DDevice9::bindResources(Direct3DIndexBuffer9 *indexBuffer)
5700 	{
5701 		if(!bindViewport())
5702 		{
5703 			return false;   // Zero-area target region
5704 		}
5705 
5706 		bindTextures();
5707 		bindIndexBuffer(indexBuffer);
5708 		bindShaderConstants();
5709 		bindLights();
5710 
5711 		return true;
5712 	}
5713 
bindVertexStreams(int base,bool instancing,int instance)5714 	void Direct3DDevice9::bindVertexStreams(int base, bool instancing, int instance)
5715 	{
5716 		ASSERT(vertexDeclaration);
5717 
5718 		renderer->resetInputStreams(vertexDeclaration->isPreTransformed());
5719 
5720 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5721 		unsigned int numElements;
5722 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5723 
5724 		// Bind vertex data streams
5725 		for(unsigned int i = 0; i < numElements - 1; i++)
5726 		{
5727 			unsigned short stream = vertexElement[i].Stream;
5728 			unsigned short offset = vertexElement[i].Offset;
5729 			unsigned char type = vertexElement[i].Type;
5730 			unsigned char method = vertexElement[i].Method;
5731 			unsigned char usage = vertexElement[i].Usage;
5732 			unsigned char index = vertexElement[i].UsageIndex;
5733 
5734 			ASSERT(method == D3DDECLMETHOD_DEFAULT);	// FIXME: Unimplemented
5735 
5736 			if(!dataStream[stream])
5737 			{
5738 				continue;
5739 			}
5740 
5741 			Direct3DVertexBuffer9 *streamBuffer = dataStream[stream];
5742 			sw::Resource *resource = streamBuffer->getResource();
5743 			const void *buffer = ((char*)resource->data() + streamOffset[stream]) + offset;
5744 
5745 			int stride = streamStride[stream];
5746 
5747 			if(instancing && streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA)
5748 			{
5749 				int instanceFrequency = streamSourceFreq[stream] & ~D3DSTREAMSOURCE_INSTANCEDATA;
5750 				buffer = (char*)buffer + stride * (instance / instanceFrequency);
5751 
5752 				stride = 0;
5753 			}
5754 			else
5755 			{
5756 				buffer = (char*)buffer + stride * base;
5757 			}
5758 
5759 			sw::Stream attribute(resource, buffer, stride);
5760 
5761 			switch(type)
5762 			{
5763 			case D3DDECLTYPE_FLOAT1:    attribute.define(sw::STREAMTYPE_FLOAT, 1, false);  break;
5764 			case D3DDECLTYPE_FLOAT2:    attribute.define(sw::STREAMTYPE_FLOAT, 2, false);  break;
5765 			case D3DDECLTYPE_FLOAT3:    attribute.define(sw::STREAMTYPE_FLOAT, 3, false);  break;
5766 			case D3DDECLTYPE_FLOAT4:    attribute.define(sw::STREAMTYPE_FLOAT, 4, false);  break;
5767 			case D3DDECLTYPE_D3DCOLOR:  attribute.define(sw::STREAMTYPE_COLOR, 4, false);  break;
5768 			case D3DDECLTYPE_UBYTE4:    attribute.define(sw::STREAMTYPE_BYTE, 4, false);   break;
5769 			case D3DDECLTYPE_SHORT2:    attribute.define(sw::STREAMTYPE_SHORT, 2, false);  break;
5770 			case D3DDECLTYPE_SHORT4:    attribute.define(sw::STREAMTYPE_SHORT, 4, false);  break;
5771 			case D3DDECLTYPE_UBYTE4N:   attribute.define(sw::STREAMTYPE_BYTE, 4, true);    break;
5772 			case D3DDECLTYPE_SHORT2N:   attribute.define(sw::STREAMTYPE_SHORT, 2, true);   break;
5773 			case D3DDECLTYPE_SHORT4N:   attribute.define(sw::STREAMTYPE_SHORT, 4, true);   break;
5774 			case D3DDECLTYPE_USHORT2N:  attribute.define(sw::STREAMTYPE_USHORT, 2, true);  break;
5775 			case D3DDECLTYPE_USHORT4N:  attribute.define(sw::STREAMTYPE_USHORT, 4, true);  break;
5776 			case D3DDECLTYPE_UDEC3:     attribute.define(sw::STREAMTYPE_UDEC3, 3, false);  break;
5777 			case D3DDECLTYPE_DEC3N:     attribute.define(sw::STREAMTYPE_DEC3N, 3, true);   break;
5778 			case D3DDECLTYPE_FLOAT16_2: attribute.define(sw::STREAMTYPE_HALF, 2, false);   break;
5779 			case D3DDECLTYPE_FLOAT16_4: attribute.define(sw::STREAMTYPE_HALF, 4, false);   break;
5780 			case D3DDECLTYPE_UNUSED:    attribute.defaults();                              break;
5781 			default:
5782 				ASSERT(false);
5783 			}
5784 
5785 			if(vertexShader)
5786 			{
5787 				const sw::VertexShader *shader = vertexShader->getVertexShader();
5788 
5789 				if(!vertexDeclaration->isPreTransformed())
5790 				{
5791 					for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
5792 					{
5793 						const sw::Shader::Semantic& input = shader->getInput(i);
5794 						if((usage == input.usage) && (index == input.index))
5795 						{
5796 							renderer->setInputStream(i, attribute);
5797 
5798 							break;
5799 						}
5800 					}
5801 				}
5802 				else   // Bind directly to the output
5803 				{
5804 					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
5805 					{
5806 						const sw::Shader::Semantic& output = shader->getOutput(i, 0);
5807 						if(((usage == output.usage) || (usage == D3DDECLUSAGE_POSITIONT && output.usage == D3DDECLUSAGE_POSITION)) &&
5808 						   (index == output.index))
5809 						{
5810 							renderer->setInputStream(i, attribute);
5811 
5812 							break;
5813 						}
5814 					}
5815 				}
5816 			}
5817 			else
5818 			{
5819 				switch(usage)
5820 				{
5821 				case D3DDECLUSAGE_POSITION:     renderer->setInputStream(sw::Position, attribute);                                       break;
5822 				case D3DDECLUSAGE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);                                    break;
5823 				case D3DDECLUSAGE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute.define(sw::STREAMTYPE_INDICES, 1)); break;
5824 				case D3DDECLUSAGE_NORMAL:       renderer->setInputStream(sw::Normal, attribute.define(sw::STREAMTYPE_FLOAT, 3));         break;
5825 				case D3DDECLUSAGE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute.define(sw::STREAMTYPE_FLOAT, 1));      break;
5826 				case D3DDECLUSAGE_TEXCOORD:     renderer->setInputStream(sw::TexCoord0 + index, attribute);                              break;
5827 				case D3DDECLUSAGE_TANGENT:      /* Ignored */                                                                            break;
5828 				case D3DDECLUSAGE_BINORMAL:     /* Ignored */                                                                            break;
5829 				case D3DDECLUSAGE_TESSFACTOR:   UNIMPLEMENTED();                                                                         break;
5830 				case D3DDECLUSAGE_POSITIONT:    renderer->setInputStream(sw::PositionT, attribute.define(sw::STREAMTYPE_FLOAT, 4));      break;
5831 				case D3DDECLUSAGE_COLOR:        renderer->setInputStream(sw::Color0 + index, attribute.define(sw::STREAMTYPE_COLOR, 4)); break;
5832 				case D3DDECLUSAGE_FOG:          /* Ignored */                                                                            break;
5833 				case D3DDECLUSAGE_DEPTH:        /* Ignored */                                                                            break;
5834 				case D3DDECLUSAGE_SAMPLE:       UNIMPLEMENTED();                                                                         break;
5835 				default:
5836 					ASSERT(false);
5837 				}
5838 			}
5839 		}
5840 	}
5841 
bindIndexBuffer(Direct3DIndexBuffer9 * indexBuffer)5842 	void Direct3DDevice9::bindIndexBuffer(Direct3DIndexBuffer9 *indexBuffer)
5843 	{
5844 		sw::Resource *resource = 0;
5845 
5846 		if(indexBuffer)
5847 		{
5848 			resource = indexBuffer->getResource();
5849 		}
5850 
5851 		renderer->setIndexBuffer(resource);
5852 	}
5853 
bindShaderConstants()5854 	void Direct3DDevice9::bindShaderConstants()
5855 	{
5856 		if(pixelShaderDirty)
5857 		{
5858 			if(pixelShader)
5859 			{
5860 				if(pixelShaderConstantsBDirty)
5861 				{
5862 					renderer->setPixelShaderConstantB(0, pixelShaderConstantB, pixelShaderConstantsBDirty);
5863 				}
5864 
5865 				if(pixelShaderConstantsFDirty)
5866 				{
5867 					renderer->setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
5868 				}
5869 
5870 				if(pixelShaderConstantsIDirty)
5871 				{
5872 					renderer->setPixelShaderConstantI(0, pixelShaderConstantI[0], pixelShaderConstantsIDirty);
5873 				}
5874 
5875 				renderer->setPixelShader(pixelShader->getPixelShader());   // Loads shader constants set with DEF
5876 				pixelShaderConstantsBDirty = pixelShader->getPixelShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty
5877 				pixelShaderConstantsFDirty = pixelShader->getPixelShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty
5878 				pixelShaderConstantsIDirty = pixelShader->getPixelShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty
5879 			}
5880 			else
5881 			{
5882 				renderer->setPixelShader(0);
5883 			}
5884 
5885 			pixelShaderDirty = false;
5886 		}
5887 
5888 		if(vertexShaderDirty)
5889 		{
5890 			if(vertexShader)
5891 			{
5892 				if(vertexShaderConstantsBDirty)
5893 				{
5894 					renderer->setVertexShaderConstantB(0, vertexShaderConstantB, vertexShaderConstantsBDirty);
5895 				}
5896 
5897 				if(vertexShaderConstantsFDirty)
5898 				{
5899 					renderer->setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
5900 				}
5901 
5902 				if(vertexShaderConstantsIDirty)
5903 				{
5904 					renderer->setVertexShaderConstantI(0, vertexShaderConstantI[0], vertexShaderConstantsIDirty);
5905 				}
5906 
5907 				renderer->setVertexShader(vertexShader->getVertexShader());   // Loads shader constants set with DEF
5908 				vertexShaderConstantsBDirty = vertexShader->getVertexShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty
5909 				vertexShaderConstantsFDirty = vertexShader->getVertexShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty
5910 				vertexShaderConstantsIDirty = vertexShader->getVertexShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty
5911 			}
5912 			else
5913 			{
5914 				renderer->setVertexShader(0);
5915 			}
5916 
5917 			vertexShaderDirty = false;
5918 		}
5919 	}
5920 
bindLights()5921 	void Direct3DDevice9::bindLights()
5922 	{
5923 		if(!lightsDirty) return;
5924 
5925 		Lights::iterator i = light.begin();
5926 		int active = 0;
5927 
5928 		// Set and enable renderer lights
5929 		while(active < 8)
5930 		{
5931 			while(i != light.end() && !i->second.enable)
5932 			{
5933 				i++;
5934 			}
5935 
5936 			if(i == light.end())
5937 			{
5938 				break;
5939 			}
5940 
5941 			const Light &l = i->second;
5942 
5943 			sw::Point position(l.Position.x, l.Position.y, l.Position.z);
5944 			sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a);
5945 			sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a);
5946 			sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a);
5947 			sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z);
5948 
5949 			renderer->setLightDiffuse(active, diffuse);
5950 			renderer->setLightSpecular(active, specular);
5951 			renderer->setLightAmbient(active, ambient);
5952 
5953 			if(l.Type == D3DLIGHT_DIRECTIONAL)
5954 			{
5955 				// FIXME: Unsupported, make it a positional light far away without falloff
5956 				renderer->setLightPosition(active, -1e10f * direction);
5957 				renderer->setLightRange(active, l.Range);
5958 				renderer->setLightAttenuation(active, 1, 0, 0);
5959 			}
5960 			else if(l.Type == D3DLIGHT_SPOT)
5961 			{
5962 				// FIXME: Unsupported, make it a positional light
5963 				renderer->setLightPosition(active, position);
5964 				renderer->setLightRange(active, l.Range);
5965 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
5966 			}
5967 			else
5968 			{
5969 				renderer->setLightPosition(active, position);
5970 				renderer->setLightRange(active, l.Range);
5971 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
5972 			}
5973 
5974 			renderer->setLightEnable(active, true);
5975 
5976 			active++;
5977 			i++;
5978 		}
5979 
5980 		// Remaining lights are disabled
5981 		while(active < 8)
5982 		{
5983 			renderer->setLightEnable(active, false);
5984 
5985 			active++;
5986 		}
5987 
5988 		lightsDirty = false;
5989 	}
5990 
bindViewport()5991 	bool Direct3DDevice9::bindViewport()
5992 	{
5993 		if(viewport.Width <= 0 || viewport.Height <= 0)
5994 		{
5995 			return false;
5996 		}
5997 
5998 		if(scissorEnable)
5999 		{
6000 			if(scissorRect.left >= scissorRect.right || scissorRect.top >= scissorRect.bottom)
6001 			{
6002 				return false;
6003 			}
6004 
6005 			sw::Rect scissor;
6006 			scissor.x0 = scissorRect.left;
6007 			scissor.x1 = scissorRect.right;
6008 			scissor.y0 = scissorRect.top;
6009 			scissor.y1 = scissorRect.bottom;
6010 
6011 			renderer->setScissor(scissor);
6012 		}
6013 		else
6014 		{
6015 			sw::Rect scissor;
6016 			scissor.x0 = viewport.X;
6017 			scissor.x1 = viewport.X + viewport.Width;
6018 			scissor.y0 = viewport.Y;
6019 			scissor.y1 = viewport.Y + viewport.Height;
6020 
6021 			renderer->setScissor(scissor);
6022 		}
6023 
6024 		sw::Viewport view;
6025 		view.x0 = (float)viewport.X;
6026 		view.y0 = (float)viewport.Y + viewport.Height;
6027 		view.width = (float)viewport.Width;
6028 		view.height = -(float)viewport.Height;
6029 		view.minZ = viewport.MinZ;
6030 		view.maxZ = viewport.MaxZ;
6031 
6032 		renderer->setViewport(view);
6033 
6034 		return true;
6035 	}
6036 
bindTextures()6037 	void Direct3DDevice9::bindTextures()
6038 	{
6039 		for(int sampler = 0; sampler < 16 + 4; sampler++)
6040 		{
6041 			Direct3DBaseTexture9 *baseTexture = texture[sampler];
6042 
6043 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX;
6044 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group
6045 
6046 			bool textureUsed = false;
6047 
6048 			if(type == sw::SAMPLER_PIXEL && pixelShader)
6049 			{
6050 				textureUsed = pixelShader->getPixelShader()->usesSampler(index);
6051 			}
6052 			else if(type == sw::SAMPLER_VERTEX && vertexShader)
6053 			{
6054 				textureUsed = vertexShader->getVertexShader()->usesSampler(index);
6055 			}
6056 			else
6057 			{
6058 				textureUsed = true;   // FIXME: Check fixed-function use?
6059 			}
6060 
6061 			sw::Resource *resource = 0;
6062 
6063 			if(baseTexture && textureUsed)
6064 			{
6065 				resource = baseTexture->getResource();
6066 			}
6067 
6068 			renderer->setTextureResource(sampler, resource);
6069 
6070 			if(baseTexture && textureUsed)
6071 			{
6072 				baseTexture->GenerateMipSubLevels();
6073 			}
6074 
6075 			if(baseTexture && textureUsed)
6076 			{
6077 				int levelCount = baseTexture->getInternalLevelCount();
6078 
6079 				int textureLOD = baseTexture->GetLOD();
6080 				int samplerLOD = samplerState[sampler][D3DSAMP_MAXMIPLEVEL];
6081 				int LOD = textureLOD > samplerLOD ? textureLOD : samplerLOD;
6082 
6083 				if(samplerState[sampler][D3DSAMP_MIPFILTER] == D3DTEXF_NONE)
6084 				{
6085 					LOD = 0;
6086 				}
6087 
6088 				switch(baseTexture->GetType())
6089 				{
6090 				case D3DRTYPE_TEXTURE:
6091 					{
6092 						Direct3DTexture9 *texture = dynamic_cast<Direct3DTexture9*>(baseTexture);
6093 						Direct3DSurface9 *surface;
6094 
6095 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6096 						{
6097 							int surfaceLevel = mipmapLevel;
6098 
6099 							if(surfaceLevel < LOD)
6100 							{
6101 								surfaceLevel = LOD;
6102 							}
6103 
6104 							if(surfaceLevel < 0)
6105 							{
6106 								surfaceLevel = 0;
6107 							}
6108 							else if(surfaceLevel >= levelCount)
6109 							{
6110 								surfaceLevel = levelCount - 1;
6111 							}
6112 
6113 							surface = texture->getInternalSurfaceLevel(surfaceLevel);
6114 							renderer->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);
6115 						}
6116 					}
6117 					break;
6118 				case D3DRTYPE_CUBETEXTURE:
6119 					for(int face = 0; face < 6; face++)
6120 					{
6121 						Direct3DCubeTexture9 *cubeTexture = dynamic_cast<Direct3DCubeTexture9*>(baseTexture);
6122 						Direct3DSurface9 *surface;
6123 
6124 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6125 						{
6126 							int surfaceLevel = mipmapLevel;
6127 
6128 							if(surfaceLevel < LOD)
6129 							{
6130 								surfaceLevel = LOD;
6131 							}
6132 
6133 							if(surfaceLevel < 0)
6134 							{
6135 								surfaceLevel = 0;
6136 							}
6137 							else if(surfaceLevel >= levelCount)
6138 							{
6139 								surfaceLevel = levelCount - 1;
6140 							}
6141 
6142 							surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel);
6143 							renderer->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
6144 						}
6145 					}
6146 					break;
6147 				case D3DRTYPE_VOLUMETEXTURE:
6148 					{
6149 						Direct3DVolumeTexture9 *volumeTexture = dynamic_cast<Direct3DVolumeTexture9*>(baseTexture);
6150 						Direct3DVolume9 *volume;
6151 
6152 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6153 						{
6154 							int surfaceLevel = mipmapLevel;
6155 
6156 							if(surfaceLevel < LOD)
6157 							{
6158 								surfaceLevel = LOD;
6159 							}
6160 
6161 							if(surfaceLevel < 0)
6162 							{
6163 								surfaceLevel = 0;
6164 							}
6165 							else if(surfaceLevel >= levelCount)
6166 							{
6167 								surfaceLevel = levelCount - 1;
6168 							}
6169 
6170 							volume = volumeTexture->getInternalVolumeLevel(surfaceLevel);
6171 							renderer->setTextureLevel(sampler, 0, mipmapLevel, volume, sw::TEXTURE_3D);
6172 						}
6173 					}
6174 					break;
6175 				default:
6176 					UNIMPLEMENTED();
6177 				}
6178 			}
6179 			else
6180 			{
6181 				renderer->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
6182 			}
6183 		}
6184 	}
6185 
isRecording() const6186 	bool Direct3DDevice9::isRecording() const
6187 	{
6188 		return stateRecorder != 0;
6189 	}
6190 
setOcclusionEnabled(bool enable)6191 	void Direct3DDevice9::setOcclusionEnabled(bool enable)
6192 	{
6193 		renderer->setOcclusionEnabled(enable);
6194 	}
6195 
removeQuery(sw::Query * query)6196 	void Direct3DDevice9::removeQuery(sw::Query *query)
6197 	{
6198 		renderer->removeQuery(query);
6199 	}
6200 
addQuery(sw::Query * query)6201 	void Direct3DDevice9::addQuery(sw::Query *query)
6202 	{
6203 		renderer->addQuery(query);
6204 	}
6205 
stretchRect(Direct3DSurface9 * source,const RECT * sourceRect,Direct3DSurface9 * dest,const RECT * destRect,D3DTEXTUREFILTERTYPE filter)6206 	void Direct3DDevice9::stretchRect(Direct3DSurface9 *source, const RECT *sourceRect, Direct3DSurface9 *dest, const RECT *destRect, D3DTEXTUREFILTERTYPE filter)
6207 	{
6208 		D3DSURFACE_DESC sourceDescription;
6209 		D3DSURFACE_DESC destDescription;
6210 
6211 		source->GetDesc(&sourceDescription);
6212 		dest->GetDesc(&destDescription);
6213 
6214 		int sWidth = source->getWidth();
6215 		int sHeight = source->getHeight();
6216 		int dWidth = dest->getWidth();
6217 		int dHeight = dest->getHeight();
6218 
6219 		sw::Rect sRect(0, 0, sWidth, sHeight);
6220 		sw::Rect dRect(0, 0, dWidth, dHeight);
6221 
6222 		if(sourceRect)
6223 		{
6224 			sRect.x0 = sourceRect->left;
6225 			sRect.y0 = sourceRect->top;
6226 			sRect.x1 = sourceRect->right;
6227 			sRect.y1 = sourceRect->bottom;
6228 		}
6229 
6230 		if(destRect)
6231 		{
6232 			dRect.x0 = destRect->left;
6233 			dRect.y0 = destRect->top;
6234 			dRect.x1 = destRect->right;
6235 			dRect.y1 = destRect->bottom;
6236 		}
6237 
6238 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
6239 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
6240 		bool depthStencil = (sourceDescription.Usage & D3DUSAGE_DEPTHSTENCIL) == D3DUSAGE_DEPTHSTENCIL;
6241 		bool alpha0xFF = false;
6242 
6243 		if((sourceDescription.Format == D3DFMT_A8R8G8B8 && destDescription.Format == D3DFMT_X8R8G8B8) ||
6244 		   (sourceDescription.Format == D3DFMT_X8R8G8B8 && destDescription.Format == D3DFMT_A8R8G8B8))
6245 		{
6246 			equalFormats = true;
6247 			alpha0xFF = true;
6248 		}
6249 
6250 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
6251 		{
6252 			if(source->hasDepth())
6253 			{
6254 				byte *sourceBuffer = (byte*)source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6255 				byte *destBuffer = (byte*)dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
6256 
6257 				unsigned int width = source->getWidth();
6258 				unsigned int height = source->getHeight();
6259 				unsigned int pitch = source->getInternalPitchB();
6260 
6261 				for(unsigned int y = 0; y < height; y++)
6262 				{
6263 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
6264 
6265 					sourceBuffer += pitch;
6266 					destBuffer += pitch;
6267 				}
6268 
6269 				source->unlockInternal();
6270 				dest->unlockInternal();
6271 			}
6272 
6273 			if(source->hasStencil())
6274 			{
6275 				byte *sourceBuffer = (byte*)source->lockStencil(0, 0, 0, sw::PUBLIC);
6276 				byte *destBuffer = (byte*)dest->lockStencil(0, 0, 0, sw::PUBLIC);
6277 
6278 				unsigned int width = source->getWidth();
6279 				unsigned int height = source->getHeight();
6280 				unsigned int pitch = source->getStencilPitchB();
6281 
6282 				for(unsigned int y = 0; y < height; y++)
6283 				{
6284 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
6285 
6286 					sourceBuffer += pitch;
6287 					destBuffer += pitch;
6288 				}
6289 
6290 				source->unlockStencil();
6291 				dest->unlockStencil();
6292 			}
6293 		}
6294 		else if(!scaling && equalFormats)
6295 		{
6296 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6297 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, sw::LOCK_READWRITE, sw::PUBLIC);
6298 			unsigned int sourcePitch = source->getInternalPitchB();
6299 			unsigned int destPitch = dest->getInternalPitchB();
6300 
6301 			unsigned int width = dRect.x1 - dRect.x0;
6302 			unsigned int height = dRect.y1 - dRect.y0;
6303 			unsigned int bytes = width * sw::Surface::bytes(source->getInternalFormat());
6304 
6305 			for(unsigned int y = 0; y < height; y++)
6306 			{
6307 				memcpy(destBytes, sourceBytes, bytes);
6308 
6309 				if(alpha0xFF)
6310 				{
6311 					for(unsigned int x = 0; x < width; x++)
6312 					{
6313 						destBytes[4 * x + 3] = 0xFF;
6314 					}
6315 				}
6316 
6317 				sourceBytes += sourcePitch;
6318 				destBytes += destPitch;
6319 			}
6320 
6321 			source->unlockInternal();
6322 			dest->unlockInternal();
6323 		}
6324 		else
6325 		{
6326 			sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, 0);
6327 			renderer->blit(source, sRectF, dest, dRect, filter >= D3DTEXF_LINEAR);
6328 		}
6329 	}
6330 
updateVolume(IDirect3DVolume9 * sourceVolume,IDirect3DVolume9 * destinationVolume)6331 	long Direct3DDevice9::updateVolume(IDirect3DVolume9 *sourceVolume, IDirect3DVolume9 *destinationVolume)
6332 	{
6333 		TRACE("IDirect3DVolume9 *sourceVolume = 0x%0.8p, IDirect3DVolume9 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume);
6334 
6335 		if(!sourceVolume || !destinationVolume)
6336 		{
6337 			return INVALIDCALL();
6338 		}
6339 
6340 		D3DVOLUME_DESC sourceDescription;
6341 		D3DVOLUME_DESC destinationDescription;
6342 
6343 		sourceVolume->GetDesc(&sourceDescription);
6344 		destinationVolume->GetDesc(&destinationDescription);
6345 
6346 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||
6347 		   destinationDescription.Pool != D3DPOOL_DEFAULT ||
6348 		   sourceDescription.Format != destinationDescription.Format ||
6349 		   sourceDescription.Width  != destinationDescription.Width ||
6350 		   sourceDescription.Height != destinationDescription.Height ||
6351 		   sourceDescription.Depth  != destinationDescription.Depth)
6352 		{
6353 			return INVALIDCALL();
6354 		}
6355 
6356 		sw::Surface *source = static_cast<Direct3DVolume9*>(sourceVolume);
6357 		sw::Surface *dest = static_cast<Direct3DVolume9*>(destinationVolume);
6358 
6359 		if(source->getExternalPitchB() != dest->getExternalPitchB() ||
6360 		   source->getExternalSliceB() != dest->getExternalSliceB())
6361 		{
6362 			UNIMPLEMENTED();
6363 		}
6364 
6365 		void *sBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6366 		void *dBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
6367 
6368 		memcpy(dBuffer, sBuffer, source->getExternalSliceB() * sourceDescription.Depth);
6369 
6370 		source->unlockExternal();
6371 		dest->unlockExternal();
6372 
6373 		return D3D_OK;
6374 	}
6375 
validRectangle(const RECT * rect,IDirect3DSurface9 * surface)6376 	bool Direct3DDevice9::validRectangle(const RECT *rect, IDirect3DSurface9 *surface)
6377 	{
6378 		if(!rect)
6379 		{
6380 			return true;
6381 		}
6382 
6383 		if(rect->right <= rect->left || rect->bottom <= rect->top)
6384 		{
6385 			return false;
6386 		}
6387 
6388 		if(rect->left < 0 || rect->top < 0)
6389 		{
6390 			return false;
6391 		}
6392 
6393 		D3DSURFACE_DESC description;
6394 		surface->GetDesc(&description);
6395 
6396 		if(rect->right > (int)description.Width || rect->bottom > (int)description.Height)
6397 		{
6398 			return false;
6399 		}
6400 
6401 		return true;
6402 	}
6403 
configureFPU()6404 	void Direct3DDevice9::configureFPU()
6405 	{
6406 	//	_controlfp(_PC_24, _MCW_PC);     // Single-precision
6407 		_controlfp(_MCW_EM, _MCW_EM);    // Mask all exceptions
6408 		_controlfp(_RC_NEAR, _MCW_RC);   // Round to nearest
6409 	}
6410 }
6411