• 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 "Direct3DDevice8.hpp"
16 
17 #include "Direct3D8.hpp"
18 #include "Direct3DSurface8.hpp"
19 #include "Direct3DIndexBuffer8.hpp"
20 #include "Direct3DVertexBuffer8.hpp"
21 #include "Direct3DTexture8.hpp"
22 #include "Direct3DVolumeTexture8.hpp"
23 #include "Direct3DCubeTexture8.hpp"
24 #include "Direct3DSwapChain8.hpp"
25 #include "Direct3DPixelShader8.hpp"
26 #include "Direct3DVertexShader8.hpp"
27 #include "Direct3DVolume8.hpp"
28 
29 #include "Debug.hpp"
30 #include "Capabilities.hpp"
31 #include "Renderer.hpp"
32 #include "Config.hpp"
33 #include "FrameBuffer.hpp"
34 #include "Clipper.hpp"
35 #include "Configurator.hpp"
36 #include "Timer.hpp"
37 #include "Resource.hpp"
38 
39 #include <assert.h>
40 
41 bool localShaderConstants = false;
42 
43 namespace D3D8
44 {
FtoDW(float f)45 	inline unsigned long FtoDW(float f)   // FIXME: Deprecate
46 	{
47 		return (unsigned long&)f;
48 	}
49 
Direct3DDevice8(const HINSTANCE instance,Direct3D8 * d3d8,unsigned int adapter,D3DDEVTYPE deviceType,HWND focusWindow,unsigned long behaviourFlags,D3DPRESENT_PARAMETERS * presentParameters)50 	Direct3DDevice8::Direct3DDevice8(const HINSTANCE instance, Direct3D8 *d3d8, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), d3d8(d3d8), adapter(adapter), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags), presentParameters(*presentParameters)
51 	{
52 		init = true;
53 		recordState = false;
54 
55 		d3d8->AddRef();
56 
57 		context = new sw::Context();
58 		renderer = new sw::Renderer(context, sw::Direct3D, false);
59 
60 		swapChain.push_back(0);
61 		depthStencil = 0;
62 		renderTarget = 0;
63 
64 		for(int i = 0; i < 8; i++)
65 		{
66 			texture[i] = 0;
67 		}
68 
69 		cursor = 0;
70 		unsigned char one[32 * 32 / sizeof(unsigned char)];
71 		memset(one, 0xFFFFFFFF, sizeof(one));
72 		unsigned char zero[32 * 32 / sizeof(unsigned char)] = {0};
73 		nullCursor = CreateCursor(instance, 0, 0, 32, 32, one, zero);
74 		win32Cursor = GetCursor();
75 
76 		Reset(presentParameters);
77 
78 		pixelShader.push_back(0);   // pixelShader[0] = 0
79 		vertexShader.push_back(0);   // vertexShader[0] = 0
80 		vertexShaderHandle = 0;
81 		pixelShaderHandle = 0;
82 
83 		lightsDirty = true;
84 
85 		for(int i = 0; i < 16; i++)
86 		{
87 			dataStream[i] = 0;
88 			streamStride[i] = 0;
89 		}
90 
91 		indexData = 0;
92 		baseVertexIndex = 0;
93 		declaration = 0;
94 		FVF = 0;
95 
96 		D3DMATERIAL8 material;
97 
98 		material.Diffuse.r = 1.0f;
99 		material.Diffuse.g = 1.0f;
100 		material.Diffuse.b = 1.0f;
101 		material.Diffuse.a = 0.0f;
102 		material.Ambient.r = 0.0f;
103 		material.Ambient.g = 0.0f;
104 		material.Ambient.b = 0.0f;
105 		material.Ambient.a = 0.0f;
106 		material.Emissive.r = 0.0f;
107 		material.Emissive.g = 0.0f;
108 		material.Emissive.b = 0.0f;
109 		material.Emissive.a = 0.0f;
110 		material.Specular.r = 0.0f;
111 		material.Specular.g = 0.0f;
112 		material.Specular.b = 0.0f;
113 		material.Specular.a = 0.0f;
114 		material.Power = 0.0f;
115 
116 		SetMaterial(&material);
117 
118 		D3DMATRIX identity = {1, 0, 0, 0,
119 			                  0, 1, 0, 0,
120 							  0, 0, 1, 0,
121 							  0, 0, 0, 1};
122 
123 		SetTransform(D3DTS_VIEW, &identity);
124 		SetTransform(D3DTS_PROJECTION, &identity);
125 		SetTransform(D3DTS_TEXTURE0, &identity);
126 		SetTransform(D3DTS_TEXTURE1, &identity);
127 		SetTransform(D3DTS_TEXTURE2, &identity);
128 		SetTransform(D3DTS_TEXTURE3, &identity);
129 		SetTransform(D3DTS_TEXTURE4, &identity);
130 		SetTransform(D3DTS_TEXTURE5, &identity);
131 		SetTransform(D3DTS_TEXTURE6, &identity);
132 		SetTransform(D3DTS_TEXTURE7, &identity);
133 
134 		for(int i = 0; i < 12; i++)
135 		{
136 			SetTransform(D3DTS_WORLDMATRIX(i), &identity);
137 		}
138 
139 		for(int i = 0; i < 8; i++)
140 		{
141 			float zero[4] = {0, 0, 0, 0};
142 
143 			SetPixelShaderConstant(i, zero, 1);
144 		}
145 
146 		for(int i = 0; i < 256; i++)
147 		{
148 			float zero[4] = {0, 0, 0, 0};
149 
150 			SetVertexShaderConstant(i, zero, 1);
151 		}
152 
153 		init = false;
154 
155 		if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE))
156 		{
157 			configureFPU();
158 		}
159 	}
160 
~Direct3DDevice8()161 	Direct3DDevice8::~Direct3DDevice8()
162 	{
163 		delete renderer;
164 		renderer = 0;
165 		delete context;
166 		context = 0;
167 
168 		d3d8->Release();
169 		d3d8 = 0;
170 
171 		for(unsigned int i = 0; i < swapChain.size(); i++)
172 		{
173 			if(swapChain[i])
174 			{
175 				swapChain[i]->unbind();
176 				swapChain[i] = 0;
177 			}
178 		}
179 
180 		if(depthStencil)
181 		{
182 			depthStencil->unbind();
183 			depthStencil = 0;
184 		}
185 
186 		if(renderTarget)
187 		{
188 			renderTarget->unbind();
189 			renderTarget = 0;
190 		}
191 
192 		for(int i = 0; i < 8; i++)
193 		{
194 			if(texture[i])
195 			{
196 				texture[i]->unbind();
197 				texture[i] = 0;
198 			}
199 		}
200 
201 		for(int i = 0; i < 16; i++)
202 		{
203 			if(dataStream[i])
204 			{
205 				dataStream[i]->unbind();
206 				dataStream[i] = 0;
207 			}
208 		}
209 
210 		if(indexData)
211 		{
212 			indexData->unbind();
213 			indexData = 0;
214 		}
215 
216 		for(unsigned int i = 0; i < pixelShader.size(); i++)
217 		{
218 			if(pixelShader[i])
219 			{
220 				pixelShader[i]->unbind();
221 				pixelShader[i] = 0;
222 			}
223 		}
224 
225 		for(unsigned int i = 0; i < vertexShader.size(); i++)
226 		{
227 			if(vertexShader[i])
228 			{
229 				vertexShader[i]->unbind();
230 				vertexShader[i] = 0;
231 			}
232 		}
233 
234 		for(unsigned int i = 0; i < stateRecorder.size(); i++)
235 		{
236 			if(stateRecorder[i])
237 			{
238 				stateRecorder[i]->unbind();
239 				stateRecorder[i] = 0;
240 			}
241 		}
242 
243 		palette.clear();
244 
245 		delete cursor;
246 		DestroyCursor(nullCursor);
247 	}
248 
QueryInterface(const IID & iid,void ** object)249 	long Direct3DDevice8::QueryInterface(const IID &iid, void **object)
250 	{
251 		TRACE("");
252 
253 		if(iid == IID_IDirect3DDevice8 ||
254 		   iid == IID_IUnknown)
255 		{
256 			AddRef();
257 			*object = this;
258 
259 			return S_OK;
260 		}
261 
262 		*object = 0;
263 
264 		return NOINTERFACE(iid);
265 	}
266 
AddRef()267 	unsigned long Direct3DDevice8::AddRef()
268 	{
269 		TRACE("");
270 
271 		return Unknown::AddRef();
272 	}
273 
Release()274 	unsigned long Direct3DDevice8::Release()
275 	{
276 		TRACE("");
277 
278 		return Unknown::Release();
279 	}
280 
ApplyStateBlock(unsigned long token)281 	long Direct3DDevice8::ApplyStateBlock(unsigned long token)
282 	{
283 		TRACE("");
284 
285 		stateRecorder[token]->Apply();
286 
287 		return D3D_OK;
288 	}
289 
BeginScene()290 	long Direct3DDevice8::BeginScene()
291 	{
292 		TRACE("");
293 
294 		return D3D_OK;
295 	}
296 
BeginStateBlock()297 	long Direct3DDevice8::BeginStateBlock()
298 	{
299 		TRACE("");
300 
301 		recordState = true;
302 		Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, (D3DSTATEBLOCKTYPE)0);
303 		stateBlock->bind();
304 		stateRecorder.push_back(stateBlock);
305 
306 		return D3D_OK;
307 	}
308 
CaptureStateBlock(unsigned long token)309 	long Direct3DDevice8::CaptureStateBlock(unsigned long token)
310 	{
311 		TRACE("");
312 
313 		stateRecorder[token]->Capture();
314 
315 		return D3D_OK;
316 	}
317 
Clear(unsigned long count,const D3DRECT * rects,unsigned long flags,unsigned long color,float z,unsigned long stencil)318 	long Direct3DDevice8::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil)
319 	{
320 		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);
321 
322 		if(!rects && count != 0)
323 		{
324 			return INVALIDCALL();
325 		}
326 
327 		if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil)
328 		{
329 			return INVALIDCALL();
330 		}
331 
332 		if(flags & D3DCLEAR_STENCIL)   // Check for stencil component
333 		{
334 			D3DSURFACE_DESC description;
335 			depthStencil->GetDesc(&description);
336 
337 			switch(description.Format)
338 			{
339 			case D3DFMT_D15S1:
340 			case D3DFMT_D24S8:
341 			case D3DFMT_D24X8:
342 			case D3DFMT_D24X4S4:
343 				break;
344 			case D3DFMT_D16_LOCKABLE:
345 			case D3DFMT_D32:
346 			case D3DFMT_D16:
347 				return INVALIDCALL();
348 			default:
349 				ASSERT(false);
350 			}
351 		}
352 
353 		if(!rects)
354 		{
355 			count = 1;
356 
357 			D3DRECT rect;
358 			rect.x1 = viewport.X;
359 			rect.x2 = viewport.X + viewport.Width;
360 			rect.y1 = viewport.Y;
361 			rect.y2 = viewport.Y + viewport.Height;
362 
363 			rects = &rect;
364 		}
365 
366 		for(unsigned int i = 0; i < count; i++)
367 		{
368 			sw::Rect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
369 
370 			clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height);
371 
372 			if(flags & D3DCLEAR_TARGET)
373 			{
374 				if(renderTarget)
375 				{
376 					D3DSURFACE_DESC description;
377 					renderTarget->GetDesc(&description);
378 
379 					float rgba[4];
380 					rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000;
381 					rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00;
382 					rgba[2] = (float)(color & 0x000000FF) / 0x000000FF;
383 					rgba[3] = (float)(color & 0xFF000000) / 0xFF000000;
384 
385 					renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget, clearRect, 0xF);
386 				}
387 			}
388 
389 			if(flags & D3DCLEAR_ZBUFFER)
390 			{
391 				z = sw::clamp01(z);
392 				depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
393 			}
394 
395 			if(flags & D3DCLEAR_STENCIL)
396 			{
397 				depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
398 			}
399 		}
400 
401 		return D3D_OK;
402 	}
403 
CopyRects(IDirect3DSurface8 * sourceSurface,const RECT * sourceRectsArray,unsigned int rects,IDirect3DSurface8 * destinationSurface,const POINT * destPointsArray)404 	long Direct3DDevice8::CopyRects(IDirect3DSurface8 *sourceSurface, const RECT *sourceRectsArray, unsigned int rects, IDirect3DSurface8 *destinationSurface, const POINT *destPointsArray)
405 	{
406 		TRACE("");
407 
408 		if(!sourceSurface || !destinationSurface)
409 		{
410 			return INVALIDCALL();
411 		}
412 
413 		if(sourceRectsArray && rects == 0 || !sourceRectsArray && rects > 0)
414 		{
415 			return INVALIDCALL();   // FIXME: Verify REF behaviour
416 		}
417 
418 		D3DSURFACE_DESC sourceDescription;
419 		D3DSURFACE_DESC destDescription;
420 
421 		sourceSurface->GetDesc(&sourceDescription);
422 		destinationSurface->GetDesc(&destDescription);
423 
424 		if(sourceDescription.Format != destDescription.Format)
425 		{
426 			return INVALIDCALL();
427 		}
428 
429 		int sWidth = sourceDescription.Width;
430 		int sHeight = sourceDescription.Height;
431 		int dWidth = destDescription.Width;
432 		int dHeight = destDescription.Height;
433 
434 		RECT sRect = {0, 0, sWidth, sHeight};
435 		POINT dPoint = {0, 0};
436 
437 		if(!sourceRectsArray || !destPointsArray)
438 		{
439 			sourceRectsArray = &sRect;
440 			destPointsArray = &dPoint;
441 
442 			rects = 1;
443 		}
444 
445 		int bpp = 8 * Direct3DSurface8::bytes(sourceDescription.Format);
446 
447 		for(unsigned int i = 0; i < rects; i++)
448 		{
449 			const RECT &sRect = sourceRectsArray[i];
450 			const POINT &dPoint = destPointsArray[i];
451 
452 			int rWidth = sRect.right - sRect.left;
453 			int rHeight = sRect.bottom - sRect.top;
454 
455 			RECT dRect;
456 
457 			dRect.top = dPoint.y;
458 			dRect.left = dPoint.x;
459 			dRect.bottom = dPoint.y + rHeight;
460 			dRect.right = dPoint.x + rWidth;
461 
462 			D3DLOCKED_RECT sourceLock;
463 			D3DLOCKED_RECT destLock;
464 
465 			sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY);
466 			destinationSurface->LockRect(&destLock, &dRect, D3DLOCK_DISCARD);
467 
468 			for(int y = 0; y < rHeight; y++)
469 			{
470 				switch(sourceDescription.Format)
471 				{
472 				case D3DFMT_DXT1:
473 				case D3DFMT_DXT2:
474 				case D3DFMT_DXT3:
475 				case D3DFMT_DXT4:
476 				case D3DFMT_DXT5:
477 					memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8);
478 					y += 3;   // Advance four lines at once
479 					break;
480 				default:
481 					memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8);
482 				}
483 
484 				(char*&)sourceLock.pBits += sourceLock.Pitch;
485 				(char*&)destLock.pBits += destLock.Pitch;
486 			}
487 
488 			sourceSurface->UnlockRect();
489 			destinationSurface->UnlockRect();
490 		}
491 
492 		return D3D_OK;
493 	}
494 
CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS * presentParameters,IDirect3DSwapChain8 ** swapChain)495 	long Direct3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain8 **swapChain)
496 	{
497 		TRACE("");
498 
499 		*swapChain = 0;
500 
501 		if(!presentParameters || !swapChain)
502 		{
503 			return INVALIDCALL();
504 		}
505 
506 		if(presentParameters->BackBufferCount > 3)
507 		{
508 			return INVALIDCALL();   // Maximum of three back buffers
509 		}
510 
511 		if(presentParameters->BackBufferCount == 0)
512 		{
513 			presentParameters->BackBufferCount = 1;
514 		}
515 
516 		D3DPRESENT_PARAMETERS present = *presentParameters;
517 
518 		*swapChain = new Direct3DSwapChain8(this, &present);
519 
520 		if(!*swapChain)
521 		{
522 			return OUTOFMEMORY();
523 		}
524 
525 		if(GetAvailableTextureMem() == 0)
526 		{
527 			delete *swapChain;
528 
529 			return OUTOFVIDEOMEMORY();
530 		}
531 
532 		this->swapChain.push_back(static_cast<Direct3DSwapChain8*>(*swapChain));
533 
534 		(*swapChain)->AddRef();
535 
536 		return D3D_OK;
537 	}
538 
CreateCubeTexture(unsigned int edgeLength,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DCubeTexture8 ** cubeTexture)539 	long Direct3DDevice8::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **cubeTexture)
540 	{
541 		TRACE("");
542 
543 		*cubeTexture = 0;
544 
545 		if(edgeLength == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK)
546 		{
547 			return INVALIDCALL();
548 		}
549 
550 		*cubeTexture = new Direct3DCubeTexture8(this, edgeLength, levels, usage, format, pool);
551 
552 		if(!*cubeTexture)
553 		{
554 			return OUTOFMEMORY();
555 		}
556 
557 		if(GetAvailableTextureMem() == 0)
558 		{
559 			delete *cubeTexture;
560 
561 			return OUTOFVIDEOMEMORY();
562 		}
563 
564 		(*cubeTexture)->AddRef();
565 
566 		return D3D_OK;
567 	}
568 
CreateDepthStencilSurface(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,IDirect3DSurface8 ** surface)569 	long Direct3DDevice8::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, IDirect3DSurface8 **surface)
570 	{
571 		TRACE("");
572 
573 		*surface = 0;
574 
575 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
576 		{
577 			return INVALIDCALL();
578 		}
579 
580 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, format == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL);
581 
582 		if(!*surface)
583 		{
584 			return OUTOFMEMORY();
585 		}
586 
587 		if(GetAvailableTextureMem() == 0)
588 		{
589 			delete *surface;
590 
591 			return OUTOFVIDEOMEMORY();
592 		}
593 
594 		(*surface)->AddRef();
595 
596 		return D3D_OK;
597 	}
598 
CreateImageSurface(unsigned int width,unsigned int height,D3DFORMAT format,IDirect3DSurface8 ** surface)599 	long Direct3DDevice8::CreateImageSurface(unsigned int width, unsigned int height, D3DFORMAT format, IDirect3DSurface8 **surface)
600 	{
601 		TRACE("");
602 
603 		*surface = 0;
604 
605 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK)
606 		{
607 			return INVALIDCALL();
608 		}
609 
610 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, true, 0);
611 
612 		if(!*surface)
613 		{
614 			return OUTOFMEMORY();
615 		}
616 
617 		if(GetAvailableTextureMem() == 0)
618 		{
619 			delete *surface;
620 
621 			return OUTOFVIDEOMEMORY();
622 		}
623 
624 		(*surface)->AddRef();
625 
626 		return D3D_OK;
627 	}
628 
CreateIndexBuffer(unsigned int length,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DIndexBuffer8 ** indexBuffer)629 	long Direct3DDevice8::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **indexBuffer)
630 	{
631 		TRACE("");
632 
633 		*indexBuffer = new Direct3DIndexBuffer8(this, length, usage, format, pool);
634 
635 		if(!*indexBuffer)
636 		{
637 			return OUTOFMEMORY();
638 		}
639 
640 		if(GetAvailableTextureMem() == 0)
641 		{
642 			delete *indexBuffer;
643 
644 			return OUTOFVIDEOMEMORY();
645 		}
646 
647 		(*indexBuffer)->AddRef();
648 
649 		return D3D_OK;
650 	}
651 
CreatePixelShader(const unsigned long * function,unsigned long * handle)652 	long Direct3DDevice8::CreatePixelShader(const unsigned long *function, unsigned long *handle)
653 	{
654 		TRACE("");
655 
656 		if(!function || !handle || function[0] > pixelShaderVersion)
657 		{
658 			return INVALIDCALL();
659 		}
660 
661 		unsigned int index;
662 
663 		for(index = 1; index < pixelShader.size(); index++)   // Skip NULL handle
664 		{
665 			if(pixelShader[index] == 0)
666 			{
667 				pixelShader[index] = new Direct3DPixelShader8(this, function);   // FIXME: Check for null
668 
669 				break;
670 			}
671 		}
672 
673 		if(index == pixelShader.size())
674 		{
675 			pixelShader.push_back(new Direct3DPixelShader8(this, function));
676 		}
677 
678 		pixelShader[index]->AddRef();
679 
680 		*handle = index;
681 
682 		return D3D_OK;
683 	}
684 
CreateRenderTarget(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,int lockable,IDirect3DSurface8 ** surface)685 	long Direct3DDevice8::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, int lockable, IDirect3DSurface8 **surface)
686 	{
687 		TRACE("");
688 
689 		*surface = 0;
690 
691 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
692 		{
693 			return INVALIDCALL();
694 		}
695 
696 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, lockable != FALSE, D3DUSAGE_RENDERTARGET);
697 
698 		if(!*surface)
699 		{
700 			return OUTOFMEMORY();
701 		}
702 
703 		if(GetAvailableTextureMem() == 0)
704 		{
705 			delete *surface;
706 
707 			return OUTOFVIDEOMEMORY();
708 		}
709 
710 		(*surface)->AddRef();
711 
712 		return D3D_OK;
713 	}
714 
CreateStateBlock(D3DSTATEBLOCKTYPE type,unsigned long * token)715 	long Direct3DDevice8::CreateStateBlock(D3DSTATEBLOCKTYPE type, unsigned long *token)
716 	{
717 		TRACE("");
718 
719 		if(!token)
720 		{
721 			return INVALIDCALL();
722 		}
723 
724 		Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, type);
725 		stateBlock->bind();
726 		stateRecorder.push_back(stateBlock);
727 		*token = (unsigned long)(stateRecorder.size() - 1);
728 
729 		return D3D_OK;
730 	}
731 
CreateTexture(unsigned int width,unsigned int height,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DTexture8 ** texture)732 	long Direct3DDevice8::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture8 **texture)
733 	{
734 		TRACE("");
735 
736 		*texture = 0;
737 
738 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK)
739 		{
740 			return INVALIDCALL();
741 		}
742 
743 		*texture = new Direct3DTexture8(this, width, height, levels, usage, format, pool);
744 
745 		if(!*texture)
746 		{
747 			return OUTOFMEMORY();
748 		}
749 
750 		if(GetAvailableTextureMem() == 0)
751 		{
752 			delete *texture;
753 
754 			return OUTOFVIDEOMEMORY();
755 		}
756 
757 		(*texture)->AddRef();
758 
759 		return D3D_OK;
760 	}
761 
CreateVertexBuffer(unsigned int length,unsigned long usage,unsigned long FVF,D3DPOOL pool,IDirect3DVertexBuffer8 ** vertexBuffer)762 	long Direct3DDevice8::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer8 **vertexBuffer)
763 	{
764 		TRACE("");
765 
766 		*vertexBuffer = new Direct3DVertexBuffer8(this, length, usage, FVF, pool);
767 
768 		if(!*vertexBuffer)
769 		{
770 			return OUTOFMEMORY();
771 		}
772 
773 		if(GetAvailableTextureMem() == 0)
774 		{
775 			delete *vertexBuffer;
776 
777 			return OUTOFVIDEOMEMORY();
778 		}
779 
780 		(*vertexBuffer)->AddRef();
781 
782 		return D3D_OK;
783 	}
784 
CreateVertexShader(const unsigned long * declaration,const unsigned long * function,unsigned long * handle,unsigned long usage)785 	long Direct3DDevice8::CreateVertexShader(const unsigned long *declaration, const unsigned long *function, unsigned long *handle, unsigned long usage)
786 	{
787 		TRACE("const unsigned long *declaration = 0x%0.8p, const unsigned long *function = 0x%0.8p, unsigned long *handle = 0x%0.8p, unsigned long usage = %d", declaration, function, handle, usage);
788 
789 		if(!declaration || !handle || (function && function[0] > vertexShaderVersion))
790 		{
791 			return INVALIDCALL();
792 		}
793 
794 		unsigned int index;
795 
796 		for(index = 1; index < vertexShader.size(); index++)   // NOTE: skip NULL handle
797 		{
798 			if(vertexShader[index] == 0)
799 			{
800 				vertexShader[index] = new Direct3DVertexShader8(this, declaration, function);   // FIXME: Check for null
801 
802 				break;
803 			}
804 		}
805 
806 		if(index == vertexShader.size())
807 		{
808 			vertexShader.push_back(new Direct3DVertexShader8(this, declaration, function));
809 		}
810 
811 		vertexShader[index]->AddRef();
812 
813 		*handle = (index << 16) + 1;
814 
815 		return D3D_OK;
816 	}
817 
CreateVolumeTexture(unsigned int width,unsigned int height,unsigned int depth,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DVolumeTexture8 ** volumeTexture)818 	long Direct3DDevice8::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture8 **volumeTexture)
819 	{
820 		TRACE("");
821 
822 		*volumeTexture = 0;
823 
824 		if(width == 0 || height == 0 || depth == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK)
825 		{
826 			return INVALIDCALL();
827 		}
828 
829 		*volumeTexture = new Direct3DVolumeTexture8(this, width, height, depth, levels, usage, format, pool);
830 
831 		if(!*volumeTexture)
832 		{
833 			return OUTOFMEMORY();
834 		}
835 
836 		if(GetAvailableTextureMem() == 0)
837 		{
838 			delete *volumeTexture;
839 
840 			return OUTOFVIDEOMEMORY();
841 		}
842 
843 		(*volumeTexture)->AddRef();
844 
845 		return D3D_OK;
846 	}
847 
DeletePatch(unsigned int handle)848 	long Direct3DDevice8::DeletePatch(unsigned int handle)
849 	{
850 		TRACE("");
851 
852 		UNIMPLEMENTED();
853 
854 		return D3D_OK;
855 	}
856 
DeleteStateBlock(unsigned long token)857 	long Direct3DDevice8::DeleteStateBlock(unsigned long token)
858 	{
859 		TRACE("");
860 
861 		if(token >= stateRecorder.size() || !stateRecorder[token])
862 		{
863 			return INVALIDCALL();
864 		}
865 
866 		stateRecorder[token]->unbind();
867 		stateRecorder[token] = 0;
868 
869 		return D3D_OK;
870 	}
871 
DeleteVertexShader(unsigned long handle)872 	long Direct3DDevice8::DeleteVertexShader(unsigned long handle)
873 	{
874 		TRACE("");
875 
876 		unsigned int index = handle >> 16;
877 
878 		if(index >= vertexShader.size() || !vertexShader[index])
879 		{
880 			return INVALIDCALL();
881 		}
882 
883 		vertexShader[index]->Release();
884 		vertexShader[index] = 0;
885 
886 		return D3D_OK;
887 	}
888 
DrawIndexedPrimitive(D3DPRIMITIVETYPE type,unsigned int minIndex,unsigned int numVertices,unsigned int startIndex,unsigned int primitiveCount)889 	long Direct3DDevice8::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount)
890 	{
891 		TRACE("");
892 
893 		if(!indexData)
894 		{
895 			return INVALIDCALL();
896 		}
897 
898 		if(!bindData(indexData, baseVertexIndex) || !primitiveCount)
899 		{
900 			return D3D_OK;
901 		}
902 
903 		unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account
904 
905 		sw::DrawType drawType;
906 
907 		if(indexData->is32Bit())
908 		{
909 			switch(type)
910 			{
911 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break;
912 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break;
913 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break;
914 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break;
915 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break;
916 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break;
917 			default:
918 				ASSERT(false);
919 			}
920 		}
921 		else
922 		{
923 			switch(type)
924 			{
925 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break;
926 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break;
927 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break;
928 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break;
929 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break;
930 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break;
931 			default:
932 				ASSERT(false);
933 			}
934 		}
935 
936 		bindData(indexData, baseVertexIndex);
937 
938 		renderer->draw(drawType, indexOffset, primitiveCount);
939 
940 		return D3D_OK;
941 	}
942 
DeletePixelShader(unsigned long handle)943 	long Direct3DDevice8::DeletePixelShader(unsigned long handle)
944 	{
945 		TRACE("");
946 
947 		if(handle >= pixelShader.size() || !pixelShader[handle])
948 		{
949 			return INVALIDCALL();
950 		}
951 
952 		pixelShader[handle]->Release();
953 		pixelShader[handle] = 0;
954 
955 		return D3D_OK;
956 	}
957 
DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type,unsigned int minIndex,unsigned int numVertices,unsigned int primitiveCount,const void * indexData,D3DFORMAT indexDataFormat,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)958 	long Direct3DDevice8::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
959 	{
960 		TRACE("");
961 
962 		if(!vertexStreamZeroData || !indexData)
963 		{
964 			return INVALIDCALL();
965 		}
966 
967 		int length = (minIndex + numVertices) * vertexStreamZeroStride;
968 
969 		Direct3DVertexBuffer8 *vertexBuffer = new Direct3DVertexBuffer8(this, length, 0, 0, D3DPOOL_DEFAULT);
970 
971 		unsigned char *data;
972 		vertexBuffer->Lock(0, 0, &data, 0);
973 		memcpy(data, vertexStreamZeroData, length);
974 		vertexBuffer->Unlock();
975 
976 		SetStreamSource(0, vertexBuffer, vertexStreamZeroStride);
977 
978 		switch(type)
979 		{
980 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
981 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
982 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
983 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
984 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
985 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
986 		default:
987 			ASSERT(false);
988 		}
989 
990 		length *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2;
991 
992 		Direct3DIndexBuffer8 *indexBuffer = new Direct3DIndexBuffer8(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT);
993 
994 		indexBuffer->Lock(0, 0, &data, 0);
995 		memcpy(data, indexData, length);
996 		indexBuffer->Unlock();
997 
998 		SetIndices(indexBuffer, 0);
999 
1000 		if(!bindData(indexBuffer, 0) || !primitiveCount)
1001 		{
1002 			vertexBuffer->Release();
1003 
1004 			return D3D_OK;
1005 		}
1006 
1007 		sw::DrawType drawType;
1008 
1009 		if(indexDataFormat == D3DFMT_INDEX32)
1010 		{
1011 			switch(type)
1012 			{
1013 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break;
1014 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break;
1015 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break;
1016 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break;
1017 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break;
1018 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break;
1019 			default:
1020 				ASSERT(false);
1021 			}
1022 		}
1023 		else
1024 		{
1025 			switch(type)
1026 			{
1027 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break;
1028 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break;
1029 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break;
1030 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break;
1031 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break;
1032 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break;
1033 			default:
1034 				ASSERT(false);
1035 			}
1036 		}
1037 
1038 		renderer->draw(drawType, 0, primitiveCount);
1039 
1040 		SetStreamSource(0, 0, 0);
1041 		SetIndices(0, 0);
1042 
1043 		return D3D_OK;
1044 	}
1045 
DrawPrimitive(D3DPRIMITIVETYPE primitiveType,unsigned int startVertex,unsigned int primitiveCount)1046 	long Direct3DDevice8::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount)
1047 	{
1048 		TRACE("");
1049 
1050 		if(!bindData(0, startVertex) || !primitiveCount)
1051 		{
1052 			return D3D_OK;
1053 		}
1054 
1055 		sw::DrawType drawType;
1056 
1057 		switch(primitiveType)
1058 		{
1059 		case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break;
1060 		case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break;
1061 		case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break;
1062 		case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break;
1063 		case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break;
1064 		case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break;
1065 		default:
1066 			ASSERT(false);
1067 		}
1068 
1069 		renderer->draw(drawType, 0, primitiveCount);
1070 
1071 		return D3D_OK;
1072 	}
1073 
DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType,unsigned int primitiveCount,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)1074 	long Direct3DDevice8::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
1075 	{
1076 		TRACE("");
1077 
1078 		if(!vertexStreamZeroData)
1079 		{
1080 			return INVALIDCALL();
1081 		}
1082 
1083 		IDirect3DVertexBuffer8 *vertexBuffer = 0;
1084 		int length = 0;
1085 
1086 		switch(primitiveType)
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 *= vertexStreamZeroStride;
1099 
1100 		CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer);
1101 
1102 		unsigned char *data;
1103 		vertexBuffer->Lock(0, 0, &data, 0);
1104 		memcpy(data, vertexStreamZeroData, length);
1105 		vertexBuffer->Unlock();
1106 
1107 		SetStreamSource(0, vertexBuffer, vertexStreamZeroStride);
1108 
1109 		if(!bindData(0, 0) || !primitiveCount)
1110 		{
1111 			vertexBuffer->Release();
1112 
1113 			return D3D_OK;
1114 		}
1115 
1116 		sw::DrawType drawType;
1117 
1118 		switch(primitiveType)
1119 		{
1120 		case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break;
1121 		case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break;
1122 		case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break;
1123 		case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break;
1124 		case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break;
1125 		case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break;
1126 		default:
1127 			ASSERT(false);
1128 		}
1129 
1130 		renderer->draw(drawType, 0, primitiveCount);
1131 
1132 		SetStreamSource(0, 0, 0);
1133 		vertexBuffer->Release();
1134 
1135 		return D3D_OK;
1136 	}
1137 
DrawRectPatch(unsigned int handle,const float * numSegs,const D3DRECTPATCH_INFO * rectPatchInfo)1138 	long Direct3DDevice8::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo)
1139 	{
1140 		TRACE("");
1141 
1142 		if(!numSegs || !rectPatchInfo)
1143 		{
1144 			return INVALIDCALL();
1145 		}
1146 
1147 		UNIMPLEMENTED();
1148 
1149 		return D3D_OK;
1150 	}
1151 
DrawTriPatch(unsigned int handle,const float * numSegs,const D3DTRIPATCH_INFO * triPatchInfo)1152 	long Direct3DDevice8::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo)
1153 	{
1154 		TRACE("");
1155 
1156 		if(!numSegs || !triPatchInfo)
1157 		{
1158 			return INVALIDCALL();
1159 		}
1160 
1161 		UNIMPLEMENTED();
1162 
1163 		return D3D_OK;
1164 	}
1165 
EndScene()1166 	long Direct3DDevice8::EndScene()
1167 	{
1168 		TRACE("");
1169 
1170 		return D3D_OK;
1171 	}
1172 
EndStateBlock(unsigned long * token)1173 	long Direct3DDevice8::EndStateBlock(unsigned long *token)
1174 	{
1175 		TRACE("");
1176 
1177 		if(!token)
1178 		{
1179 			return INVALIDCALL();
1180 		}
1181 
1182 		recordState = false;
1183 		*token = (unsigned long)(stateRecorder.size() - 1);
1184 
1185 		return D3D_OK;
1186 	}
1187 
GetAvailableTextureMem()1188 	unsigned int Direct3DDevice8::GetAvailableTextureMem()
1189 	{
1190 		TRACE("");
1191 
1192 		int availableMemory = textureMemory - Direct3DResource8::getMemoryUsage();
1193 		if(availableMemory < 0) availableMemory = 0;
1194 
1195 		// Round to nearest MB
1196 		return (availableMemory + 0x80000) & 0xFFF00000;
1197 	}
1198 
GetBackBuffer(unsigned int index,D3DBACKBUFFER_TYPE type,IDirect3DSurface8 ** backBuffer)1199 	long Direct3DDevice8::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface8 **backBuffer)
1200 	{
1201 		TRACE("");
1202 
1203 		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
1204 		{
1205 			return INVALIDCALL();
1206 		}
1207 
1208 		swapChain[index]->GetBackBuffer(index, type, backBuffer);
1209 
1210 		return D3D_OK;
1211 	}
1212 
GetClipPlane(unsigned long index,float * plane)1213 	long Direct3DDevice8::GetClipPlane(unsigned long index, float *plane)
1214 	{
1215 		TRACE("");
1216 
1217 		if(!plane || index >= 6)
1218 		{
1219 			return INVALIDCALL();
1220 		}
1221 
1222 		plane[0] = this->plane[index][0];
1223 		plane[1] = this->plane[index][1];
1224 		plane[2] = this->plane[index][2];
1225 		plane[3] = this->plane[index][3];
1226 
1227 		return D3D_OK;
1228 	}
1229 
GetClipStatus(D3DCLIPSTATUS8 * clipStatus)1230 	long Direct3DDevice8::GetClipStatus(D3DCLIPSTATUS8 *clipStatus)
1231 	{
1232 		TRACE("");
1233 
1234 		if(!clipStatus)
1235 		{
1236 			return INVALIDCALL();
1237 		}
1238 
1239 		*clipStatus = this->clipStatus;
1240 
1241 		return D3D_OK;
1242 	}
1243 
GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS * parameters)1244 	long Direct3DDevice8::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters)
1245 	{
1246 		TRACE("");
1247 
1248 		if(!parameters)
1249 		{
1250 			return INVALIDCALL();
1251 		}
1252 
1253 		parameters->AdapterOrdinal = adapter;
1254 		parameters->BehaviorFlags = behaviourFlags;
1255 		parameters->DeviceType = deviceType;
1256 		parameters->hFocusWindow = focusWindow;
1257 
1258 		return D3D_OK;
1259 	}
1260 
GetCurrentTexturePalette(unsigned int * paletteNumber)1261 	long Direct3DDevice8::GetCurrentTexturePalette(unsigned int *paletteNumber)
1262 	{
1263 		TRACE("");
1264 
1265 		if(!paletteNumber)
1266 		{
1267 			return INVALIDCALL();
1268 		}
1269 
1270 		*paletteNumber = currentPalette;
1271 
1272 		return D3D_OK;
1273 	}
1274 
GetDepthStencilSurface(IDirect3DSurface8 ** depthStencilSurface)1275 	long Direct3DDevice8::GetDepthStencilSurface(IDirect3DSurface8 **depthStencilSurface)
1276 	{
1277 		TRACE("");
1278 
1279 		if(!depthStencilSurface)
1280 		{
1281 			return INVALIDCALL();
1282 		}
1283 
1284 		*depthStencilSurface = depthStencil;
1285 
1286 		if(depthStencil)
1287 		{
1288 			depthStencil->AddRef();
1289 		}
1290 
1291 		return D3D_OK;   // FIXME: Return NOTFOUND() when no depthStencil?
1292 	}
1293 
GetDeviceCaps(D3DCAPS8 * caps)1294 	long Direct3DDevice8::GetDeviceCaps(D3DCAPS8 *caps)
1295 	{
1296 		TRACE("");
1297 
1298 		return d3d8->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps);
1299 	}
1300 
GetDirect3D(IDirect3D8 ** d3d8)1301 	long Direct3DDevice8::GetDirect3D(IDirect3D8 **d3d8)
1302 	{
1303 		TRACE("");
1304 
1305 		if(!d3d8)
1306 		{
1307 			return INVALIDCALL();
1308 		}
1309 
1310 		ASSERT(this->d3d8);
1311 
1312 		*d3d8 = this->d3d8;
1313 		this->d3d8->AddRef();
1314 
1315 		return D3D_OK;
1316 	}
1317 
GetDisplayMode(D3DDISPLAYMODE * mode)1318 	long Direct3DDevice8::GetDisplayMode(D3DDISPLAYMODE *mode)
1319 	{
1320 		TRACE("");
1321 
1322 		if(!mode)
1323 		{
1324 			return INVALIDCALL();
1325 		}
1326 
1327 		d3d8->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, mode);
1328 
1329 		return D3D_OK;
1330 	}
1331 
GetFrontBuffer(IDirect3DSurface8 * destSurface)1332 	long Direct3DDevice8::GetFrontBuffer(IDirect3DSurface8 *destSurface)
1333 	{
1334 		TRACE("");
1335 
1336 		if(!destSurface)
1337 		{
1338 			return INVALIDCALL();
1339 		}
1340 
1341 		D3DLOCKED_RECT description;
1342 		destSurface->LockRect(&description, 0, 0);
1343 
1344 		swapChain[0]->screenshot(description.pBits);
1345 
1346 		destSurface->UnlockRect();
1347 
1348 		return D3D_OK;
1349 	}
1350 
GetGammaRamp(D3DGAMMARAMP * ramp)1351 	void Direct3DDevice8::GetGammaRamp(D3DGAMMARAMP *ramp)
1352 	{
1353 		TRACE("");
1354 
1355 		if(!ramp)
1356 		{
1357 			return;
1358 		}
1359 
1360 		swapChain[0]->getGammaRamp((sw::GammaRamp*)ramp);
1361 	}
1362 
GetIndices(IDirect3DIndexBuffer8 ** indexData,unsigned int * baseVertexIndex)1363 	long Direct3DDevice8::GetIndices(IDirect3DIndexBuffer8 **indexData, unsigned int *baseVertexIndex)
1364 	{
1365 		TRACE("");
1366 
1367 		if(!indexData || !baseVertexIndex)
1368 		{
1369 			return INVALIDCALL();
1370 		}
1371 
1372 		*indexData = this->indexData;
1373 
1374 		if(this->indexData)
1375 		{
1376 			this->indexData->AddRef();
1377 		}
1378 
1379 		*baseVertexIndex = this->baseVertexIndex;
1380 
1381 		return D3D_OK;
1382 	}
1383 
GetInfo(unsigned long devInfoID,void * devInfoStruct,unsigned long devInfoStructSize)1384 	long Direct3DDevice8::GetInfo(unsigned long devInfoID, void *devInfoStruct, unsigned long devInfoStructSize)
1385 	{
1386 		TRACE("");
1387 
1388 		if(!devInfoStruct || devInfoStructSize == 0)
1389 		{
1390 			return INVALIDCALL();
1391 		}
1392 
1393 		switch(devInfoID)
1394 		{
1395 		case 0: return E_FAIL;
1396 		case 1: return E_FAIL;
1397 		case 2: return E_FAIL;
1398 		case 3: return E_FAIL;
1399 		case 4: return S_FALSE;
1400 		case 5: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_RESOURCEMANAGER
1401 		case 6: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_D3DVERTEXSTATS
1402 		case 7: return E_FAIL;
1403 		}
1404 
1405 		return D3D_OK;
1406 	}
1407 
GetLight(unsigned long index,D3DLIGHT8 * light)1408 	long Direct3DDevice8::GetLight(unsigned long index, D3DLIGHT8 *light)
1409 	{
1410 		TRACE("");
1411 
1412 		if(!light)
1413 		{
1414 			return INVALIDCALL();
1415 		}
1416 
1417 		if(!this->light.exists(index))
1418 		{
1419 			return INVALIDCALL();
1420 		}
1421 
1422 		*light = this->light[index];
1423 
1424 		return D3D_OK;
1425 	}
1426 
GetLightEnable(unsigned long index,int * enable)1427 	long Direct3DDevice8::GetLightEnable(unsigned long index , int *enable)
1428 	{
1429 		TRACE("");
1430 
1431 		if(!enable)
1432 		{
1433 			return INVALIDCALL();
1434 		}
1435 
1436 		if(!light.exists(index))
1437 		{
1438 			return INVALIDCALL();
1439 		}
1440 
1441 		*enable = light[index].enable;
1442 
1443 		return D3D_OK;
1444 	}
1445 
GetMaterial(D3DMATERIAL8 * material)1446 	long Direct3DDevice8::GetMaterial(D3DMATERIAL8 *material)
1447 	{
1448 		TRACE("");
1449 
1450 		if(!material)
1451 		{
1452 			return INVALIDCALL();
1453 		}
1454 
1455 		*material = this->material;
1456 
1457 		return D3D_OK;
1458 	}
1459 
GetPaletteEntries(unsigned int paletteNumber,PALETTEENTRY * entries)1460 	long Direct3DDevice8::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries)
1461 	{
1462 		TRACE("");
1463 
1464 		if(paletteNumber > 0xFFFF || !entries)
1465 		{
1466 			return INVALIDCALL();
1467 		}
1468 
1469 		for(int i = 0; i < 256; i++)
1470 		{
1471 			entries[i] = palette[paletteNumber].entry[i];
1472 		}
1473 
1474 		return D3D_OK;
1475 	}
1476 
GetPixelShader(unsigned long * handle)1477 	long Direct3DDevice8::GetPixelShader(unsigned long *handle)
1478 	{
1479 		TRACE("");
1480 
1481 		if(!handle)
1482 		{
1483 			return INVALIDCALL();
1484 		}
1485 
1486 		*handle = pixelShaderHandle;
1487 
1488 		return D3D_OK;
1489 	}
1490 
GetPixelShaderFunction(unsigned long handle,void * data,unsigned long * size)1491 	long Direct3DDevice8::GetPixelShaderFunction(unsigned long handle, void *data, unsigned long *size)
1492 	{
1493 		TRACE("");
1494 
1495 		if(!data)
1496 		{
1497 			return INVALIDCALL();
1498 		}
1499 
1500 		UNIMPLEMENTED();
1501 
1502 		return D3D_OK;
1503 	}
1504 
GetPixelShaderConstant(unsigned long startRegister,void * constantData,unsigned long count)1505 	long Direct3DDevice8::GetPixelShaderConstant(unsigned long startRegister, void *constantData, unsigned long count)
1506 	{
1507 		TRACE("");
1508 
1509 		if(!constantData)
1510 		{
1511 			return INVALIDCALL();
1512 		}
1513 
1514 		for(unsigned int i = 0; i < count; i++)
1515 		{
1516 			((float*)constantData)[i * 4 + 0] = pixelShaderConstant[startRegister + i][0];
1517 			((float*)constantData)[i * 4 + 1] = pixelShaderConstant[startRegister + i][1];
1518 			((float*)constantData)[i * 4 + 2] = pixelShaderConstant[startRegister + i][2];
1519 			((float*)constantData)[i * 4 + 3] = pixelShaderConstant[startRegister + i][3];
1520 		}
1521 
1522 		return D3D_OK;
1523 	}
1524 
GetRasterStatus(D3DRASTER_STATUS * rasterStatus)1525 	long Direct3DDevice8::GetRasterStatus(D3DRASTER_STATUS *rasterStatus)
1526 	{
1527 		TRACE("");
1528 
1529 		if(!rasterStatus)
1530 		{
1531 			return INVALIDCALL();
1532 		}
1533 
1534 		UNIMPLEMENTED();
1535 
1536 		return D3D_OK;
1537 	}
1538 
GetRenderState(D3DRENDERSTATETYPE state,unsigned long * value)1539 	long Direct3DDevice8::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value)
1540 	{
1541 		TRACE("");
1542 
1543 		if(!value)
1544 		{
1545 			return INVALIDCALL();
1546 		}
1547 
1548 		*value = renderState[state];
1549 
1550 		return D3D_OK;
1551 	}
1552 
GetRenderTarget(IDirect3DSurface8 ** renderTarget)1553 	long Direct3DDevice8::GetRenderTarget(IDirect3DSurface8 **renderTarget)
1554 	{
1555 		TRACE("");
1556 
1557 		if(!renderTarget)
1558 		{
1559 			return INVALIDCALL();
1560 		}
1561 
1562 		*renderTarget = this->renderTarget;
1563 		this->renderTarget->AddRef();
1564 
1565 		return D3D_OK;
1566 	}
1567 
GetStreamSource(unsigned int streamNumber,IDirect3DVertexBuffer8 ** streamData,unsigned int * stride)1568 	long Direct3DDevice8::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer8 **streamData, unsigned int *stride)
1569 	{
1570 		TRACE("");
1571 
1572 		if(streamNumber >= 16 || !streamData || !stride)
1573 		{
1574 			return INVALIDCALL();
1575 		}
1576 
1577 		*streamData = dataStream[streamNumber];
1578 
1579 		if(dataStream[streamNumber])
1580 		{
1581 			dataStream[streamNumber]->AddRef();
1582 		}
1583 
1584 		*stride = 0;   // NOTE: Unimplemented
1585 
1586 		return D3D_OK;
1587 	}
1588 
GetTexture(unsigned long stage,IDirect3DBaseTexture8 ** texture)1589 	long Direct3DDevice8::GetTexture(unsigned long stage, IDirect3DBaseTexture8 **texture)
1590 	{
1591 		TRACE("");
1592 
1593 		if(!texture || stage >= 8)
1594 		{
1595 			return INVALIDCALL();
1596 		}
1597 
1598 		*texture = this->texture[stage];
1599 
1600 		if(this->texture[stage])
1601 		{
1602 			this->texture[stage]->AddRef();
1603 		}
1604 
1605 		return D3D_OK;
1606 	}
1607 
GetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE state,unsigned long * value)1608 	long Direct3DDevice8::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE state, unsigned long *value)
1609 	{
1610 		TRACE("");
1611 
1612 		if(!value  || stage < 0 || stage >= 8 || state < 0 || state > D3DTSS_RESULTARG)   // FIXME: Set *value to 0?
1613 		{
1614 			return INVALIDCALL();
1615 		}
1616 
1617 		*value = textureStageState[stage][state];
1618 
1619 		return D3D_OK;
1620 	}
1621 
GetTransform(D3DTRANSFORMSTATETYPE state,D3DMATRIX * matrix)1622 	long Direct3DDevice8::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
1623 	{
1624 		TRACE("");
1625 
1626 		if(!matrix || state < 0 || state > 511)
1627 		{
1628 			return INVALIDCALL();
1629 		}
1630 
1631 		*matrix = this->matrix[state];
1632 
1633 		return D3D_OK;
1634 	}
1635 
GetVertexShader(unsigned long * handle)1636 	long Direct3DDevice8::GetVertexShader(unsigned long *handle)
1637 	{
1638 		TRACE("");
1639 
1640 		if(!handle)
1641 		{
1642 			return INVALIDCALL();
1643 		}
1644 
1645 		*handle = vertexShaderHandle;
1646 
1647 		return D3D_OK;
1648 	}
1649 
GetVertexShaderConstant(unsigned long startRegister,void * constantData,unsigned long count)1650 	long Direct3DDevice8::GetVertexShaderConstant(unsigned long startRegister, void *constantData, unsigned long count)
1651 	{
1652 		TRACE("");
1653 
1654 		if(!constantData)
1655 		{
1656 			return INVALIDCALL();
1657 		}
1658 
1659 		for(unsigned int i = 0; i < count; i++)
1660 		{
1661 			((float*)constantData)[i * 4 + 0] = vertexShaderConstant[startRegister + i][0];
1662 			((float*)constantData)[i * 4 + 1] = vertexShaderConstant[startRegister + i][1];
1663 			((float*)constantData)[i * 4 + 2] = vertexShaderConstant[startRegister + i][2];
1664 			((float*)constantData)[i * 4 + 3] = vertexShaderConstant[startRegister + i][3];
1665 		}
1666 
1667 		return D3D_OK;
1668 	}
1669 
GetVertexShaderDeclaration(unsigned long handle,void * data,unsigned long * size)1670 	long Direct3DDevice8::GetVertexShaderDeclaration(unsigned long handle, void *data, unsigned long *size)
1671 	{
1672 		TRACE("");
1673 
1674 		if(!data || !size)
1675 		{
1676 			return INVALIDCALL();
1677 		}
1678 
1679 		UNIMPLEMENTED();
1680 
1681 		return D3D_OK;
1682 	}
1683 
GetVertexShaderFunction(unsigned long handle,void * data,unsigned long * size)1684 	long Direct3DDevice8::GetVertexShaderFunction(unsigned long handle, void *data, unsigned long *size)
1685 	{
1686 		TRACE("");
1687 
1688 		if(!data || !size)
1689 		{
1690 			return INVALIDCALL();
1691 		}
1692 
1693 		UNIMPLEMENTED();
1694 
1695 		return D3D_OK;
1696 	}
1697 
GetViewport(D3DVIEWPORT8 * viewport)1698 	long Direct3DDevice8::GetViewport(D3DVIEWPORT8 *viewport)
1699 	{
1700 		TRACE("");
1701 
1702 		if(!viewport)
1703 		{
1704 			return INVALIDCALL();
1705 		}
1706 
1707 		*viewport = this->viewport;
1708 
1709 		return D3D_OK;
1710 	}
1711 
LightEnable(unsigned long index,int enable)1712 	long Direct3DDevice8::LightEnable(unsigned long index, int enable)
1713 	{
1714 		TRACE("");
1715 
1716 		if(!recordState)
1717 		{
1718 			if(!light.exists(index))   // Insert default light
1719 			{
1720 				D3DLIGHT8 light;
1721 
1722 				light.Type = D3DLIGHT_DIRECTIONAL;
1723 				light.Diffuse.r = 1;
1724 				light.Diffuse.g = 1;
1725 				light.Diffuse.b = 1;
1726 				light.Diffuse.a = 0;
1727 				light.Specular.r = 0;
1728 				light.Specular.g = 0;
1729 				light.Specular.b = 0;
1730 				light.Specular.a = 0;
1731 				light.Ambient.r = 0;
1732 				light.Ambient.g = 0;
1733 				light.Ambient.b = 0;
1734 				light.Ambient.a = 0;
1735 				light.Position.x = 0;
1736 				light.Position.y = 0;
1737 				light.Position.z = 0;
1738 				light.Direction.x = 0;
1739 				light.Direction.y = 0;
1740 				light.Direction.z = 1;
1741 				light.Range = 0;
1742 				light.Falloff = 0;
1743 				light.Attenuation0 = 0;
1744 				light.Attenuation1 = 0;
1745 				light.Attenuation2 = 0;
1746 				light.Theta = 0;
1747 				light.Phi = 0;
1748 
1749 				SetLight(index, &light);
1750 			}
1751 
1752 			light[index].enable = (enable != FALSE);
1753 
1754 			lightsDirty = true;
1755 		}
1756 		else
1757 		{
1758 			stateRecorder.back()->lightEnable(index, enable);
1759 		}
1760 
1761 		return D3D_OK;
1762 	}
1763 
MultiplyTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)1764 	long Direct3DDevice8::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1765 	{
1766 		TRACE("");
1767 
1768 		if(!matrix)
1769 		{
1770 			return INVALIDCALL();
1771 		}
1772 
1773 		D3DMATRIX *current = &this->matrix[state];
1774 
1775 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41,
1776 		             current->_12, current->_22, current->_32, current->_42,
1777 		             current->_13, current->_23, current->_33, current->_43,
1778 		             current->_14, current->_24, current->_34, current->_44);
1779 
1780 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
1781 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
1782 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
1783 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
1784 
1785 		switch(state)
1786 		{
1787 		case D3DTS_WORLD:
1788 			renderer->setModelMatrix(C * M);
1789 			break;
1790 		case D3DTS_VIEW:
1791 			renderer->setViewMatrix(C * M);
1792 			break;
1793 		case D3DTS_PROJECTION:
1794 			renderer->setProjectionMatrix(C * M);
1795 			break;
1796 		case D3DTS_TEXTURE0:
1797 			renderer->setTextureMatrix(0, C * M);
1798 			break;
1799 		case D3DTS_TEXTURE1:
1800 			renderer->setTextureMatrix(1, C * M);
1801 			break;
1802 		case D3DTS_TEXTURE2:
1803 			renderer->setTextureMatrix(2, C * M);
1804 			break;
1805 		case D3DTS_TEXTURE3:
1806 			renderer->setTextureMatrix(3, C * M);
1807 			break;
1808 		case D3DTS_TEXTURE4:
1809 			renderer->setTextureMatrix(4, C * M);
1810 			break;
1811 		case D3DTS_TEXTURE5:
1812 			renderer->setTextureMatrix(5, C * M);
1813 			break;
1814 		case D3DTS_TEXTURE6:
1815 			renderer->setTextureMatrix(6, C * M);
1816 			break;
1817 		case D3DTS_TEXTURE7:
1818 			renderer->setTextureMatrix(7, C * M);
1819 			break;
1820 		default:
1821 			if(state > 256 && state < 512)
1822 			{
1823 				renderer->setModelMatrix(C * M, state - 256);
1824 			}
1825 			else ASSERT(false);
1826 		}
1827 
1828 		return D3D_OK;
1829 	}
1830 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion)1831 	long Direct3DDevice8::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
1832 	{
1833 		TRACE("");
1834 
1835 		// NOTE: sourceRect and destRect can be null, dirtyRegion has to be null
1836 
1837 		HWND windowHandle = presentParameters.hDeviceWindow ? presentParameters.hDeviceWindow : focusWindow;
1838 
1839 		if(destWindowOverride && destWindowOverride != windowHandle)
1840 		{
1841 			UNIMPLEMENTED();
1842 		}
1843 
1844 		if(dirtyRegion)
1845 		{
1846 			return INVALIDCALL();
1847 		}
1848 
1849 		swapChain[0]->Present(sourceRect, destRect, destWindowOverride, dirtyRegion);
1850 
1851 		return D3D_OK;
1852 	}
1853 
ProcessVertices(unsigned int srcStartIndex,unsigned int destIndex,unsigned int vertexCount,IDirect3DVertexBuffer8 * destBuffer,unsigned long flags)1854 	long Direct3DDevice8::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer8 *destBuffer, unsigned long flags)
1855 	{
1856 		TRACE("");
1857 
1858 		if(!destBuffer)
1859 		{
1860 			return INVALIDCALL();
1861 		}
1862 
1863 		UNIMPLEMENTED();
1864 
1865 		return D3D_OK;
1866 	}
1867 
Reset(D3DPRESENT_PARAMETERS * presentParameters)1868 	long Direct3DDevice8::Reset(D3DPRESENT_PARAMETERS *presentParameters)
1869 	{
1870 		TRACE("");
1871 
1872 		if(!presentParameters)
1873 		{
1874 			return INVALIDCALL();
1875 		}
1876 
1877 		if(swapChain[0])
1878 		{
1879 			swapChain[0]->unbind();
1880 			swapChain[0] = 0;
1881 		}
1882 
1883 		if(depthStencil)
1884 		{
1885 			depthStencil->unbind();
1886 			depthStencil = 0;
1887 		}
1888 
1889 		if(renderTarget)
1890 		{
1891 			renderTarget->unbind();
1892 			renderTarget = 0;
1893 		}
1894 
1895 		D3DPRESENT_PARAMETERS present = *presentParameters;
1896 
1897 		if(!swapChain[0])
1898 		{
1899 			swapChain[0] = new Direct3DSwapChain8(this, &present);
1900 			swapChain[0]->bind();
1901 		}
1902 		else
1903 		{
1904 			swapChain[0]->reset(&present);
1905 		}
1906 
1907 		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : focusWindow;
1908 
1909 		int width = 0;
1910 		int height = 0;
1911 
1912 		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
1913 		{
1914 			RECT rectangle;
1915 			GetClientRect(windowHandle, &rectangle);
1916 
1917 			width = rectangle.right - rectangle.left;
1918 			height = rectangle.bottom - rectangle.top;
1919 		}
1920 		else
1921 		{
1922 			width = presentParameters->BackBufferWidth;
1923 			height = presentParameters->BackBufferHeight;
1924 		}
1925 
1926 		if(presentParameters->EnableAutoDepthStencil != FALSE)
1927 		{
1928 			depthStencil = new Direct3DSurface8(this, this, width, height, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->AutoDepthStencilFormat == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL);
1929 			depthStencil->bind();
1930 		}
1931 
1932 		IDirect3DSurface8 *renderTarget;
1933 		swapChain[0]->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget);
1934 		SetRenderTarget(renderTarget, depthStencil);
1935 		renderTarget->Release();
1936 
1937 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE);
1938 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1939 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
1940 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1941 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1942 		SetRenderState(D3DRS_LASTPIXEL, TRUE);
1943 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
1944 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
1945 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
1946 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1947 		SetRenderState(D3DRS_ALPHAREF, 0);
1948 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
1949 		SetRenderState(D3DRS_DITHERENABLE, FALSE);
1950 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1951 		SetRenderState(D3DRS_FOGENABLE, FALSE);
1952 		SetRenderState(D3DRS_SPECULARENABLE, FALSE);
1953 	//	SetRenderState(D3DRS_ZVISIBLE, 0);
1954 		SetRenderState(D3DRS_FOGCOLOR, 0);
1955 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1956 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f));
1957 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f));
1958 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f));
1959 		SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);
1960 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
1961 		SetRenderState(D3DRS_ZBIAS, 0);
1962 		SetRenderState(D3DRS_STENCILENABLE, FALSE);
1963 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
1964 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
1965 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
1966 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1967 		SetRenderState(D3DRS_STENCILREF, 0);
1968 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
1969 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
1970 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
1971 		SetRenderState(D3DRS_WRAP0, 0);
1972 		SetRenderState(D3DRS_WRAP1, 0);
1973 		SetRenderState(D3DRS_WRAP2, 0);
1974 		SetRenderState(D3DRS_WRAP3, 0);
1975 		SetRenderState(D3DRS_WRAP4, 0);
1976 		SetRenderState(D3DRS_WRAP5, 0);
1977 		SetRenderState(D3DRS_WRAP6, 0);
1978 		SetRenderState(D3DRS_WRAP7, 0);
1979 		SetRenderState(D3DRS_CLIPPING, TRUE);
1980 		SetRenderState(D3DRS_LIGHTING, TRUE);
1981 		SetRenderState(D3DRS_AMBIENT, 0);
1982 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1983 		SetRenderState(D3DRS_COLORVERTEX, TRUE);
1984 		SetRenderState(D3DRS_LOCALVIEWER, TRUE);
1985 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
1986 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
1987 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
1988 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
1989 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
1990 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
1991 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1992 		SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
1993 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f));
1994 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.0f));
1995 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
1996 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
1997 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f));
1998 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
1999 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
2000 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
2001 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
2002 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
2003 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
2004 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f));
2005 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
2006 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F);
2007 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f));
2008 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
2009 		SetRenderState(D3DRS_POSITIONORDER, D3DORDER_CUBIC);
2010 		SetRenderState(D3DRS_NORMALORDER, D3DORDER_LINEAR);
2011 
2012 		for(int i = 0; i < 8; i++)
2013 		{
2014 			SetTexture(i, 0);
2015 
2016 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE);
2017 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned
2018 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
2019 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE);
2020 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned
2021 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
2022 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f));
2023 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f));
2024 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f));
2025 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f));
2026 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
2027 			SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
2028 			SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
2029 			SetTextureStageState(i, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
2030 			SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
2031 			SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2032 			SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT);
2033 			SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
2034 			SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
2035 			SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
2036 			SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
2037 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f));
2038 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f));
2039 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2040 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
2041 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
2042 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
2043 		}
2044 
2045 		currentPalette = 0xFFFF;
2046 
2047 		delete cursor;
2048 		showCursor = false;
2049 
2050 		return D3D_OK;
2051 	}
2052 
ResourceManagerDiscardBytes(unsigned long bytes)2053 	long Direct3DDevice8::ResourceManagerDiscardBytes(unsigned long bytes)
2054 	{
2055 		TRACE("");
2056 
2057 		return D3D_OK;
2058 	}
2059 
SetClipPlane(unsigned long index,const float * plane)2060 	long Direct3DDevice8::SetClipPlane(unsigned long index, const float *plane)
2061 	{
2062 		TRACE("");
2063 
2064 		if(!plane || index > 6)
2065 		{
2066 			return INVALIDCALL();
2067 		}
2068 
2069 		if(!recordState)
2070 		{
2071 			this->plane[index][0] = plane[0];
2072 			this->plane[index][1] = plane[1];
2073 			this->plane[index][2] = plane[2];
2074 			this->plane[index][3] = plane[3];
2075 
2076 			renderer->setClipPlane(index, plane);
2077 		}
2078 		else
2079 		{
2080 			stateRecorder.back()->setClipPlane(index, plane);
2081 		}
2082 
2083 		return D3D_OK;
2084 	}
2085 
SetClipStatus(const D3DCLIPSTATUS8 * clipStatus)2086 	long Direct3DDevice8::SetClipStatus(const D3DCLIPSTATUS8 *clipStatus)
2087 	{
2088 		TRACE("");
2089 
2090 		if(!clipStatus)
2091 		{
2092 			return INVALIDCALL();
2093 		}
2094 
2095 		this->clipStatus = *clipStatus;
2096 
2097 		UNIMPLEMENTED();
2098 
2099 		return D3D_OK;
2100 	}
2101 
SetCurrentTexturePalette(unsigned int paletteNumber)2102 	long Direct3DDevice8::SetCurrentTexturePalette(unsigned int paletteNumber)
2103 	{
2104 		TRACE("");
2105 
2106 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end())
2107 		{
2108 			return INVALIDCALL();
2109 		}
2110 
2111 		if(!recordState)
2112 		{
2113 			currentPalette = paletteNumber;
2114 
2115 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2116 		}
2117 		else
2118 		{
2119 			stateRecorder.back()->setCurrentTexturePalette(paletteNumber);
2120 		}
2121 
2122 		return D3D_OK;
2123 	}
2124 
SetCursorPosition(int x,int y,unsigned long flags)2125 	void Direct3DDevice8::SetCursorPosition(int x, int y, unsigned long flags)
2126 	{
2127 		TRACE("");
2128 
2129 		POINT point = {x, y};
2130 		HWND window = focusWindow ? focusWindow : presentParameters.hDeviceWindow;
2131 		ScreenToClient(window, &point);
2132 
2133 		sw::FrameBuffer::setCursorPosition(point.x, point.y);
2134 	}
2135 
SetCursorProperties(unsigned int x0,unsigned int y0,IDirect3DSurface8 * cursorBitmap)2136 	long Direct3DDevice8::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface8 *cursorBitmap)
2137 	{
2138 		TRACE("");
2139 
2140 		if(!cursorBitmap)
2141 		{
2142 			return INVALIDCALL();
2143 		}
2144 
2145 		D3DSURFACE_DESC desc;
2146 		D3DLOCKED_RECT lock;
2147 
2148 		cursorBitmap->GetDesc(&desc);
2149 		cursorBitmap->LockRect(&lock, 0, 0);
2150 
2151 		delete cursor;
2152 		cursor = sw::Surface::create(0, desc.Width, desc.Height, 1, sw::FORMAT_A8R8G8B8, false, false);
2153 
2154 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
2155 		memcpy(buffer, lock.pBits, desc.Width * desc.Height * sizeof(unsigned int));
2156 		cursor->unlockExternal();
2157 
2158 		cursorBitmap->UnlockRect();
2159 
2160 		sw::FrameBuffer::setCursorOrigin(x0, y0);
2161 
2162 		bindCursor();
2163 
2164 		return D3D_OK;
2165 	}
2166 
SetGammaRamp(unsigned long flags,const D3DGAMMARAMP * ramp)2167 	void Direct3DDevice8::SetGammaRamp(unsigned long flags, const D3DGAMMARAMP *ramp)
2168 	{
2169 		TRACE("");
2170 
2171 		if(!ramp)
2172 		{
2173 			return;
2174 		}
2175 
2176 		swapChain[0]->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE);
2177 
2178 		return;
2179 	}
2180 
SetLight(unsigned long index,const D3DLIGHT8 * light)2181 	long Direct3DDevice8::SetLight(unsigned long index, const D3DLIGHT8 *light)
2182 	{
2183 		TRACE("");
2184 
2185 		if(!light)
2186 		{
2187 			return INVALIDCALL();
2188 		}
2189 
2190 		if(!recordState)
2191 		{
2192 			this->light[index] = *light;
2193 
2194 			lightsDirty = true;
2195 		}
2196 		else
2197 		{
2198 			stateRecorder.back()->setLight(index, light);
2199 		}
2200 
2201 		return D3D_OK;
2202 	}
2203 
SetMaterial(const D3DMATERIAL8 * material)2204 	long Direct3DDevice8::SetMaterial(const D3DMATERIAL8 *material)
2205 	{
2206 		TRACE("");
2207 
2208 		if(!material)
2209 		{
2210 			return INVALIDCALL();   // FIXME: Correct behaviour?
2211 		}
2212 
2213 		if(!recordState)
2214 		{
2215 			this->material = *material;
2216 
2217 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a));
2218 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a));
2219 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a));
2220 			renderer->setMaterialShininess(material->Power);
2221 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a));
2222 		}
2223 		else
2224 		{
2225 			stateRecorder.back()->setMaterial(material);
2226 		}
2227 
2228 		return D3D_OK;
2229 	}
2230 
SetPaletteEntries(unsigned int paletteNumber,const PALETTEENTRY * entries)2231 	long Direct3DDevice8::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries)
2232 	{
2233 		TRACE("");
2234 
2235 		if(paletteNumber > 0xFFFF || !entries)
2236 		{
2237 			return INVALIDCALL();
2238 		}
2239 
2240 		for(int i = 0; i < 256; i++)
2241 		{
2242 			palette[paletteNumber].entry[i] = entries[i];
2243 		}
2244 
2245 		if(paletteNumber == currentPalette)
2246 		{
2247 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2248 		}
2249 
2250 		return D3D_OK;
2251 	}
2252 
SetPixelShader(unsigned long handle)2253 	long Direct3DDevice8::SetPixelShader(unsigned long handle)
2254 	{
2255 		TRACE("");
2256 
2257 		if(!recordState)
2258 		{
2259 			if(pixelShader[handle])
2260 			{
2261 				pixelShader[handle]->bind();
2262 			}
2263 
2264 			if(pixelShader[pixelShaderHandle])
2265 			{
2266 				pixelShader[pixelShaderHandle]->unbind();
2267 			}
2268 
2269 			pixelShaderHandle = handle;
2270 
2271 			if(handle != 0)
2272 			{
2273 				renderer->setPixelShader(pixelShader[handle]->getPixelShader());
2274 			}
2275 			else
2276 			{
2277 				renderer->setPixelShader(0);
2278 			}
2279 		}
2280 		else
2281 		{
2282 			stateRecorder.back()->setPixelShader(handle);
2283 		}
2284 
2285 		return D3D_OK;
2286 	}
2287 
SetPixelShaderConstant(unsigned long startRegister,const void * constantData,unsigned long count)2288 	long Direct3DDevice8::SetPixelShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count)
2289 	{
2290 		TRACE("");
2291 
2292 		if(!recordState)
2293 		{
2294 			for(unsigned int i = 0; i < count; i++)
2295 			{
2296 				pixelShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0];
2297 				pixelShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1];
2298 				pixelShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2];
2299 				pixelShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3];
2300 			}
2301 
2302 			renderer->setPixelShaderConstantF(startRegister, (const float*)constantData, count);
2303 		}
2304 		else
2305 		{
2306 			stateRecorder.back()->setPixelShaderConstant(startRegister, constantData, count);
2307 		}
2308 
2309 		return D3D_OK;
2310 	}
2311 
SetRenderState(D3DRENDERSTATETYPE state,unsigned long value)2312 	long Direct3DDevice8::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value)
2313 	{
2314 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value);
2315 
2316 		if(state < D3DRS_ZENABLE || state > D3DRS_NORMALORDER)
2317 		{
2318 			return D3D_OK;   // FIXME: Warning
2319 		}
2320 
2321 		if(!recordState)
2322 		{
2323 			if(!init && renderState[state] == value)
2324 			{
2325 				return D3D_OK;
2326 			}
2327 
2328 			renderState[state] = value;
2329 
2330 			switch(state)
2331 			{
2332 			case D3DRS_ZENABLE:
2333 				switch(value)
2334 				{
2335 				case D3DZB_TRUE:
2336 				case D3DZB_USEW:
2337 					renderer->setDepthBufferEnable(true);
2338 					break;
2339 				case D3DZB_FALSE:
2340 					renderer->setDepthBufferEnable(false);
2341 					break;
2342 				default:
2343 					ASSERT(false);
2344 				}
2345 				break;
2346 			case D3DRS_FILLMODE:
2347 				switch(value)
2348 				{
2349 				case D3DFILL_POINT:
2350 					renderer->setFillMode(sw::FILL_VERTEX);
2351 					break;
2352 				case D3DFILL_WIREFRAME:
2353 					renderer->setFillMode(sw::FILL_WIREFRAME);
2354 					break;
2355 				case D3DFILL_SOLID:
2356 					renderer->setFillMode(sw::FILL_SOLID);
2357 					break;
2358 				default:
2359 					ASSERT(false);
2360 				}
2361 				break;
2362 			case D3DRS_SHADEMODE:
2363 				switch(value)
2364 				{
2365 				case D3DSHADE_FLAT:
2366 					renderer->setShadingMode(sw::SHADING_FLAT);
2367 					break;
2368 				case D3DSHADE_GOURAUD:
2369 					renderer->setShadingMode(sw::SHADING_GOURAUD);
2370 					break;
2371 				case D3DSHADE_PHONG:
2372 					// FIXME: Unimplemented (should set gouraud)?
2373 					break;
2374 				default:
2375 					ASSERT(false);
2376 				}
2377 				break;
2378 			case D3DRS_LINEPATTERN:
2379 				if(!init) UNIMPLEMENTED();
2380 				break;
2381 			case D3DRS_ZWRITEENABLE:
2382 				renderer->setDepthWriteEnable(value != FALSE);
2383 				break;
2384 			case D3DRS_ALPHATESTENABLE:
2385 				renderer->setAlphaTestEnable(value != FALSE);
2386 				break;
2387 			case D3DRS_LASTPIXEL:
2388 				if(!init) UNIMPLEMENTED();
2389 				break;
2390 			case D3DRS_SRCBLEND:
2391 				switch(value)
2392 				{
2393 				case D3DBLEND_ZERO:
2394 					renderer->setSourceBlendFactor(sw::BLEND_ZERO);
2395 					break;
2396 				case D3DBLEND_ONE:
2397 					renderer->setSourceBlendFactor(sw::BLEND_ONE);
2398 					break;
2399 				case D3DBLEND_SRCCOLOR:
2400 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE);
2401 					break;
2402 				case D3DBLEND_INVSRCCOLOR:
2403 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE);
2404 					break;
2405 				case D3DBLEND_SRCALPHA:
2406 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
2407 					break;
2408 				case D3DBLEND_INVSRCALPHA:
2409 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
2410 					break;
2411 				case D3DBLEND_DESTALPHA:
2412 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA);
2413 					break;
2414 				case D3DBLEND_INVDESTALPHA:
2415 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA);
2416 					break;
2417 				case D3DBLEND_DESTCOLOR:
2418 					renderer->setSourceBlendFactor(sw::BLEND_DEST);
2419 					break;
2420 				case D3DBLEND_INVDESTCOLOR:
2421 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST);
2422 					break;
2423 				case D3DBLEND_SRCALPHASAT:
2424 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT);
2425 					break;
2426 				case D3DBLEND_BOTHSRCALPHA:
2427 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
2428 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
2429 					break;
2430 				case D3DBLEND_BOTHINVSRCALPHA:
2431 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
2432 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
2433 					break;
2434 				default:
2435 					ASSERT(false);
2436 				}
2437 				break;
2438 			case D3DRS_DESTBLEND:
2439 				switch(value)
2440 				{
2441 				case D3DBLEND_ZERO:
2442 					renderer->setDestBlendFactor(sw::BLEND_ZERO);
2443 					break;
2444 				case D3DBLEND_ONE:
2445 					renderer->setDestBlendFactor(sw::BLEND_ONE);
2446 					break;
2447 				case D3DBLEND_SRCCOLOR:
2448 					renderer->setDestBlendFactor(sw::BLEND_SOURCE);
2449 					break;
2450 				case D3DBLEND_INVSRCCOLOR:
2451 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE);
2452 					break;
2453 				case D3DBLEND_SRCALPHA:
2454 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
2455 					break;
2456 				case D3DBLEND_INVSRCALPHA:
2457 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
2458 					break;
2459 				case D3DBLEND_DESTALPHA:
2460 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA);
2461 					break;
2462 				case D3DBLEND_INVDESTALPHA:
2463 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA);
2464 					break;
2465 				case D3DBLEND_DESTCOLOR:
2466 					renderer->setDestBlendFactor(sw::BLEND_DEST);
2467 					break;
2468 				case D3DBLEND_INVDESTCOLOR:
2469 					renderer->setDestBlendFactor(sw::BLEND_INVDEST);
2470 					break;
2471 				case D3DBLEND_SRCALPHASAT:
2472 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT);
2473 					break;
2474 				case D3DBLEND_BOTHSRCALPHA:
2475 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
2476 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
2477 					break;
2478 				case D3DBLEND_BOTHINVSRCALPHA:
2479 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
2480 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
2481 					break;
2482 				default:
2483 					ASSERT(false);
2484 				}
2485 				break;
2486 			case D3DRS_CULLMODE:
2487 				switch(value)
2488 				{
2489 				case D3DCULL_NONE:
2490 					renderer->setCullMode(sw::CULL_NONE);
2491 					break;
2492 				case D3DCULL_CCW:
2493 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE);
2494 					break;
2495 				case D3DCULL_CW:
2496 					renderer->setCullMode(sw::CULL_CLOCKWISE);
2497 					break;
2498 				default:
2499 					ASSERT(false);
2500 				}
2501 				break;
2502 			case D3DRS_ZFUNC:
2503 				switch(value)
2504 				{
2505 				case D3DCMP_NEVER:
2506 					renderer->setDepthCompare(sw::DEPTH_NEVER);
2507 					break;
2508 				case D3DCMP_LESS:
2509 					renderer->setDepthCompare(sw::DEPTH_LESS);
2510 					break;
2511 				case D3DCMP_EQUAL:
2512 					renderer->setDepthCompare(sw::DEPTH_EQUAL);
2513 					break;
2514 				case D3DCMP_LESSEQUAL:
2515 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL);
2516 					break;
2517 				case D3DCMP_GREATER:
2518 					renderer->setDepthCompare(sw::DEPTH_GREATER);
2519 					break;
2520 				case D3DCMP_NOTEQUAL:
2521 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL);
2522 					break;
2523 				case D3DCMP_GREATEREQUAL:
2524 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL);
2525 					break;
2526 				case D3DCMP_ALWAYS:
2527 					renderer->setDepthCompare(sw::DEPTH_ALWAYS);
2528 					break;
2529 				default:
2530 					ASSERT(false);
2531 				}
2532 				break;
2533 			case D3DRS_ALPHAREF:
2534 				renderer->setAlphaReference(value & 0x000000FF);
2535 				break;
2536 			case D3DRS_ALPHAFUNC:
2537 				switch(value)
2538 				{
2539 				case D3DCMP_NEVER:
2540 					renderer->setAlphaCompare(sw::ALPHA_NEVER);
2541 					break;
2542 				case D3DCMP_LESS:
2543 					renderer->setAlphaCompare(sw::ALPHA_LESS);
2544 					break;
2545 				case D3DCMP_EQUAL:
2546 					renderer->setAlphaCompare(sw::ALPHA_EQUAL);
2547 					break;
2548 				case D3DCMP_LESSEQUAL:
2549 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL);
2550 					break;
2551 				case D3DCMP_GREATER:
2552 					renderer->setAlphaCompare(sw::ALPHA_GREATER);
2553 					break;
2554 				case D3DCMP_NOTEQUAL:
2555 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL);
2556 					break;
2557 				case D3DCMP_GREATEREQUAL:
2558 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL);
2559 					break;
2560 				case D3DCMP_ALWAYS:
2561 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS);
2562 					break;
2563 				default:
2564 					ASSERT(false);
2565 				}
2566 				break;
2567 			case D3DRS_DITHERENABLE:
2568 			//	if(!init && value == 1) UNIMPLEMENTED();   // FIXME: Unimplemented
2569 				break;
2570 			case D3DRS_ALPHABLENDENABLE:
2571 				renderer->setAlphaBlendEnable(value != FALSE);
2572 				break;
2573 			case D3DRS_FOGENABLE:
2574 				renderer->setFogEnable(value != FALSE);
2575 				break;
2576 			case D3DRS_ZVISIBLE:
2577 				break;   // Not supported
2578 			case D3DRS_FOGCOLOR:
2579 				renderer->setFogColor(value);
2580 				break;
2581 			case D3DRS_FOGTABLEMODE:
2582 				switch(value)
2583 				{
2584 				case D3DFOG_NONE:
2585 					renderer->setPixelFogMode(sw::FOG_NONE);
2586 					break;
2587 				case D3DFOG_LINEAR:
2588 					renderer->setPixelFogMode(sw::FOG_LINEAR);
2589 					break;
2590 				case D3DFOG_EXP:
2591 					renderer->setPixelFogMode(sw::FOG_EXP);
2592 					break;
2593 				case D3DFOG_EXP2:
2594 					renderer->setPixelFogMode(sw::FOG_EXP2);
2595 					break;
2596 				default:
2597 					ASSERT(false);
2598 				}
2599 				break;
2600 			case D3DRS_FOGSTART:
2601 				renderer->setFogStart((float&)value);
2602 				break;
2603 			case D3DRS_FOGEND:
2604 				renderer->setFogEnd((float&)value);
2605 				break;
2606 			case D3DRS_FOGDENSITY:
2607 				renderer->setFogDensity((float&)value);
2608 				break;
2609 			case D3DRS_EDGEANTIALIAS:
2610 				if(!init) if(value != FALSE) UNIMPLEMENTED();
2611 				break;
2612 			case D3DRS_ZBIAS:
2613 				renderer->setDepthBias(-2.0e-6f * value);
2614 				renderer->setSlopeDepthBias(0.0f);
2615 				break;
2616 			case D3DRS_RANGEFOGENABLE:
2617 				renderer->setRangeFogEnable(value != FALSE);
2618 				break;
2619 			case D3DRS_SPECULARENABLE:
2620 				renderer->setSpecularEnable(value != FALSE);
2621 				break;
2622 			case D3DRS_STENCILENABLE:
2623 				renderer->setStencilEnable(value != FALSE);
2624 				break;
2625 			case D3DRS_STENCILFAIL:
2626 				switch(value)
2627 				{
2628 				case D3DSTENCILOP_KEEP:
2629 					renderer->setStencilFailOperation(sw::OPERATION_KEEP);
2630 					break;
2631 				case D3DSTENCILOP_ZERO:
2632 					renderer->setStencilFailOperation(sw::OPERATION_ZERO);
2633 					break;
2634 				case D3DSTENCILOP_REPLACE:
2635 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE);
2636 					break;
2637 				case D3DSTENCILOP_INCRSAT:
2638 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT);
2639 					break;
2640 				case D3DSTENCILOP_DECRSAT:
2641 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT);
2642 					break;
2643 				case D3DSTENCILOP_INVERT:
2644 					renderer->setStencilFailOperation(sw::OPERATION_INVERT);
2645 					break;
2646 				case D3DSTENCILOP_INCR:
2647 					renderer->setStencilFailOperation(sw::OPERATION_INCR);
2648 					break;
2649 				case D3DSTENCILOP_DECR:
2650 					renderer->setStencilFailOperation(sw::OPERATION_DECR);
2651 					break;
2652 				default:
2653 					ASSERT(false);
2654 				}
2655 				break;
2656 			case D3DRS_STENCILZFAIL:
2657 				switch(value)
2658 				{
2659 				case D3DSTENCILOP_KEEP:
2660 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP);
2661 					break;
2662 				case D3DSTENCILOP_ZERO:
2663 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO);
2664 					break;
2665 				case D3DSTENCILOP_REPLACE:
2666 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE);
2667 					break;
2668 				case D3DSTENCILOP_INCRSAT:
2669 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT);
2670 					break;
2671 				case D3DSTENCILOP_DECRSAT:
2672 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT);
2673 					break;
2674 				case D3DSTENCILOP_INVERT:
2675 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT);
2676 					break;
2677 				case D3DSTENCILOP_INCR:
2678 					renderer->setStencilZFailOperation(sw::OPERATION_INCR);
2679 					break;
2680 				case D3DSTENCILOP_DECR:
2681 					renderer->setStencilZFailOperation(sw::OPERATION_DECR);
2682 					break;
2683 				default:
2684 					ASSERT(false);
2685 				}
2686 				break;
2687 			case D3DRS_STENCILPASS:
2688 				switch(value)
2689 				{
2690 				case D3DSTENCILOP_KEEP:
2691 					renderer->setStencilPassOperation(sw::OPERATION_KEEP);
2692 					break;
2693 				case D3DSTENCILOP_ZERO:
2694 					renderer->setStencilPassOperation(sw::OPERATION_ZERO);
2695 					break;
2696 				case D3DSTENCILOP_REPLACE:
2697 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE);
2698 					break;
2699 				case D3DSTENCILOP_INCRSAT:
2700 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT);
2701 					break;
2702 				case D3DSTENCILOP_DECRSAT:
2703 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT);
2704 					break;
2705 				case D3DSTENCILOP_INVERT:
2706 					renderer->setStencilPassOperation(sw::OPERATION_INVERT);
2707 					break;
2708 				case D3DSTENCILOP_INCR:
2709 					renderer->setStencilPassOperation(sw::OPERATION_INCR);
2710 					break;
2711 				case D3DSTENCILOP_DECR:
2712 					renderer->setStencilPassOperation(sw::OPERATION_DECR);
2713 					break;
2714 				default:
2715 					ASSERT(false);
2716 				}
2717 				break;
2718 			case D3DRS_STENCILFUNC:
2719 				switch(value)
2720 				{
2721 				case D3DCMP_NEVER:
2722 					renderer->setStencilCompare(sw::STENCIL_NEVER);
2723 					break;
2724 				case D3DCMP_LESS:
2725 					renderer->setStencilCompare(sw::STENCIL_LESS);
2726 					break;
2727 				case D3DCMP_EQUAL:
2728 					renderer->setStencilCompare(sw::STENCIL_EQUAL);
2729 					break;
2730 				case D3DCMP_LESSEQUAL:
2731 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL);
2732 					break;
2733 				case D3DCMP_GREATER:
2734 					renderer->setStencilCompare(sw::STENCIL_GREATER);
2735 					break;
2736 				case D3DCMP_NOTEQUAL:
2737 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL);
2738 					break;
2739 				case D3DCMP_GREATEREQUAL:
2740 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL);
2741 					break;
2742 				case D3DCMP_ALWAYS:
2743 					renderer->setStencilCompare(sw::STENCIL_ALWAYS);
2744 					break;
2745 				default:
2746 					ASSERT(false);
2747 				}
2748 				break;
2749 			case D3DRS_STENCILREF:
2750 				renderer->setStencilReference(value);
2751 				renderer->setStencilReferenceCCW(value);
2752 				break;
2753 			case D3DRS_STENCILMASK:
2754 				renderer->setStencilMask(value);
2755 				renderer->setStencilMaskCCW(value);
2756 				break;
2757 			case D3DRS_STENCILWRITEMASK:
2758 				renderer->setStencilWriteMask(value);
2759 				renderer->setStencilWriteMaskCCW(value);
2760 				break;
2761 			case D3DRS_TEXTUREFACTOR:
2762 				renderer->setTextureFactor(value);
2763 				break;
2764 			case D3DRS_WRAP0:
2765 				renderer->setTextureWrap(0, value);
2766 				break;
2767 			case D3DRS_WRAP1:
2768 				renderer->setTextureWrap(1, value);
2769 				break;
2770 			case D3DRS_WRAP2:
2771 				renderer->setTextureWrap(2, value);
2772 				break;
2773 			case D3DRS_WRAP3:
2774 				renderer->setTextureWrap(3, value);
2775 				break;
2776 			case D3DRS_WRAP4:
2777 				renderer->setTextureWrap(4, value);
2778 				break;
2779 			case D3DRS_WRAP5:
2780 				renderer->setTextureWrap(5, value);
2781 				break;
2782 			case D3DRS_WRAP6:
2783 				renderer->setTextureWrap(6, value);
2784 				break;
2785 			case D3DRS_WRAP7:
2786 				renderer->setTextureWrap(7, value);
2787 				break;
2788 			case D3DRS_CLIPPING:
2789 				// Ignored, clipping is always performed
2790 				break;
2791 			case D3DRS_LIGHTING:
2792 				renderer->setLightingEnable(value != FALSE);
2793 				break;
2794 			case D3DRS_AMBIENT:
2795 				renderer->setGlobalAmbient(value);
2796 				break;
2797 			case D3DRS_FOGVERTEXMODE:
2798 				switch(value)
2799 				{
2800 				case D3DFOG_NONE:
2801 					renderer->setVertexFogMode(sw::FOG_NONE);
2802 					break;
2803 				case D3DFOG_LINEAR:
2804 					renderer->setVertexFogMode(sw::FOG_LINEAR);
2805 					break;
2806 				case D3DFOG_EXP:
2807 					renderer->setVertexFogMode(sw::FOG_EXP);
2808 					break;
2809 				case D3DFOG_EXP2:
2810 					renderer->setVertexFogMode(sw::FOG_EXP2);
2811 					break;
2812 				default:
2813 					ASSERT(false);
2814 				}
2815 				break;
2816 			case D3DRS_COLORVERTEX:
2817 				renderer->setColorVertexEnable(value != FALSE);
2818 				break;
2819 			case D3DRS_LOCALVIEWER:
2820 				renderer->setLocalViewer(value != FALSE);
2821 				break;
2822 			case D3DRS_NORMALIZENORMALS:
2823 				renderer->setNormalizeNormals(value != FALSE);
2824 				break;
2825 			case D3DRS_DIFFUSEMATERIALSOURCE:
2826 				switch(value)
2827 				{
2828 				case D3DMCS_MATERIAL:
2829 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);
2830 					break;
2831 				case D3DMCS_COLOR1:
2832 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
2833 					break;
2834 				case D3DMCS_COLOR2:
2835 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2);
2836 					break;
2837 				default:
2838 					ASSERT(false);
2839 				}
2840 				break;
2841 			case D3DRS_SPECULARMATERIALSOURCE:
2842 				switch(value)
2843 				{
2844 				case D3DMCS_MATERIAL:
2845 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
2846 					break;
2847 				case D3DMCS_COLOR1:
2848 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1);
2849 					break;
2850 				case D3DMCS_COLOR2:
2851 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2);
2852 					break;
2853 				default:
2854 					ASSERT(false);
2855 				}
2856 				break;
2857 			case D3DRS_AMBIENTMATERIALSOURCE:
2858 				switch(value)
2859 				{
2860 				case D3DMCS_MATERIAL:
2861 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
2862 					break;
2863 				case D3DMCS_COLOR1:
2864 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1);
2865 					break;
2866 				case D3DMCS_COLOR2:
2867 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2);
2868 					break;
2869 				default:
2870 					ASSERT(false);
2871 				}
2872 				break;
2873 			case D3DRS_EMISSIVEMATERIALSOURCE:
2874 				switch(value)
2875 				{
2876 				case D3DMCS_MATERIAL:
2877 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
2878 					break;
2879 				case D3DMCS_COLOR1:
2880 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1);
2881 					break;
2882 				case D3DMCS_COLOR2:
2883 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2);
2884 					break;
2885 				default:
2886 					ASSERT(false);
2887 				}
2888 				break;
2889 			case D3DRS_VERTEXBLEND:
2890 				switch(value)
2891 				{
2892 				case D3DVBF_DISABLE:
2893 					renderer->setVertexBlendMatrixCount(0);
2894 					break;
2895 				case D3DVBF_1WEIGHTS:
2896 					renderer->setVertexBlendMatrixCount(2);
2897 					break;
2898 				case D3DVBF_2WEIGHTS:
2899 					renderer->setVertexBlendMatrixCount(3);
2900 					break;
2901 				case D3DVBF_3WEIGHTS:
2902 					renderer->setVertexBlendMatrixCount(4);
2903 					break;
2904 				case D3DVBF_TWEENING:
2905 					UNIMPLEMENTED();
2906 					break;
2907 				case D3DVBF_0WEIGHTS:
2908 					renderer->setVertexBlendMatrixCount(1);
2909 					break;
2910 				default:
2911 					ASSERT(false);
2912 				}
2913 				break;
2914 			case D3DRS_CLIPPLANEENABLE:
2915 				renderer->setClipFlags(value);
2916 				break;
2917 			case D3DRS_SOFTWAREVERTEXPROCESSING:
2918 				break;
2919 			case D3DRS_POINTSIZE:
2920 				renderer->setPointSize((float&)value);
2921 				break;
2922 			case D3DRS_POINTSIZE_MIN:
2923 				renderer->setPointSizeMin((float&)value);
2924 				break;
2925 			case D3DRS_POINTSPRITEENABLE:
2926 				renderer->setPointSpriteEnable(value != FALSE);
2927 				break;
2928 			case D3DRS_POINTSCALEENABLE:
2929 				renderer->setPointScaleEnable(value != FALSE);
2930 				break;
2931 			case D3DRS_POINTSCALE_A:
2932 				renderer->setPointScaleA((float&)value);
2933 				break;
2934 			case D3DRS_POINTSCALE_B:
2935 				renderer->setPointScaleB((float&)value);
2936 				break;
2937 			case D3DRS_POINTSCALE_C:
2938 				renderer->setPointScaleC((float&)value);
2939 				break;
2940 			case D3DRS_MULTISAMPLEANTIALIAS:
2941 			//	if(!init) UNIMPLEMENTED();
2942 				break;
2943 			case D3DRS_MULTISAMPLEMASK:
2944 				SetRenderTarget(renderTarget, depthStencil);   // Sets the multi-sample mask, if maskable
2945 				break;
2946 			case D3DRS_PATCHEDGESTYLE:
2947 			//	if(!init) UNIMPLEMENTED();
2948 				break;
2949 			case D3DRS_PATCHSEGMENTS:
2950 			//	UNIMPLEMENTED();   // FIXME
2951 				break;
2952 			case D3DRS_DEBUGMONITORTOKEN:
2953 				if(!init) UNIMPLEMENTED();
2954 				break;
2955 			case D3DRS_POINTSIZE_MAX:
2956 				renderer->setPointSizeMax((float&)value);
2957 				break;
2958 			case D3DRS_INDEXEDVERTEXBLENDENABLE:
2959 				renderer->setIndexedVertexBlendEnable(value != FALSE);
2960 				break;
2961 			case D3DRS_COLORWRITEENABLE:
2962 				renderer->setColorWriteMask(0, value);
2963 				break;
2964 			case D3DRS_TWEENFACTOR:
2965 				if(!init) UNIMPLEMENTED();
2966 				break;
2967 			case D3DRS_BLENDOP:
2968 				switch(value)
2969 				{
2970 				case D3DBLENDOP_ADD:
2971 					renderer->setBlendOperation(sw::BLENDOP_ADD);
2972 					break;
2973 				case D3DBLENDOP_SUBTRACT:
2974 					renderer->setBlendOperation(sw::BLENDOP_SUB);
2975 					break;
2976 				case D3DBLENDOP_REVSUBTRACT:
2977 					renderer->setBlendOperation(sw::BLENDOP_INVSUB);
2978 					break;
2979 				case D3DBLENDOP_MIN:
2980 					renderer->setBlendOperation(sw::BLENDOP_MIN);
2981 					break;
2982 				case D3DBLENDOP_MAX:
2983 					renderer->setBlendOperation(sw::BLENDOP_MAX);
2984 					break;
2985 				default:
2986 					ASSERT(false);
2987 				}
2988 				break;
2989 			case D3DRS_POSITIONORDER:
2990 				if(!init) UNIMPLEMENTED();
2991 				break;
2992 			case D3DRS_NORMALORDER:
2993 				if(!init) UNIMPLEMENTED();
2994 				break;
2995 			default:
2996 				ASSERT(false);
2997 			}
2998 		}
2999 		else   // stateRecorder
3000 		{
3001 			stateRecorder.back()->setRenderState(state, value);
3002 		}
3003 
3004 		return D3D_OK;
3005 	}
3006 
SetRenderTarget(IDirect3DSurface8 * newRenderTarget,IDirect3DSurface8 * newDepthStencil)3007 	long Direct3DDevice8::SetRenderTarget(IDirect3DSurface8 *newRenderTarget, IDirect3DSurface8 *newDepthStencil)
3008 	{
3009 		TRACE("");
3010 
3011 		Direct3DSurface8 *renderTarget = static_cast<Direct3DSurface8*>(newRenderTarget);
3012 
3013 		if(renderTarget)   // FIXME: Check for D3DUSAGE_RENDERTARGET
3014 		{
3015 			renderTarget->bind();
3016 		}
3017 
3018 		if(this->renderTarget)
3019 		{
3020 			this->renderTarget->unbind();
3021 		}
3022 
3023 		this->renderTarget = renderTarget;
3024 
3025 		Direct3DSurface8 *depthStencil = static_cast<Direct3DSurface8*>(newDepthStencil);
3026 
3027 		if(depthStencil)   // FIXME: Check for D3DUSAGE_DEPTHSTENCIL and D3DPOOL_DEFAULT
3028 		{
3029 			depthStencil->bind();
3030 		}
3031 
3032 		if(this->depthStencil)
3033 		{
3034 			this->depthStencil->unbind();
3035 		}
3036 
3037 		this->depthStencil = depthStencil;
3038 
3039 		// Reset viewport to size of current render target
3040 		D3DSURFACE_DESC renderTargetDesc;
3041 		renderTarget->GetDesc(&renderTargetDesc);
3042 
3043 		D3DVIEWPORT8 viewport;
3044 		viewport.X = 0;
3045 		viewport.Y = 0;
3046 		viewport.Width = renderTargetDesc.Width;
3047 		viewport.Height = renderTargetDesc.Height;
3048 		viewport.MinZ = 0;
3049 		viewport.MaxZ = 1;
3050 
3051 		SetViewport(&viewport);
3052 
3053 		// Set the multi-sample mask, if maskable
3054 		if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE)
3055 		{
3056 			renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]);
3057 		}
3058 		else
3059 		{
3060 			renderer->setMultiSampleMask(0xFFFFFFFF);
3061 		}
3062 
3063 		renderer->setRenderTarget(0, renderTarget);
3064 		renderer->setDepthBuffer(depthStencil);
3065 		renderer->setStencilBuffer(depthStencil);
3066 
3067 		return D3D_OK;
3068 	}
3069 
SetStreamSource(unsigned int stream,IDirect3DVertexBuffer8 * iVertexBuffer,unsigned int stride)3070 	long Direct3DDevice8::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer8 *iVertexBuffer, unsigned int stride)
3071 	{
3072 		TRACE("");
3073 
3074 		Direct3DVertexBuffer8 *vertexBuffer = static_cast<Direct3DVertexBuffer8*>(iVertexBuffer);
3075 
3076 		if(!recordState)
3077 		{
3078 			if(vertexBuffer)
3079 			{
3080 				vertexBuffer->bind();
3081 			}
3082 
3083 			if(dataStream[stream])
3084 			{
3085 				dataStream[stream]->unbind();
3086 				streamStride[stream] = 0;
3087 			}
3088 
3089 			dataStream[stream] = vertexBuffer;
3090 			streamStride[stream] = stride;
3091 		}
3092 		else
3093 		{
3094 			stateRecorder.back()->setStreamSource(stream, vertexBuffer, stride);
3095 		}
3096 
3097 		return D3D_OK;
3098 	}
3099 
SetTexture(unsigned long stage,IDirect3DBaseTexture8 * iBaseTexture)3100 	long Direct3DDevice8::SetTexture(unsigned long stage, IDirect3DBaseTexture8 *iBaseTexture)
3101 	{
3102 		TRACE("");
3103 
3104 		if(stage >= 8)
3105 		{
3106 			return INVALIDCALL();
3107 		}
3108 
3109 		Direct3DBaseTexture8 *baseTexture = dynamic_cast<Direct3DBaseTexture8*>(iBaseTexture);
3110 
3111 		if(!recordState)
3112 		{
3113 			if(texture[stage] == baseTexture)
3114 			{
3115 				return D3D_OK;
3116 			}
3117 
3118 			if(baseTexture)
3119 			{
3120 				baseTexture->bind();
3121 			}
3122 
3123 			if(texture[stage])
3124 			{
3125 				texture[stage]->unbind();
3126 			}
3127 
3128 			texture[stage] = baseTexture;
3129 		}
3130 		else
3131 		{
3132 			stateRecorder.back()->setTexture(stage, baseTexture);
3133 		}
3134 
3135 		return D3D_OK;
3136 	}
3137 
SetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long value)3138 	long Direct3DDevice8::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value)
3139 	{
3140 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value);
3141 
3142 		if(stage >= 8 || type < 0 || type > D3DTSS_RESULTARG)
3143 		{
3144 			return INVALIDCALL();
3145 		}
3146 
3147 		if(!recordState)
3148 		{
3149 			if(!init && textureStageState[stage][type] == value)
3150 			{
3151 				return D3D_OK;
3152 			}
3153 
3154 			textureStageState[stage][type] = value;
3155 
3156 			switch(type)
3157 			{
3158 			case D3DTSS_COLOROP:
3159 				switch(value)
3160 				{
3161 				case D3DTOP_DISABLE:
3162 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE);
3163 					break;
3164 				case D3DTOP_SELECTARG1:
3165 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1);
3166 					break;
3167 				case D3DTOP_SELECTARG2:
3168 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2);
3169 					break;
3170 				case D3DTOP_MODULATE:
3171 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE);
3172 					break;
3173 				case D3DTOP_MODULATE2X:
3174 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X);
3175 					break;
3176 				case D3DTOP_MODULATE4X:
3177 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X);
3178 					break;
3179 				case D3DTOP_ADD:
3180 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD);
3181 					break;
3182 				case D3DTOP_ADDSIGNED:
3183 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED);
3184 					break;
3185 				case D3DTOP_ADDSIGNED2X:
3186 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
3187 					break;
3188 				case D3DTOP_SUBTRACT:
3189 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT);
3190 					break;
3191 				case D3DTOP_ADDSMOOTH:
3192 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH);
3193 					break;
3194 				case D3DTOP_BLENDDIFFUSEALPHA:
3195 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
3196 					break;
3197 				case D3DTOP_BLENDTEXTUREALPHA:
3198 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
3199 					break;
3200 				case D3DTOP_BLENDFACTORALPHA:
3201 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
3202 					break;
3203 				case D3DTOP_BLENDTEXTUREALPHAPM:
3204 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
3205 					break;
3206 				case D3DTOP_BLENDCURRENTALPHA:
3207 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
3208 					break;
3209 				case D3DTOP_PREMODULATE:
3210 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE);
3211 					break;
3212 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
3213 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
3214 					break;
3215 				case D3DTOP_MODULATECOLOR_ADDALPHA:
3216 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
3217 					break;
3218 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
3219 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
3220 					break;
3221 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
3222 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
3223 					break;
3224 				case D3DTOP_BUMPENVMAP:
3225 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP);
3226 					break;
3227 				case D3DTOP_BUMPENVMAPLUMINANCE:
3228 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
3229 					break;
3230 				case D3DTOP_DOTPRODUCT3:
3231 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3);
3232 					break;
3233 				case D3DTOP_MULTIPLYADD:
3234 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD);
3235 					break;
3236 				case D3DTOP_LERP:
3237 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP);
3238 					break;
3239 				default:
3240 					ASSERT(false);
3241 				}
3242 				break;
3243 			case D3DTSS_COLORARG1:
3244 				switch(value & D3DTA_SELECTMASK)
3245 				{
3246 				case D3DTA_DIFFUSE:
3247 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
3248 					break;
3249 				case D3DTA_CURRENT:
3250 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT);
3251 					break;
3252 				case D3DTA_TEXTURE:
3253 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
3254 					break;
3255 				case D3DTA_TFACTOR:
3256 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
3257 					break;
3258 				case D3DTA_SPECULAR:
3259 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
3260 					break;
3261 				case D3DTA_TEMP:
3262 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP);
3263 					break;
3264 				default:
3265 					ASSERT(false);
3266 				}
3267 
3268 				switch(value & ~D3DTA_SELECTMASK)
3269 				{
3270 				case 0:
3271 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR);
3272 					break;
3273 				case D3DTA_COMPLEMENT:
3274 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3275 					break;
3276 				case D3DTA_ALPHAREPLICATE:
3277 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
3278 					break;
3279 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3280 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
3281 					break;
3282 				default:
3283 					ASSERT(false);
3284 				}
3285 				break;
3286 			case D3DTSS_COLORARG2:
3287 				switch(value & D3DTA_SELECTMASK)
3288 				{
3289 				case D3DTA_DIFFUSE:
3290 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
3291 					break;
3292 				case D3DTA_CURRENT:
3293 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT);
3294 					break;
3295 				case D3DTA_TEXTURE:
3296 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
3297 					break;
3298 				case D3DTA_TFACTOR:
3299 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
3300 					break;
3301 				case D3DTA_SPECULAR:
3302 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
3303 					break;
3304 				case D3DTA_TEMP:
3305 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP);
3306 					break;
3307 				default:
3308 					ASSERT(false);
3309 				}
3310 
3311 				switch(value & ~D3DTA_SELECTMASK)
3312 				{
3313 				case 0:
3314 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR);
3315 					break;
3316 				case D3DTA_COMPLEMENT:
3317 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3318 					break;
3319 				case D3DTA_ALPHAREPLICATE:
3320 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
3321 					break;
3322 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3323 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
3324 					break;
3325 				default:
3326 					ASSERT(false);
3327 				}
3328 				break;
3329 			case D3DTSS_ALPHAOP:
3330 				switch(value)
3331 				{
3332 				case D3DTOP_DISABLE:
3333 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE);
3334 					break;
3335 				case D3DTOP_SELECTARG1:
3336 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1);
3337 					break;
3338 				case D3DTOP_SELECTARG2:
3339 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2);
3340 					break;
3341 				case D3DTOP_MODULATE:
3342 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE);
3343 					break;
3344 				case D3DTOP_MODULATE2X:
3345 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X);
3346 					break;
3347 				case D3DTOP_MODULATE4X:
3348 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X);
3349 					break;
3350 				case D3DTOP_ADD:
3351 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD);
3352 					break;
3353 				case D3DTOP_ADDSIGNED:
3354 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED);
3355 					break;
3356 				case D3DTOP_ADDSIGNED2X:
3357 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
3358 					break;
3359 				case D3DTOP_SUBTRACT:
3360 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT);
3361 					break;
3362 				case D3DTOP_ADDSMOOTH:
3363 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH);
3364 					break;
3365 				case D3DTOP_BLENDDIFFUSEALPHA:
3366 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
3367 					break;
3368 				case D3DTOP_BLENDTEXTUREALPHA:
3369 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
3370 					break;
3371 				case D3DTOP_BLENDFACTORALPHA:
3372 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
3373 					break;
3374 				case D3DTOP_BLENDTEXTUREALPHAPM:
3375 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
3376 					break;
3377 				case D3DTOP_BLENDCURRENTALPHA:
3378 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
3379 					break;
3380 				case D3DTOP_PREMODULATE:
3381 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE);
3382 					break;
3383 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
3384 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
3385 					break;
3386 				case D3DTOP_MODULATECOLOR_ADDALPHA:
3387 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
3388 					break;
3389 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
3390 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
3391 					break;
3392 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
3393 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
3394 					break;
3395 				case D3DTOP_BUMPENVMAP:
3396 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP);
3397 					break;
3398 				case D3DTOP_BUMPENVMAPLUMINANCE:
3399 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
3400 					break;
3401 				case D3DTOP_DOTPRODUCT3:
3402 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3);
3403 					break;
3404 				case D3DTOP_MULTIPLYADD:
3405 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD);
3406 					break;
3407 				case D3DTOP_LERP:
3408 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP);
3409 					break;
3410 				default:
3411 					ASSERT(false);
3412 				}
3413 				break;
3414 			case D3DTSS_ALPHAARG1:
3415 				switch(value & D3DTA_SELECTMASK)
3416 				{
3417 				case D3DTA_DIFFUSE:
3418 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
3419 					break;
3420 				case D3DTA_CURRENT:
3421 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
3422 					break;
3423 				case D3DTA_TEXTURE:
3424 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
3425 					break;
3426 				case D3DTA_TFACTOR:
3427 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
3428 					break;
3429 				case D3DTA_SPECULAR:
3430 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
3431 					break;
3432 				case D3DTA_TEMP:
3433 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
3434 					break;
3435 				default:
3436 					ASSERT(false);
3437 				}
3438 
3439 				switch(value & ~D3DTA_SELECTMASK)
3440 				{
3441 				case 0:
3442 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
3443 					break;
3444 				case D3DTA_COMPLEMENT:
3445 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3446 					break;
3447 				case D3DTA_ALPHAREPLICATE:
3448 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
3449 					break;
3450 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3451 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
3452 					break;
3453 				default:
3454 					ASSERT(false);
3455 				}
3456 				break;
3457 			case D3DTSS_ALPHAARG2:
3458 				switch(value & D3DTA_SELECTMASK)
3459 				{
3460 				case D3DTA_DIFFUSE:
3461 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
3462 					break;
3463 				case D3DTA_CURRENT:
3464 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
3465 					break;
3466 				case D3DTA_TEXTURE:
3467 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
3468 					break;
3469 				case D3DTA_TFACTOR:
3470 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
3471 					break;
3472 				case D3DTA_SPECULAR:
3473 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
3474 					break;
3475 				case D3DTA_TEMP:
3476 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
3477 					break;
3478 				default:
3479 					ASSERT(false);
3480 				}
3481 
3482 				switch(value & ~D3DTA_SELECTMASK)
3483 				{
3484 				case 0:
3485 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
3486 					break;
3487 				case D3DTA_COMPLEMENT:
3488 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3489 					break;
3490 				case D3DTA_ALPHAREPLICATE:
3491 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
3492 					break;
3493 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3494 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
3495 					break;
3496 				default:
3497 					ASSERT(false);
3498 				}
3499 				break;
3500 			case D3DTSS_BUMPENVMAT00:
3501 				renderer->setBumpmapMatrix(stage, 0, (float&)value);
3502 				break;
3503 			case D3DTSS_BUMPENVMAT01:
3504 				renderer->setBumpmapMatrix(stage, 1, (float&)value);
3505 				break;
3506 			case D3DTSS_BUMPENVMAT10:
3507 				renderer->setBumpmapMatrix(stage, 2, (float&)value);
3508 				break;
3509 			case D3DTSS_BUMPENVMAT11:
3510 				renderer->setBumpmapMatrix(stage, 3, (float&)value);
3511 				break;
3512 			case D3DTSS_TEXCOORDINDEX:
3513 				renderer->setTexCoordIndex(stage, value & 0xFFFF);
3514 
3515 				switch(value & 0xFFFF0000)
3516 				{
3517 				case D3DTSS_TCI_PASSTHRU:
3518 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU);
3519 					break;
3520 				case D3DTSS_TCI_CAMERASPACENORMAL:
3521 					renderer->setTexCoordIndex(stage, stage);
3522 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL);
3523 					break;
3524 				case D3DTSS_TCI_CAMERASPACEPOSITION:
3525 					renderer->setTexCoordIndex(stage, stage);
3526 					renderer->setTexGen(stage, sw::TEXGEN_POSITION);
3527 					break;
3528 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3529 					renderer->setTexCoordIndex(stage, stage);
3530 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION);
3531 					break;
3532 				default:
3533 					ASSERT(false);
3534 				}
3535 				break;
3536 			case D3DTSS_ADDRESSU:
3537 				switch(value)
3538 				{
3539 				case D3DTADDRESS_WRAP:
3540 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
3541 					break;
3542 				case D3DTADDRESS_MIRROR:
3543 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
3544 					break;
3545 				case D3DTADDRESS_CLAMP:
3546 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
3547 					break;
3548 				case D3DTADDRESS_BORDER:
3549 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
3550 					break;
3551 				case D3DTADDRESS_MIRRORONCE:
3552 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
3553 					break;
3554 				default:
3555 					ASSERT(false);
3556 				}
3557 				break;
3558 			case D3DTSS_ADDRESSV:
3559 				switch(value)
3560 				{
3561 				case D3DTADDRESS_WRAP:
3562 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
3563 					break;
3564 				case D3DTADDRESS_MIRROR:
3565 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
3566 					break;
3567 				case D3DTADDRESS_CLAMP:
3568 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
3569 					break;
3570 				case D3DTADDRESS_BORDER:
3571 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
3572 					break;
3573 				case D3DTADDRESS_MIRRORONCE:
3574 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
3575 					break;
3576 				default:
3577 					ASSERT(false);
3578 				}
3579 				break;
3580 			case D3DTSS_BORDERCOLOR:
3581 				renderer->setBorderColor(sw::SAMPLER_PIXEL, stage, value);
3582 				break;
3583 			case D3DTSS_MAGFILTER:
3584 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
3585 				switch(value)
3586 				{
3587 				case D3DTEXF_NONE:
3588 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
3589 					break;
3590 				case D3DTEXF_POINT:
3591 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
3592 					break;
3593 				case D3DTEXF_LINEAR:
3594 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);
3595 					break;
3596 				case D3DTEXF_ANISOTROPIC:
3597 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC);
3598 					break;
3599 				case D3DTEXF_FLATCUBIC:
3600 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
3601 					break;
3602 				case D3DTEXF_GAUSSIANCUBIC:
3603 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
3604 					break;
3605 				default:
3606 					return INVALIDCALL();
3607 				};
3608 				break;
3609 			case D3DTSS_MINFILTER:
3610 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
3611 				switch(value)
3612 				{
3613 				case D3DTEXF_NONE:
3614 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
3615 					break;
3616 				case D3DTEXF_POINT:
3617 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
3618 					break;
3619 				case D3DTEXF_LINEAR:
3620 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);
3621 					break;
3622 				case D3DTEXF_ANISOTROPIC:
3623 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC);
3624 					break;
3625 				case D3DTEXF_FLATCUBIC:
3626 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
3627 					break;
3628 				case D3DTEXF_GAUSSIANCUBIC:
3629 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
3630 					break;
3631 				default:
3632 					return INVALIDCALL();
3633 				};
3634 				break;
3635 			case D3DTSS_MIPFILTER:
3636 				switch(value)
3637 				{
3638 				case D3DTEXF_NONE:
3639 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_NONE);
3640 					break;
3641 				case D3DTEXF_POINT:
3642 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_POINT);
3643 					break;
3644 				case D3DTEXF_LINEAR:
3645 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);
3646 					break;
3647 				case D3DTEXF_ANISOTROPIC:
3648 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
3649 					break;
3650 				case D3DTEXF_FLATCUBIC:
3651 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
3652 					break;
3653 				case D3DTEXF_GAUSSIANCUBIC:
3654 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
3655 					break;
3656 				default:
3657 					return INVALIDCALL();
3658 				};
3659 				break;
3660 			case D3DTSS_MIPMAPLODBIAS:
3661 				{
3662 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes
3663 					renderer->setMipmapLOD(sw::SAMPLER_PIXEL, stage, LOD);
3664 				}
3665 				break;
3666 			case D3DTSS_MAXMIPLEVEL:
3667 				break;
3668 			case D3DTSS_MAXANISOTROPY:
3669 				renderer->setMaxAnisotropy(sw::SAMPLER_PIXEL, stage, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy));
3670 				break;
3671 			case D3DTSS_BUMPENVLSCALE:
3672 				renderer->setLuminanceScale(stage, (float&)value);
3673 				break;
3674 			case D3DTSS_BUMPENVLOFFSET:
3675 				renderer->setLuminanceOffset(stage, (float&)value);
3676 				break;
3677 			case D3DTSS_TEXTURETRANSFORMFLAGS:
3678 				switch(value & ~D3DTTFF_PROJECTED)
3679 				{
3680 				case D3DTTFF_DISABLE:
3681 					renderer->setTextureTransform(stage, 0, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
3682 					break;
3683 				case D3DTTFF_COUNT1:
3684 					renderer->setTextureTransform(stage, 1, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
3685 					break;
3686 				case D3DTTFF_COUNT2:
3687 					renderer->setTextureTransform(stage, 2, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
3688 					break;
3689 				case D3DTTFF_COUNT3:
3690 					renderer->setTextureTransform(stage, 3, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
3691 					break;
3692 				case D3DTTFF_COUNT4:
3693 					renderer->setTextureTransform(stage, 4, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
3694 					break;
3695 				default:
3696 					ASSERT(false);
3697 				}
3698 				break;
3699 			case D3DTSS_ADDRESSW:
3700 				switch(value)
3701 				{
3702 				case D3DTADDRESS_WRAP:
3703 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
3704 					break;
3705 				case D3DTADDRESS_MIRROR:
3706 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
3707 					break;
3708 				case D3DTADDRESS_CLAMP:
3709 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
3710 					break;
3711 				case D3DTADDRESS_BORDER:
3712 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
3713 					break;
3714 				case D3DTADDRESS_MIRRORONCE:
3715 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
3716 					break;
3717 				default:
3718 					ASSERT(false);
3719 				}
3720 				break;
3721 			case D3DTSS_COLORARG0:
3722 				switch(value & D3DTA_SELECTMASK)
3723 				{
3724 				case D3DTA_CURRENT:
3725 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT);
3726 					break;
3727 				case D3DTA_DIFFUSE:
3728 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
3729 					break;
3730 				case D3DTA_SPECULAR:
3731 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
3732 					break;
3733 				case D3DTA_TEMP:
3734 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP);
3735 					break;
3736 				case D3DTA_TEXTURE:
3737 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
3738 					break;
3739 				case D3DTA_TFACTOR:
3740 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
3741 					break;
3742 				default:
3743 					ASSERT(false);
3744 				}
3745 
3746 				switch(value & ~D3DTA_SELECTMASK)
3747 				{
3748 				case 0:
3749 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR);
3750 					break;
3751 				case D3DTA_COMPLEMENT:
3752 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3753 					break;
3754 				case D3DTA_ALPHAREPLICATE:
3755 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
3756 					break;
3757 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3758 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
3759 					break;
3760 				default:
3761 					ASSERT(false);
3762 				}
3763 				break;
3764 			case D3DTSS_ALPHAARG0:
3765 				switch(value & D3DTA_SELECTMASK)
3766 				{
3767 				case D3DTA_DIFFUSE:
3768 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
3769 					break;
3770 				case D3DTA_CURRENT:
3771 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
3772 					break;
3773 				case D3DTA_TEXTURE:
3774 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
3775 					break;
3776 				case D3DTA_TFACTOR:
3777 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
3778 					break;
3779 				case D3DTA_SPECULAR:
3780 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
3781 					break;
3782 				case D3DTA_TEMP:
3783 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
3784 					break;
3785 				default:
3786 					ASSERT(false);
3787 				}
3788 
3789 				switch(value & ~D3DTA_SELECTMASK)
3790 				{
3791 				case 0:
3792 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
3793 					break;
3794 				case D3DTA_COMPLEMENT:
3795 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
3796 					break;
3797 				case D3DTA_ALPHAREPLICATE:
3798 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
3799 					break;
3800 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
3801 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
3802 					break;
3803 				default:
3804 					ASSERT(false);
3805 				}
3806 				break;
3807 			case D3DTSS_RESULTARG:
3808 				switch(value & D3DTA_SELECTMASK)
3809 				{
3810 				case D3DTA_CURRENT:
3811 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT);
3812 					break;
3813 				case D3DTA_TEMP:
3814 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP);
3815 					break;
3816 				default:
3817 					ASSERT(false);
3818 				}
3819 				break;
3820 			default:
3821 				ASSERT(false);
3822 			}
3823 		}
3824 		else   // stateRecorder
3825 		{
3826 			stateRecorder.back()->setTextureStageState(stage, type, value);
3827 		}
3828 
3829 		return D3D_OK;
3830 	}
3831 
SetTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)3832 	long Direct3DDevice8::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
3833 	{
3834 		TRACE("");
3835 
3836 		if(!matrix || state < 0 || state > 511)
3837 		{
3838 			return INVALIDCALL();
3839 		}
3840 
3841 		if(!recordState)
3842 		{
3843 			this->matrix[state] = *matrix;
3844 
3845 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
3846 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
3847 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
3848 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
3849 
3850 			switch(state)
3851 			{
3852 			case D3DTS_WORLD:
3853 				renderer->setModelMatrix(M);
3854 				break;
3855 			case D3DTS_VIEW:
3856 				renderer->setViewMatrix(M);
3857 				break;
3858 			case D3DTS_PROJECTION:
3859 				renderer->setProjectionMatrix(M);
3860 				break;
3861 			case D3DTS_TEXTURE0:
3862 				renderer->setTextureMatrix(0, M);
3863 				break;
3864 			case D3DTS_TEXTURE1:
3865 				renderer->setTextureMatrix(1, M);
3866 				break;
3867 			case D3DTS_TEXTURE2:
3868 				renderer->setTextureMatrix(2, M);
3869 				break;
3870 			case D3DTS_TEXTURE3:
3871 				renderer->setTextureMatrix(3, M);
3872 				break;
3873 			case D3DTS_TEXTURE4:
3874 				renderer->setTextureMatrix(4, M);
3875 				break;
3876 			case D3DTS_TEXTURE5:
3877 				renderer->setTextureMatrix(5, M);
3878 				break;
3879 			case D3DTS_TEXTURE6:
3880 				renderer->setTextureMatrix(6, M);
3881 				break;
3882 			case D3DTS_TEXTURE7:
3883 				renderer->setTextureMatrix(7, M);
3884 				break;
3885 			default:
3886 				if(state > 256 && state < 512)
3887 				{
3888 					renderer->setModelMatrix(M, state - 256);
3889 				}
3890 				else ASSERT(false);
3891 			}
3892 		}
3893 		else   // stateRecorder
3894 		{
3895 			stateRecorder.back()->setTransform(state, matrix);
3896 		}
3897 
3898 		return D3D_OK;
3899 	}
3900 
SetVertexShader(unsigned long handle)3901 	long Direct3DDevice8::SetVertexShader(unsigned long handle)
3902 	{
3903 		TRACE("");
3904 
3905 		if(!recordState)
3906 		{
3907 			if(handle & 0x00000001)
3908 			{
3909 				unsigned int index = handle >> 16;
3910 
3911 				if(vertexShader[index])
3912 				{
3913 					vertexShader[index]->bind();
3914 				}
3915 
3916 				if(vertexShader[vertexShaderHandle >> 16])
3917 				{
3918 					vertexShader[vertexShaderHandle >> 16]->unbind();
3919 				}
3920 
3921 				vertexShaderHandle = handle;
3922 
3923 				Direct3DVertexShader8 *shader = vertexShader[index];
3924 				renderer->setVertexShader(shader->getVertexShader());
3925 				declaration = shader->getDeclaration();
3926 
3927 				FVF = 0;
3928 			}
3929 			else
3930 			{
3931 				renderer->setVertexShader(0);
3932 				declaration = 0;
3933 
3934 				FVF = handle;
3935 			}
3936 		}
3937 		else
3938 		{
3939 			stateRecorder.back()->setVertexShader(handle);
3940 		}
3941 
3942 		return D3D_OK;
3943 	}
3944 
SetVertexShaderConstant(unsigned long startRegister,const void * constantData,unsigned long count)3945 	long Direct3DDevice8::SetVertexShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count)
3946 	{
3947 		TRACE("");
3948 
3949 		if(!constantData)
3950 		{
3951 			return INVALIDCALL();
3952 		}
3953 
3954 		if(!recordState)
3955 		{
3956 			for(unsigned int i = 0; i < count; i++)
3957 			{
3958 				vertexShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0];
3959 				vertexShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1];
3960 				vertexShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2];
3961 				vertexShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3];
3962 			}
3963 
3964 			renderer->setVertexShaderConstantF(startRegister, (const float*)constantData, count);
3965 		}
3966 		else
3967 		{
3968 			stateRecorder.back()->setVertexShaderConstant(startRegister, constantData, count);
3969 		}
3970 
3971 		return D3D_OK;
3972 	}
3973 
SetViewport(const D3DVIEWPORT8 * viewport)3974 	long Direct3DDevice8::SetViewport(const D3DVIEWPORT8 *viewport)
3975 	{
3976 		TRACE("");
3977 
3978 		if(!viewport)
3979 		{
3980 			return INVALIDCALL();
3981 		}
3982 
3983 		if(!recordState)
3984 		{
3985 			this->viewport = *viewport;
3986 		}
3987 		else
3988 		{
3989 			stateRecorder.back()->setViewport(viewport);
3990 		}
3991 
3992 		return D3D_OK;
3993 	}
3994 
ShowCursor(int show)3995 	int Direct3DDevice8::ShowCursor(int show)
3996 	{
3997 		TRACE("");
3998 
3999 		int oldValue = showCursor ? TRUE : FALSE;
4000 
4001 		showCursor = show != FALSE && cursor;
4002 
4003 		bindCursor();
4004 
4005 		return oldValue;
4006 	}
4007 
TestCooperativeLevel()4008 	long Direct3DDevice8::TestCooperativeLevel()
4009 	{
4010 		TRACE("");
4011 
4012 		return D3D_OK;
4013 	}
4014 
UpdateTexture(IDirect3DBaseTexture8 * sourceTexture,IDirect3DBaseTexture8 * destinationTexture)4015 	long Direct3DDevice8::UpdateTexture(IDirect3DBaseTexture8 *sourceTexture, IDirect3DBaseTexture8 *destinationTexture)
4016 	{
4017 		TRACE("");
4018 
4019 		if(!sourceTexture || !destinationTexture)
4020 		{
4021 			return INVALIDCALL();
4022 		}
4023 
4024 		D3DRESOURCETYPE type = sourceTexture->GetType();
4025 
4026 		if(type != destinationTexture->GetType())
4027 		{
4028 			return INVALIDCALL();
4029 		}
4030 
4031 		switch(type)
4032 		{
4033 		case D3DRTYPE_TEXTURE:
4034 			{
4035 				IDirect3DTexture8 *source;
4036 				IDirect3DTexture8 *dest;
4037 
4038 				sourceTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&source);
4039 				destinationTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&dest);
4040 
4041 				ASSERT(source && dest);
4042 
4043 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)
4044 				{
4045 					IDirect3DSurface8 *sourceSurface;
4046 					IDirect3DSurface8 *destinationSurface;
4047 
4048 					source->GetSurfaceLevel(level, &sourceSurface);
4049 					dest->GetSurfaceLevel(level, &destinationSurface);
4050 
4051 					updateSurface(sourceSurface, 0, destinationSurface, 0);
4052 
4053 					sourceSurface->Release();
4054 					destinationSurface->Release();
4055 				}
4056 
4057 				source->Release();
4058 				dest->Release();
4059 			}
4060 			break;
4061 		case D3DRTYPE_VOLUMETEXTURE:
4062 			{
4063 				IDirect3DVolumeTexture8 *source;
4064 				IDirect3DVolumeTexture8 *dest;
4065 
4066 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&source);
4067 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&dest);
4068 
4069 				ASSERT(source && dest);
4070 
4071 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
4072 				{
4073 					IDirect3DVolume8 *sourceVolume;
4074 					IDirect3DVolume8 *destinationVolume;
4075 
4076 					source->GetVolumeLevel(level, &sourceVolume);
4077 					dest->GetVolumeLevel(level, &destinationVolume);
4078 
4079 					updateVolume(sourceVolume, destinationVolume);
4080 
4081 					sourceVolume->Release();
4082 					destinationVolume->Release();
4083 				}
4084 
4085 				source->Release();
4086 				dest->Release();
4087 			}
4088 			break;
4089 		case D3DRTYPE_CUBETEXTURE:
4090 			{
4091 				IDirect3DCubeTexture8 *source;
4092 				IDirect3DCubeTexture8 *dest;
4093 
4094 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&source);
4095 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&dest);
4096 
4097 				ASSERT(source && dest);
4098 
4099 				for(int face = 0; face < 6; face++)
4100 				{
4101 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)
4102 					{
4103 						IDirect3DSurface8 *sourceSurface;
4104 						IDirect3DSurface8 *destinationSurface;
4105 
4106 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface);
4107 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface);
4108 
4109 						updateSurface(sourceSurface, 0, destinationSurface, 0);
4110 
4111 						sourceSurface->Release();
4112 						destinationSurface->Release();
4113 					}
4114 				}
4115 
4116 				source->Release();
4117 				dest->Release();
4118 			}
4119 			break;
4120 		default:
4121 			ASSERT(false);
4122 		}
4123 
4124 		return D3D_OK;
4125 	}
4126 
ValidateDevice(unsigned long * numPasses)4127 	long Direct3DDevice8::ValidateDevice(unsigned long *numPasses)
4128 	{
4129 		TRACE("");
4130 
4131 		if(!numPasses)
4132 		{
4133 			return INVALIDCALL();
4134 		}
4135 
4136 		*numPasses = 1;
4137 
4138 		return D3D_OK;
4139 	}
4140 
updateSurface(IDirect3DSurface8 * sourceSurface,const RECT * sourceRect,IDirect3DSurface8 * destinationSurface,const POINT * destPoint)4141 	long Direct3DDevice8::updateSurface(IDirect3DSurface8 *sourceSurface, const RECT *sourceRect, IDirect3DSurface8 *destinationSurface, const POINT *destPoint)
4142 	{
4143 		TRACE("IDirect3DSurface8 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface8 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint);
4144 
4145 		if(!sourceSurface || !destinationSurface)
4146 		{
4147 			return INVALIDCALL();
4148 		}
4149 
4150 		D3DSURFACE_DESC sourceDescription;
4151 		D3DSURFACE_DESC destinationDescription;
4152 
4153 		sourceSurface->GetDesc(&sourceDescription);
4154 		destinationSurface->GetDesc(&destinationDescription);
4155 
4156 		RECT sRect;
4157 		RECT dRect;
4158 
4159 		if(sourceRect && destPoint)
4160 		{
4161 			sRect.left = sourceRect->left;
4162 			sRect.top = sourceRect->top;
4163 			sRect.right = sourceRect->right;
4164 			sRect.bottom = sourceRect->bottom;
4165 
4166 			dRect.left = destPoint->x;
4167 			dRect.top = destPoint->y;
4168 			dRect.right = destPoint->x + sourceRect->right - sourceRect->left;
4169 			dRect.bottom = destPoint->y + sourceRect->bottom - sourceRect->top;
4170 		}
4171 		else
4172 		{
4173 			sRect.left = 0;
4174 			sRect.top = 0;
4175 			sRect.right = sourceDescription.Width;
4176 			sRect.bottom = sourceDescription.Height;
4177 
4178 			dRect.left = 0;
4179 			dRect.top = 0;
4180 			dRect.right = destinationDescription.Width;
4181 			dRect.bottom = destinationDescription.Height;
4182 		}
4183 
4184 		int sWidth = sRect.right - sRect.left;
4185 		int sHeight = sRect.bottom - sRect.top;
4186 
4187 		int dWidth = dRect.right - dRect.left;
4188 		int dHeight = dRect.bottom - dRect.top;
4189 
4190 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE ||
4191 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE ||
4192 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags
4193 		// destinationDescription.Pool != D3DPOOL_DEFAULT ||
4194 		   sourceDescription.Format != destinationDescription.Format ||
4195 		   sWidth  != dWidth ||
4196 		   sHeight != dHeight)
4197 		{
4198 			return INVALIDCALL();
4199 		}
4200 
4201 		D3DLOCKED_RECT sourceLock;
4202 		D3DLOCKED_RECT destinationLock;
4203 
4204 		sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY);
4205 		destinationSurface->LockRect(&destinationLock, &dRect, 0);
4206 
4207 		unsigned int width;
4208 		unsigned int height;
4209 		unsigned int bytes;
4210 
4211 		switch(sourceDescription.Format)
4212 		{
4213 		case D3DFMT_DXT1:
4214 			width = (dWidth + 3) / 4;
4215 			height = (dHeight + 3) / 4;
4216 			bytes = width * 8;   // 64 bit per 4x4 block
4217 			break;
4218 		case D3DFMT_DXT2:
4219 		case D3DFMT_DXT3:
4220 		case D3DFMT_DXT4:
4221 		case D3DFMT_DXT5:
4222 			width = (dWidth + 3) / 4;
4223 			height = (dHeight + 3) / 4;
4224 			bytes = width * 16;   // 128 bit per 4x4 block
4225 			break;
4226 		default:
4227 			width = dWidth;
4228 			height = dHeight;
4229 			bytes = width * Direct3DSurface8::bytes(sourceDescription.Format);
4230 		}
4231 
4232 		for(unsigned int y = 0; y < height; y++)
4233 		{
4234 			memcpy(destinationLock.pBits, sourceLock.pBits, bytes);
4235 
4236 			(byte*&)sourceLock.pBits += sourceLock.Pitch;
4237 			(byte*&)destinationLock.pBits += destinationLock.Pitch;
4238 		}
4239 
4240 		sourceSurface->UnlockRect();
4241 		destinationSurface->UnlockRect();
4242 
4243 		return D3D_OK;
4244 	}
4245 
SetIndices(IDirect3DIndexBuffer8 * iIndexBuffer,unsigned int baseVertexIndex)4246 	long Direct3DDevice8::SetIndices(IDirect3DIndexBuffer8 *iIndexBuffer, unsigned int baseVertexIndex)
4247 	{
4248 		TRACE("");
4249 
4250 		Direct3DIndexBuffer8 *indexBuffer = static_cast<Direct3DIndexBuffer8*>(iIndexBuffer);
4251 
4252 		if(!recordState)
4253 		{
4254 			if(indexBuffer)
4255 			{
4256 				indexBuffer->bind();
4257 			}
4258 
4259 			if(this->indexData)
4260 			{
4261 				this->indexData->unbind();
4262 			}
4263 
4264 			this->indexData = indexBuffer;
4265 			this->baseVertexIndex = baseVertexIndex;
4266 		}
4267 		else
4268 		{
4269 			stateRecorder.back()->setIndices(indexBuffer, baseVertexIndex);
4270 		}
4271 
4272 		return D3D_OK;
4273 	}
4274 
FVFStride(unsigned long FVF)4275 	int Direct3DDevice8::FVFStride(unsigned long FVF)
4276 	{
4277 		int stride = 0;
4278 
4279 		switch(FVF & D3DFVF_POSITION_MASK)
4280 		{
4281 		case D3DFVF_XYZ:	stride += 12;	break;
4282 		case D3DFVF_XYZRHW:	stride += 16;	break;
4283 		case D3DFVF_XYZB1:	stride += 16;	break;
4284 		case D3DFVF_XYZB2:	stride += 20;	break;
4285 		case D3DFVF_XYZB3:	stride += 24;	break;
4286 		case D3DFVF_XYZB4:	stride += 28;	break;
4287 		case D3DFVF_XYZB5:	stride += 32;	break;
4288 		}
4289 
4290 		if(FVF & D3DFVF_NORMAL)		stride += 12;
4291 		if(FVF & D3DFVF_PSIZE)		stride += 4;
4292 		if(FVF & D3DFVF_DIFFUSE)	stride += 4;
4293 		if(FVF & D3DFVF_SPECULAR)	stride += 4;
4294 
4295 		switch((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
4296 		{
4297 		case 8: stride += 4 + 4 * ((1 + (FVF >> 30)) % 4);
4298 		case 7: stride += 4 + 4 * ((1 + (FVF >> 28)) % 4);
4299 		case 6: stride += 4 + 4 * ((1 + (FVF >> 26)) % 4);
4300 		case 5: stride += 4 + 4 * ((1 + (FVF >> 24)) % 4);
4301 		case 4: stride += 4 + 4 * ((1 + (FVF >> 22)) % 4);
4302 		case 3: stride += 4 + 4 * ((1 + (FVF >> 20)) % 4);
4303 		case 2: stride += 4 + 4 * ((1 + (FVF >> 18)) % 4);
4304 		case 1: stride += 4 + 4 * ((1 + (FVF >> 16)) % 4);
4305 		case 0: break;
4306 		default:
4307 			ASSERT(false);
4308 		}
4309 
4310 		return stride;
4311 	}
4312 
typeStride(unsigned char type)4313 	int Direct3DDevice8::typeStride(unsigned char type)
4314 	{
4315 		static const int LUT[] =
4316 		{
4317 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.)
4318 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.)
4319 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.)
4320 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float
4321 			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)
4322 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte
4323 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.)
4324 			8 	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short
4325 		};
4326 
4327 		if(type <= 7)
4328 		{
4329 			return LUT[type];
4330 		}
4331 		else ASSERT(false);
4332 
4333 		return 0;
4334 	}
4335 
bindData(Direct3DIndexBuffer8 * indexBuffer,int base)4336 	bool Direct3DDevice8::bindData(Direct3DIndexBuffer8 *indexBuffer, int base)
4337 	{
4338 		if(!bindViewport())
4339 		{
4340 			return false;   // Zero-area target region
4341 		}
4342 
4343 		bindTextures();
4344 		bindStreams(base);
4345 		bindIndexBuffer(indexBuffer);
4346 		bindLights();
4347 
4348 		return true;
4349 	}
4350 
bindStreams(int base)4351 	void Direct3DDevice8::bindStreams(int base)
4352 	{
4353 		renderer->resetInputStreams((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW);
4354 
4355 		int stride;
4356 
4357 		if(!declaration)   // Fixed-function vertex pipeline
4358 		{
4359 			const void *buffer = 0;
4360 
4361 			ASSERT(dataStream[0]);
4362 
4363 			Direct3DVertexBuffer8 *stream = dataStream[0];
4364 			sw::Resource *resource = stream->getResource();
4365 			buffer = (char*)resource->data();
4366 			stride = FVFStride(FVF);
4367 
4368 			ASSERT(stride == streamStride[0]);   // FIXME
4369 			ASSERT(buffer && stride);
4370 
4371 			(char*&)buffer += stride * base;
4372 
4373 			sw::Stream attribute(resource, buffer, stride);
4374 
4375 			switch(FVF & D3DFVF_POSITION_MASK)
4376 			{
4377 			case D3DFVF_XYZ:
4378 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4379 				(char*&)buffer += 12;
4380 				break;
4381 			case D3DFVF_XYZRHW:
4382 				renderer->setInputStream(sw::PositionT, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4));
4383 				(char*&)buffer += 16;
4384 				break;
4385 			case D3DFVF_XYZB1:
4386 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4387 				(char*&)buffer += 12;
4388 
4389 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active?
4390 				(char*&)buffer += 4;
4391 				break;
4392 			case D3DFVF_XYZB2:
4393 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4394 				(char*&)buffer += 12;
4395 
4396 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active?
4397 				(char*&)buffer += 8;
4398 				break;
4399 			case D3DFVF_XYZB3:
4400 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4401 				(char*&)buffer += 12;
4402 
4403 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 2));   // FIXME: Stream type depends on indexed blending active?
4404 				(char*&)buffer += 12;
4405 				break;
4406 			case D3DFVF_XYZB4:
4407 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4408 				(char*&)buffer += 12;
4409 
4410 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));   // FIXME: Stream type depends on indexed blending active?
4411 				(char*&)buffer += 16;
4412 				break;
4413 			case D3DFVF_XYZB5:
4414 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4415 				(char*&)buffer += 12;
4416 
4417 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4));   // FIXME: Stream type depends on indexed blending active?
4418 				(char*&)buffer += 20;
4419 				break;
4420 			}
4421 
4422 			if(FVF & D3DFVF_LASTBETA_UBYTE4)
4423 			{
4424 				renderer->setInputStream(sw::BlendIndices, attribute.define((char*&)buffer - 4, sw::STREAMTYPE_INDICES, 1));
4425 			}
4426 
4427 			if(FVF & D3DFVF_NORMAL)
4428 			{
4429 				renderer->setInputStream(sw::Normal, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
4430 				(char*&)buffer += 12;
4431 			}
4432 
4433 			if(FVF & D3DFVF_PSIZE)
4434 			{
4435 				renderer->setInputStream(sw::PointSize, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));
4436 				(char*&)buffer += 4;
4437 			}
4438 
4439 			if(FVF & D3DFVF_DIFFUSE)
4440 			{
4441 				renderer->setInputStream(sw::Color0, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4));
4442 				(char*&)buffer += 4;
4443 			}
4444 
4445 			if(FVF & D3DFVF_SPECULAR)
4446 			{
4447 				renderer->setInputStream(sw::Color1, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4));
4448 				(char*&)buffer += 4;
4449 			}
4450 
4451 			for(unsigned int i = 0; i < 8; i++)
4452 			{
4453 				if((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT >= i + 1)
4454 				{
4455 					renderer->setInputStream(sw::TexCoord0 + i, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1 + (1 + (FVF >> (16 + i * 2))) % 4));
4456 					(char*&)buffer += 4 + 4 * ((1 + (FVF >> (16 + i * 2))) % 4);
4457 				}
4458 			}
4459 		}
4460 		else
4461 		{
4462 			const unsigned long *element = declaration;
4463 			int stream = 0;
4464 			sw::Resource *resource;
4465 			const void *buffer = 0;
4466 
4467 			while(*element != 0xFFFFFFFF)
4468 			{
4469 				switch((*element & 0xE0000000) >> 29)
4470 				{
4471 				case 0:   // NOP
4472 					if(*element != 0x00000000)
4473 					{
4474 						ASSERT(false);
4475 					}
4476 					break;
4477 				case 1:   // Stream selector
4478 					stream = *element & 0x0000000F;
4479 					{
4480 						ASSERT(dataStream[stream]);   // Expected a stream
4481 
4482 						Direct3DVertexBuffer8 *streamBuffer = (Direct3DVertexBuffer8*)dataStream[stream];
4483 						resource = streamBuffer->getResource();
4484 						buffer = (char*)resource->data();
4485 
4486 						const unsigned long *streamElement = element + 1;
4487 						stride = 0;
4488 
4489 						while((*streamElement & 0xE0000000) >> 29 == 2)   // Data definition
4490 						{
4491 							if(*streamElement & 0x10000000)   // Data skip
4492 							{
4493 								int skip = (*streamElement & 0x000F0000) >> 16;
4494 
4495 								stride += 4 * skip;
4496 							}
4497 							else
4498 							{
4499 								stride += typeStride((unsigned char)((*streamElement & 0x000F0000) >> 16));
4500 							}
4501 
4502 							streamElement++;
4503 						}
4504 
4505 					//	ASSERT(stride == streamStride[stream]);   // FIXME: Probably just ignore
4506 
4507 						(char*&)buffer += stride * base;
4508 					}
4509 					break;
4510 				case 2:   // Data definition
4511 					if(*element & 0x10000000)   // Data skip
4512 					{
4513 						int skip = (*element & 0x000F0000) >> 16;
4514 
4515 						(char*&)buffer += 4 * skip;
4516 					}
4517 					else
4518 					{
4519 						int type = (*element & 0x000F0000) >> 16;
4520 						int index = (*element & 0x0000000F) >> 0;
4521 
4522 						sw::Stream attribute(resource, buffer, stride);
4523 
4524 						switch(type)
4525 						{
4526 						case D3DVSDT_FLOAT1:   attribute.define(sw::STREAMTYPE_FLOAT, 1); break;
4527 						case D3DVSDT_FLOAT2:   attribute.define(sw::STREAMTYPE_FLOAT, 2); break;
4528 						case D3DVSDT_FLOAT3:   attribute.define(sw::STREAMTYPE_FLOAT, 3); break;
4529 						case D3DVSDT_FLOAT4:   attribute.define(sw::STREAMTYPE_FLOAT, 4); break;
4530 						case D3DVSDT_D3DCOLOR: attribute.define(sw::STREAMTYPE_COLOR, 4); break;
4531 						case D3DVSDT_UBYTE4:   attribute.define(sw::STREAMTYPE_BYTE, 4);  break;
4532 						case D3DVSDT_SHORT2:   attribute.define(sw::STREAMTYPE_SHORT, 2); break;
4533 						case D3DVSDT_SHORT4:   attribute.define(sw::STREAMTYPE_SHORT, 4); break;
4534 						default:               attribute.define(sw::STREAMTYPE_FLOAT, 0); ASSERT(false);
4535 						}
4536 
4537 						switch(index)
4538 						{
4539 						case D3DVSDE_POSITION:     renderer->setInputStream(sw::Position, attribute);     break;
4540 						case D3DVSDE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);  break;
4541 						case D3DVSDE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute); break;
4542 						case D3DVSDE_NORMAL:       renderer->setInputStream(sw::Normal, attribute);       break;
4543 						case D3DVSDE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute);    break;
4544 						case D3DVSDE_DIFFUSE:      renderer->setInputStream(sw::Color0, attribute);       break;
4545 						case D3DVSDE_SPECULAR:     renderer->setInputStream(sw::Color1, attribute);       break;
4546 						case D3DVSDE_TEXCOORD0:    renderer->setInputStream(sw::TexCoord0, attribute);    break;
4547 						case D3DVSDE_TEXCOORD1:    renderer->setInputStream(sw::TexCoord1, attribute);    break;
4548 						case D3DVSDE_TEXCOORD2:    renderer->setInputStream(sw::TexCoord2, attribute);    break;
4549 						case D3DVSDE_TEXCOORD3:    renderer->setInputStream(sw::TexCoord3, attribute);    break;
4550 						case D3DVSDE_TEXCOORD4:    renderer->setInputStream(sw::TexCoord4, attribute);    break;
4551 						case D3DVSDE_TEXCOORD5:    renderer->setInputStream(sw::TexCoord5, attribute);    break;
4552 						case D3DVSDE_TEXCOORD6:    renderer->setInputStream(sw::TexCoord6, attribute);    break;
4553 						case D3DVSDE_TEXCOORD7:    renderer->setInputStream(sw::TexCoord7, attribute);    break;
4554 					//	case D3DVSDE_POSITION2:    renderer->setInputStream(sw::Position1, attribute);    break;
4555 					//	case D3DVSDE_NORMAL2:      renderer->setInputStream(sw::Normal1, attribute);      break;
4556 						default:
4557 							ASSERT(false);
4558 						}
4559 
4560 						(char*&)buffer += typeStride(type);
4561 					}
4562 					break;
4563 				case 3:   // Tesselator data
4564 					UNIMPLEMENTED();
4565 					break;
4566 				case 4:   // Constant data
4567 					{
4568 						int count = (*element & 0x1E000000) >> 25;
4569 						int index = (*element & 0x0000007F) >> 0;
4570 
4571 						SetVertexShaderConstant(index, element + 1, count);
4572 
4573 						element += 4 * count;
4574 					}
4575 					break;
4576 				case 5:   // Extension
4577 					UNIMPLEMENTED();
4578 					break;
4579 				default:
4580 					ASSERT(false);
4581 				}
4582 
4583 				element++;
4584 			}
4585 		}
4586 	}
4587 
bindIndexBuffer(Direct3DIndexBuffer8 * indexBuffer)4588 	void Direct3DDevice8::bindIndexBuffer(Direct3DIndexBuffer8 *indexBuffer)
4589 	{
4590 		sw::Resource *resource = 0;
4591 
4592 		if(indexBuffer)
4593 		{
4594 			resource = indexBuffer->getResource();
4595 		}
4596 
4597 		renderer->setIndexBuffer(resource);
4598 	}
4599 
bindLights()4600 	void Direct3DDevice8::bindLights()
4601 	{
4602 		if(!lightsDirty) return;
4603 
4604 		Lights::iterator i = light.begin();
4605 		int active = 0;
4606 
4607 		// Set and enable renderer lights
4608 		while(active < 8)
4609 		{
4610 			while(i != light.end() && !i->second.enable)
4611 			{
4612 				i++;
4613 			}
4614 
4615 			if(i == light.end())
4616 			{
4617 				break;
4618 			}
4619 
4620 			const Light &l = i->second;
4621 
4622 			sw::Point position(l.Position.x, l.Position.y, l.Position.z);
4623 			sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a);
4624 			sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a);
4625 			sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a);
4626 			sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z);
4627 
4628 			renderer->setLightDiffuse(active, diffuse);
4629 			renderer->setLightSpecular(active, specular);
4630 			renderer->setLightAmbient(active, ambient);
4631 
4632 			if(l.Type == D3DLIGHT_DIRECTIONAL)
4633 			{
4634 			//	goto next;   // FIXME
4635 
4636 				// FIXME: Unsupported, make it a positional light far away without falloff
4637 				renderer->setLightPosition(active, -1000 * direction);
4638 				renderer->setLightRange(active, l.Range);
4639 				renderer->setLightAttenuation(active, 1, 0, 0);
4640 			}
4641 			else if(l.Type == D3DLIGHT_SPOT)
4642 			{
4643 			//	goto next;   // FIXME
4644 
4645 				// FIXME: Unsupported, make it a positional light
4646 				renderer->setLightPosition(active, position);
4647 				renderer->setLightRange(active, l.Range);
4648 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
4649 			}
4650 			else
4651 			{
4652 				renderer->setLightPosition(active, position);
4653 				renderer->setLightRange(active, l.Range);
4654 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
4655 			}
4656 
4657 			renderer->setLightEnable(active, true);
4658 
4659 			active++;
4660 
4661 	//	next:   // FIXME
4662 			i++;
4663 		}
4664 
4665 		// Remaining lights are disabled
4666 		while(active < 8)
4667 		{
4668 			renderer->setLightEnable(active, false);
4669 
4670 			active++;
4671 		}
4672 
4673 		lightsDirty= false;
4674 	}
4675 
bindViewport()4676 	bool Direct3DDevice8::bindViewport()
4677 	{
4678 		if(viewport.Width == 0 || viewport.Height == 0)
4679 		{
4680 			return false;
4681 		}
4682 
4683 		sw::Viewport view;
4684 		view.x0 = (float)viewport.X;
4685 		view.y0 = (float)viewport.Y + viewport.Height;
4686 		view.width = (float)viewport.Width;
4687 		view.height = -(float)viewport.Height;
4688 		view.minZ = viewport.MinZ;
4689 		view.maxZ = viewport.MaxZ;
4690 
4691 		renderer->setViewport(view);
4692 
4693 		sw::Rect scissor;
4694 		scissor.x0 = viewport.X;
4695 		scissor.x1 = viewport.X + viewport.Width;
4696 		scissor.y0 = viewport.Y;
4697 		scissor.y1 = viewport.Y + viewport.Height;
4698 
4699 		renderer->setScissor(scissor);
4700 
4701 		return true;
4702 	}
4703 
bindTextures()4704 	void Direct3DDevice8::bindTextures()
4705 	{
4706 		for(int stage = 0; stage < 8; stage++)
4707 		{
4708 			Direct3DBaseTexture8 *baseTexture = texture[stage];
4709 			sw::Resource *resource = 0;
4710 
4711 			bool textureUsed = false;
4712 
4713 			if(pixelShader[pixelShaderHandle])
4714 			{
4715 				textureUsed = pixelShader[pixelShaderHandle]->getPixelShader()->usesSampler(stage);
4716 			}
4717 			else
4718 			{
4719 				textureUsed = true;   // FIXME: Check fixed-function use?
4720 			}
4721 
4722 			if(baseTexture && textureUsed)
4723 			{
4724 				resource = baseTexture->getResource();
4725 			}
4726 
4727 			renderer->setTextureResource(stage, resource);
4728 
4729 			if(baseTexture && textureUsed)
4730 			{
4731 				int levelCount = baseTexture->getInternalLevelCount();
4732 
4733 				int textureLOD = baseTexture->GetLOD();
4734 				int stageLOD = textureStageState[stage][D3DTSS_MAXMIPLEVEL];
4735 				int LOD = textureLOD > stageLOD ? textureLOD : stageLOD;
4736 
4737 				if(textureStageState[stage][D3DTSS_MIPFILTER] == D3DTEXF_NONE)
4738 				{
4739 					LOD = 0;
4740 				}
4741 
4742 				switch(baseTexture->GetType())
4743 				{
4744 				case D3DRTYPE_TEXTURE:
4745 					{
4746 						Direct3DTexture8 *texture = dynamic_cast<Direct3DTexture8*>(baseTexture);
4747 						Direct3DSurface8 *surface;
4748 
4749 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
4750 						{
4751 							int surfaceLevel = mipmapLevel;
4752 
4753 							if(surfaceLevel < LOD)
4754 							{
4755 								surfaceLevel = LOD;
4756 							}
4757 
4758 							if(surfaceLevel < 0)
4759 							{
4760 								surfaceLevel = 0;
4761 							}
4762 							else if(surfaceLevel >= levelCount)
4763 							{
4764 								surfaceLevel = levelCount - 1;
4765 							}
4766 
4767 							surface = texture->getInternalSurfaceLevel(surfaceLevel);
4768 							renderer->setTextureLevel(stage, 0, mipmapLevel, surface, sw::TEXTURE_2D);
4769 						}
4770 					}
4771 					break;
4772 				case D3DRTYPE_CUBETEXTURE:
4773 					for(int face = 0; face < 6; face++)
4774 					{
4775 						Direct3DCubeTexture8 *cubeTexture = dynamic_cast<Direct3DCubeTexture8*>(baseTexture);
4776 						Direct3DSurface8 *surface;
4777 
4778 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
4779 						{
4780 							int surfaceLevel = mipmapLevel;
4781 
4782 							if(surfaceLevel < LOD)
4783 							{
4784 								surfaceLevel = LOD;
4785 							}
4786 
4787 							if(surfaceLevel < 0)
4788 							{
4789 								surfaceLevel = 0;
4790 							}
4791 							else if(surfaceLevel >= levelCount)
4792 							{
4793 								surfaceLevel = levelCount - 1;
4794 							}
4795 
4796 							surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel);
4797 							renderer->setTextureLevel(stage, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
4798 						}
4799 					}
4800 					break;
4801 				case D3DRTYPE_VOLUMETEXTURE:
4802 					{
4803 						Direct3DVolumeTexture8 *volumeTexture = dynamic_cast<Direct3DVolumeTexture8*>(baseTexture);
4804 						Direct3DVolume8 *volume;
4805 
4806 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
4807 						{
4808 							int surfaceLevel = mipmapLevel;
4809 
4810 							if(surfaceLevel < LOD)
4811 							{
4812 								surfaceLevel = LOD;
4813 							}
4814 
4815 							if(surfaceLevel < 0)
4816 							{
4817 								surfaceLevel = 0;
4818 							}
4819 							else if(surfaceLevel >= levelCount)
4820 							{
4821 								surfaceLevel = levelCount - 1;
4822 							}
4823 
4824 							volume = volumeTexture->getInternalVolumeLevel(surfaceLevel);
4825 							renderer->setTextureLevel(stage, 0, mipmapLevel, volume, sw::TEXTURE_3D);
4826 						}
4827 					}
4828 					break;
4829 				default:
4830 					UNIMPLEMENTED();
4831 				}
4832 			}
4833 			else
4834 			{
4835 				renderer->setTextureLevel(stage, 0, 0, 0, sw::TEXTURE_NULL);
4836 			}
4837 		}
4838 	}
4839 
bindCursor()4840 	void Direct3DDevice8::bindCursor()
4841 	{
4842 		if(showCursor)
4843 		{
4844 			sw::FrameBuffer::setCursorImage(cursor);
4845 
4846 			HCURSOR oldCursor = SetCursor(nullCursor);
4847 
4848 			if(oldCursor != nullCursor)
4849 			{
4850 				win32Cursor = oldCursor;
4851 			}
4852 		}
4853 		else
4854 		{
4855 			sw::FrameBuffer::setCursorImage(0);
4856 
4857 			if(GetCursor() == nullCursor)
4858 			{
4859 				SetCursor(win32Cursor);
4860 			}
4861 		}
4862 	}
4863 
updateVolume(IDirect3DVolume8 * sourceVolume,IDirect3DVolume8 * destinationVolume)4864 	long Direct3DDevice8::updateVolume(IDirect3DVolume8 *sourceVolume, IDirect3DVolume8 *destinationVolume)
4865 	{
4866 		TRACE("IDirect3DVolume8 *sourceVolume = 0x%0.8p, IDirect3DVolume8 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume);
4867 
4868 		if(!sourceVolume || !destinationVolume)
4869 		{
4870 			return INVALIDCALL();
4871 		}
4872 
4873 		D3DVOLUME_DESC sourceDescription;
4874 		D3DVOLUME_DESC destinationDescription;
4875 
4876 		sourceVolume->GetDesc(&sourceDescription);
4877 		destinationVolume->GetDesc(&destinationDescription);
4878 
4879 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||
4880 		   destinationDescription.Pool != D3DPOOL_DEFAULT ||
4881 		   sourceDescription.Format != destinationDescription.Format ||
4882 		   sourceDescription.Width  != destinationDescription.Width ||
4883 		   sourceDescription.Height != destinationDescription.Height)
4884 		{
4885 			return INVALIDCALL();
4886 		}
4887 
4888 		D3DLOCKED_BOX sourceLock;
4889 		D3DLOCKED_BOX destinationLock;
4890 
4891 		sourceVolume->LockBox(&sourceLock, 0, 0);
4892 		destinationVolume->LockBox(&destinationLock, 0, 0);
4893 
4894 		if(sourceLock.RowPitch != destinationLock.RowPitch ||
4895 		   sourceLock.SlicePitch != destinationLock.SlicePitch)
4896 		{
4897 			UNIMPLEMENTED();
4898 		}
4899 
4900 		memcpy(destinationLock.pBits, sourceLock.pBits, sourceLock.SlicePitch * sourceDescription.Depth);
4901 
4902 		sourceVolume->UnlockBox();
4903 		destinationVolume->UnlockBox();
4904 
4905 		return D3D_OK;
4906 	}
4907 
configureFPU()4908 	void Direct3DDevice8::configureFPU()
4909 	{
4910 		unsigned short cw;
4911 
4912 		__asm
4913 		{
4914 			fstcw cw
4915 			and cw, 0xFCFC   // Single-precision
4916 			or cw, 0x003F    // Mask all exceptions
4917 			and cw, 0xF3FF   // Round to nearest
4918 			fldcw cw
4919 		}
4920 	}
4921 }
4922