OSDN Git Service

Fix clearing all samples of multisample render targets.
[android-x86/external-swiftshader.git] / src / D3D8 / Direct3DDevice8.cpp
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 {
45         inline unsigned long FtoDW(float f)   // FIXME: Deprecate
46         {
47                 return (unsigned long&)f;
48         }
49
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
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
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
267         unsigned long Direct3DDevice8::AddRef()
268         {
269                 TRACE("");
270
271                 return Unknown::AddRef();
272         }
273
274         unsigned long Direct3DDevice8::Release()
275         {
276                 TRACE("");
277
278                 return Unknown::Release();
279         }
280
281         long Direct3DDevice8::ApplyStateBlock(unsigned long token)
282         {
283                 TRACE("");
284
285                 stateRecorder[token]->Apply();
286
287                 return D3D_OK;
288         }
289
290         long Direct3DDevice8::BeginScene()
291         {
292                 TRACE("");
293
294                 return D3D_OK;
295         }
296
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
309         long Direct3DDevice8::CaptureStateBlock(unsigned long token)
310         {
311                 TRACE("");
312
313                 stateRecorder[token]->Capture();
314
315                 return D3D_OK;
316         }
317
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
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
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
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
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
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
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
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
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
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
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
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
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
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
848         long Direct3DDevice8::DeletePatch(unsigned int handle)
849         {
850                 TRACE("");
851
852                 UNIMPLEMENTED();
853
854                 return D3D_OK;
855         }
856
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
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
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
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
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
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
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
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
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
1166         long Direct3DDevice8::EndScene()
1167         {
1168                 TRACE("");
1169
1170                 return D3D_OK;
1171         }
1172
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
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
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
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
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
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
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
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
1294         long Direct3DDevice8::GetDeviceCaps(D3DCAPS8 *caps)
1295         {
1296                 TRACE("");
1297
1298                 return d3d8->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps);
1299         }
1300
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2053         long Direct3DDevice8::ResourceManagerDiscardBytes(unsigned long bytes)
2054         {
2055                 TRACE("");
2056
2057                 return D3D_OK;
2058         }
2059
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
4008         long Direct3DDevice8::TestCooperativeLevel()
4009         {
4010                 TRACE("");
4011
4012                 return D3D_OK;
4013         }
4014
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }