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 "Device.hpp"
16
17#include "Image.hpp"
18#include "Texture.h"
19
20#include "Renderer/Renderer.hpp"
21#include "Renderer/Clipper.hpp"
22#include "Shader/PixelShader.hpp"
23#include "Shader/VertexShader.hpp"
24#include "Main/Config.hpp"
25#include "Main/FrameBuffer.hpp"
26#include "Common/Math.hpp"
27#include "Common/Configurator.hpp"
28#include "Common/Memory.hpp"
29#include "Common/Timer.hpp"
30#include "../common/debug.h"
31
32namespace gl
33{
34	using namespace sw;
35
36	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
37	{
38		depthStencil = 0;
39		renderTarget = 0;
40
41		setDepthBufferEnable(true);
42		setFillMode(FILL_SOLID);
43		setShadingMode(SHADING_GOURAUD);
44		setDepthWriteEnable(true);
45		setAlphaTestEnable(false);
46		setSourceBlendFactor(BLEND_ONE);
47		setDestBlendFactor(BLEND_ZERO);
48		setCullMode(CULL_COUNTERCLOCKWISE);
49		setDepthCompare(DEPTH_LESSEQUAL);
50		setAlphaReference(0.0f);
51		setAlphaCompare(ALPHA_ALWAYS);
52		setAlphaBlendEnable(false);
53		setFogEnable(false);
54		setSpecularEnable(false);
55		setFogColor(0);
56		setPixelFogMode(FOG_NONE);
57		setFogStart(0.0f);
58		setFogEnd(1.0f);
59		setFogDensity(1.0f);
60		setRangeFogEnable(false);
61		setStencilEnable(false);
62		setStencilFailOperation(OPERATION_KEEP);
63		setStencilZFailOperation(OPERATION_KEEP);
64		setStencilPassOperation(OPERATION_KEEP);
65		setStencilCompare(STENCIL_ALWAYS);
66		setStencilReference(0);
67		setStencilMask(0xFFFFFFFF);
68		setStencilWriteMask(0xFFFFFFFF);
69		setVertexFogMode(FOG_NONE);
70		setClipFlags(0);
71		setPointSize(1.0f);
72		setPointSizeMin(0.125f);
73		setPointSizeMax(8192.0f);
74		setColorWriteMask(0, 0x0000000F);
75		setBlendOperation(BLENDOP_ADD);
76		scissorEnable = false;
77		setSlopeDepthBias(0.0f);
78		setTwoSidedStencil(false);
79		setStencilFailOperationCCW(OPERATION_KEEP);
80		setStencilZFailOperationCCW(OPERATION_KEEP);
81		setStencilPassOperationCCW(OPERATION_KEEP);
82		setStencilCompareCCW(STENCIL_ALWAYS);
83		setColorWriteMask(1, 0x0000000F);
84		setColorWriteMask(2, 0x0000000F);
85		setColorWriteMask(3, 0x0000000F);
86		setBlendConstant(0xFFFFFFFF);
87		setWriteSRGB(false);
88		setDepthBias(0.0f);
89		setSeparateAlphaBlendEnable(false);
90		setSourceBlendFactorAlpha(BLEND_ONE);
91		setDestBlendFactorAlpha(BLEND_ZERO);
92		setBlendOperationAlpha(BLENDOP_ADD);
93		setPointSpriteEnable(true);
94		setColorLogicOpEnabled(false);
95		setLogicalOperation(LOGICALOP_COPY);
96
97		for(int i = 0; i < 16; i++)
98		{
99			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
100			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
101			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
102			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
103			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
104			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
105			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
106		}
107
108		for(int i = 0; i < 4; i++)
109		{
110			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
111			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
112			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
113			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
114			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
115			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
116			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
117		}
118
119		for(int i = 0; i < 6; i++)
120		{
121			float plane[4] = {0, 0, 0, 0};
122
123			setClipPlane(i, plane);
124		}
125
126		pixelShader = 0;
127		vertexShader = 0;
128
129		pixelShaderDirty = true;
130		pixelShaderConstantsFDirty = 0;
131		vertexShaderDirty = true;
132		vertexShaderConstantsFDirty = 0;
133
134		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
135		{
136			float zero[4] = {0, 0, 0, 0};
137
138			setPixelShaderConstantF(i, zero, 1);
139		}
140
141		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
142		{
143			float zero[4] = {0, 0, 0, 0};
144
145			setVertexShaderConstantF(i, zero, 1);
146		}
147
148		setLightingEnable(false);
149
150		setGlobalAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
151		setMaterialAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
152		setMaterialDiffuse(sw::Color<float>(0.8f, 0.8f, 0.8f, 1.0f));
153		setMaterialSpecular(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
154		setMaterialEmission(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
155
156		for(int i = 0; i < 8; i++)
157		{
158			setLightEnable(i, false);
159			setLightAttenuation(i, 1.0f, 0.0f, 0.0f);
160		}
161
162		setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
163		setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
164		setAmbientMaterialSource(sw::MATERIAL_COLOR1);
165		setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
166	}
167
168	Device::~Device()
169	{
170		if(depthStencil)
171		{
172			depthStencil->release();
173			depthStencil = 0;
174		}
175
176		if(renderTarget)
177		{
178			renderTarget->release();
179			renderTarget = 0;
180		}
181
182		delete context;
183	}
184
185	// This object has to be mem aligned
186	void* Device::operator new(size_t size)
187	{
188		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
189		return sw::allocate(sizeof(gl::Device), 16);
190	}
191
192	void Device::operator delete(void * mem)
193	{
194		sw::deallocate(mem);
195	}
196
197	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
198	{
199		if(!renderTarget || !rgbaMask)
200		{
201			return;
202		}
203
204		sw::Rect clearRect = renderTarget->getRect();
205
206		if(scissorEnable)
207		{
208			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
209		}
210
211		float rgba[4];
212		rgba[0] = red;
213		rgba[1] = green;
214		rgba[2] = blue;
215		rgba[3] = alpha;
216
217		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
218	}
219
220	void Device::clearDepth(float z)
221	{
222		if(!depthStencil)
223		{
224			return;
225		}
226
227		z = clamp01(z);
228		sw::Rect clearRect = depthStencil->getRect();
229
230		if(scissorEnable)
231		{
232			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
233		}
234
235		depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
236	}
237
238	void Device::clearStencil(unsigned int stencil, unsigned int mask)
239	{
240		if(!depthStencil)
241		{
242			return;
243		}
244
245		sw::Rect clearRect = depthStencil->getRect();
246
247		if(scissorEnable)
248		{
249			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
250		}
251
252		depthStencil->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
253	}
254
255	Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
256	{
257		if(height > OUTLINE_RESOLUTION)
258		{
259			ERR("Invalid parameters: %dx%d", width, height);
260			return 0;
261		}
262
263		bool lockable = true;
264
265		switch(format)
266		{
267	//	case FORMAT_D15S1:
268		case FORMAT_D24S8:
269		case FORMAT_D24X8:
270	//	case FORMAT_D24X4S4:
271		case FORMAT_D24FS8:
272		case FORMAT_D32:
273		case FORMAT_D16:
274			lockable = false;
275			break;
276	//	case FORMAT_S8_LOCKABLE:
277	//	case FORMAT_D16_LOCKABLE:
278		case FORMAT_D32F_LOCKABLE:
279	//	case FORMAT_D32_LOCKABLE:
280		case FORMAT_DF24S8:
281		case FORMAT_DF16S8:
282			lockable = true;
283			break;
284		default:
285			UNREACHABLE(format);
286		}
287
288		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
289
290		if(!surface)
291		{
292			ERR("Out of memory");
293			return 0;
294		}
295
296		return surface;
297	}
298
299	Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
300	{
301		if(height > OUTLINE_RESOLUTION)
302		{
303			ERR("Invalid parameters: %dx%d", width, height);
304			return 0;
305		}
306
307		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
308
309		if(!surface)
310		{
311			ERR("Out of memory");
312			return 0;
313		}
314
315		return surface;
316	}
317
318	void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
319	{
320		if(!bindResources() || !primitiveCount)
321		{
322			return;
323		}
324
325		DrawType drawType;
326
327		if(indexSize == 4)
328		{
329			switch(type)
330			{
331			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
332			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
333			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
334			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP32;      break;
335			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
336			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
337			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;	  break;
338			default: UNREACHABLE(type);
339			}
340		}
341		else if(indexSize == 2)
342		{
343			switch(type)
344			{
345			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
346			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
347			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
348			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP16;      break;
349			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
350			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
351			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
352			default: UNREACHABLE(type);
353			}
354		}
355		else if(indexSize == 1)
356		{
357			switch(type)
358			{
359			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST8;     break;
360			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST8;      break;
361			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP8;     break;
362			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP8;      break;
363			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST8;  break;
364			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP8; break;
365			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN8;   break;
366			default: UNREACHABLE(type);
367			}
368		}
369		else UNREACHABLE(indexSize);
370
371		draw(drawType, indexOffset, primitiveCount);
372	}
373
374	void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
375	{
376		if(!bindResources() || !primitiveCount)
377		{
378			return;
379		}
380
381		setIndexBuffer(0);
382
383		DrawType drawType;
384
385		switch(primitiveType)
386		{
387		case DRAW_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
388		case DRAW_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
389		case DRAW_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
390		case DRAW_LINELOOP:      drawType = sw::DRAW_LINELOOP;      break;
391		case DRAW_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
392		case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
393		case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
394		case DRAW_QUADLIST:      drawType = sw::DRAW_QUADLIST;      break;
395		default: UNREACHABLE(primitiveType);
396		}
397
398		draw(drawType, 0, primitiveCount);
399	}
400
401	void Device::setDepthStencilSurface(Image *depthStencil)
402	{
403		if(this->depthStencil == depthStencil)
404		{
405			return;
406		}
407
408		if(depthStencil)
409		{
410			depthStencil->addRef();
411		}
412
413		if(this->depthStencil)
414		{
415			this->depthStencil->release();
416		}
417
418		this->depthStencil = depthStencil;
419
420		setDepthBuffer(depthStencil);
421		setStencilBuffer(depthStencil);
422	}
423
424	void Device::setPixelShader(PixelShader *pixelShader)
425	{
426		this->pixelShader = pixelShader;
427		pixelShaderDirty = true;
428	}
429
430	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
431	{
432		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
433		{
434			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
435			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
436			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
437			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
438		}
439
440		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
441		pixelShaderDirty = true;   // Reload DEF constants
442	}
443
444	void Device::setScissorEnable(bool enable)
445	{
446		scissorEnable = enable;
447	}
448
449	void Device::setRenderTarget(int index, Image *renderTarget)
450	{
451		if(renderTarget)
452		{
453			renderTarget->addRef();
454		}
455
456		if(this->renderTarget)
457		{
458			this->renderTarget->release();
459		}
460
461		this->renderTarget = renderTarget;
462
463		Renderer::setRenderTarget(index, renderTarget);
464	}
465
466	void Device::setScissorRect(const sw::Rect &rect)
467	{
468		scissorRect = rect;
469	}
470
471	void Device::setVertexShader(VertexShader *vertexShader)
472	{
473		this->vertexShader = vertexShader;
474		vertexShaderDirty = true;
475	}
476
477	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
478	{
479		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
480		{
481			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
482			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
483			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
484			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
485		}
486
487		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
488		vertexShaderDirty = true;   // Reload DEF constants
489	}
490
491	void Device::setViewport(const Viewport &viewport)
492	{
493		this->viewport = viewport;
494	}
495
496	bool Device::stretchRect(Image *source, const sw::SliceRect *sourceRect, Image *dest, const sw::SliceRect *destRect, bool filter)
497	{
498		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
499		{
500			ERR("Invalid parameters");
501			return false;
502		}
503
504		int sWidth = source->getWidth();
505		int sHeight = source->getHeight();
506		int dWidth = dest->getWidth();
507		int dHeight = dest->getHeight();
508
509		SliceRect sRect;
510		SliceRect dRect;
511
512		if(sourceRect)
513		{
514			sRect = *sourceRect;
515		}
516		else
517		{
518			sRect.y0 = 0;
519			sRect.x0 = 0;
520			sRect.y1 = sHeight;
521			sRect.x1 = sWidth;
522		}
523
524		if(destRect)
525		{
526			dRect = *destRect;
527		}
528		else
529		{
530			dRect.y0 = 0;
531			dRect.x0 = 0;
532			dRect.y1 = dHeight;
533			dRect.x1 = dWidth;
534		}
535
536		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
537		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
538		bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
539		bool alpha0xFF = false;
540
541		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
542		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
543		{
544			equalFormats = true;
545			alpha0xFF = true;
546		}
547
548		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
549		{
550			if(source->hasDepth())
551			{
552				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
553				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
554
555				unsigned int width = source->getWidth();
556				unsigned int height = source->getHeight();
557				unsigned int pitch = source->getInternalPitchB();
558
559				for(unsigned int y = 0; y < height; y++)
560				{
561					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
562
563					sourceBuffer += pitch;
564					destBuffer += pitch;
565				}
566
567				source->unlockInternal();
568				dest->unlockInternal();
569			}
570
571			if(source->hasStencil())
572			{
573				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
574				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
575
576				unsigned int width = source->getWidth();
577				unsigned int height = source->getHeight();
578				unsigned int pitch = source->getStencilPitchB();
579
580				for(unsigned int y = 0; y < height; y++)
581				{
582					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
583
584					sourceBuffer += pitch;
585					destBuffer += pitch;
586				}
587
588				source->unlockStencil();
589				dest->unlockStencil();
590			}
591		}
592		else if(!scaling && equalFormats)
593		{
594			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
595			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
596			unsigned int sourcePitch = source->getInternalPitchB();
597			unsigned int destPitch = dest->getInternalPitchB();
598
599			unsigned int width = dRect.x1 - dRect.x0;
600			unsigned int height = dRect.y1 - dRect.y0;
601			unsigned int bytes = width * Image::bytes(source->getInternalFormat());
602
603			for(unsigned int y = 0; y < height; y++)
604			{
605				memcpy(destBytes, sourceBytes, bytes);
606
607				if(alpha0xFF)
608				{
609					for(unsigned int x = 0; x < width; x++)
610					{
611						destBytes[4 * x + 3] = 0xFF;
612					}
613				}
614
615				sourceBytes += sourcePitch;
616				destBytes += destPitch;
617			}
618
619			source->unlockInternal();
620			dest->unlockInternal();
621		}
622		else
623		{
624			sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice);
625			blit(source, sRectF, dest, dRect, scaling && filter);
626		}
627
628		return true;
629	}
630
631	bool Device::bindResources()
632	{
633		if(!bindViewport())
634		{
635			return false;   // Zero-area target region
636		}
637
638		bindShaderConstants();
639
640		return true;
641	}
642
643	void Device::bindShaderConstants()
644	{
645		if(pixelShaderDirty)
646		{
647			if(pixelShader)
648			{
649				if(pixelShaderConstantsFDirty)
650				{
651					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
652				}
653
654				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
655				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
656			}
657			else
658			{
659				setPixelShader(0);
660			}
661
662			pixelShaderDirty = false;
663		}
664
665		if(vertexShaderDirty)
666		{
667			if(vertexShader)
668			{
669				if(vertexShaderConstantsFDirty)
670				{
671					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
672				}
673
674				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
675				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
676			}
677			else
678			{
679				setVertexShader(0);
680			}
681
682			vertexShaderDirty = false;
683		}
684	}
685
686	bool Device::bindViewport()
687	{
688		if(viewport.width <= 0 || viewport.height <= 0)
689		{
690			return false;
691		}
692
693		if(scissorEnable)
694		{
695			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
696			{
697				return false;
698			}
699
700			sw::Rect scissor;
701			scissor.x0 = scissorRect.x0;
702			scissor.x1 = scissorRect.x1;
703			scissor.y0 = scissorRect.y0;
704			scissor.y1 = scissorRect.y1;
705
706			setScissor(scissor);
707		}
708		else
709		{
710			sw::Rect scissor;
711			scissor.x0 = viewport.x0;
712			scissor.x1 = viewport.x0 + viewport.width;
713			scissor.y0 = viewport.y0;
714			scissor.y1 = viewport.y0 + viewport.height;
715
716			if(renderTarget)
717			{
718				scissor.x0 = max(scissor.x0, 0);
719				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
720				scissor.y0 = max(scissor.y0, 0);
721				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
722			}
723
724			if(depthStencil)
725			{
726				scissor.x0 = max(scissor.x0, 0);
727				scissor.x1 = min(scissor.x1, depthStencil->getWidth());
728				scissor.y0 = max(scissor.y0, 0);
729				scissor.y1 = min(scissor.y1, depthStencil->getHeight());
730			}
731
732			setScissor(scissor);
733		}
734
735		sw::Viewport view;
736		view.x0 = (float)viewport.x0;
737		view.y0 = (float)viewport.y0;
738		view.width = (float)viewport.width;
739		view.height = (float)viewport.height;
740		view.minZ = viewport.minZ;
741		view.maxZ = viewport.maxZ;
742
743		Renderer::setViewport(view);
744
745		return true;
746	}
747
748	bool Device::validRectangle(const sw::Rect *rect, Image *surface)
749	{
750		if(!rect)
751		{
752			return true;
753		}
754
755		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
756		{
757			return false;
758		}
759
760		if(rect->x0 < 0 || rect->y0 < 0)
761		{
762			return false;
763		}
764
765		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
766		{
767			return false;
768		}
769
770		return true;
771	}
772
773	void Device::finish()
774	{
775		synchronize();
776	}
777}
778