Device.cpp revision d9762743d768d943003a980005b8c689d94d7cc9
1// SwiftShader Software Renderer
2//
3// Copyright(c) 2005-2013 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "Device.hpp"
13
14#include "common/Image.hpp"
15#include "Texture.h"
16
17#include "Renderer/Renderer.hpp"
18#include "Renderer/Clipper.hpp"
19#include "Shader/PixelShader.hpp"
20#include "Shader/VertexShader.hpp"
21#include "Main/Config.hpp"
22#include "Main/FrameBuffer.hpp"
23#include "Common/Math.hpp"
24#include "Common/Configurator.hpp"
25#include "Common/Timer.hpp"
26#include "../common/debug.h"
27
28namespace es1
29{
30	using namespace sw;
31
32	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
33	{
34		depthStencil = 0;
35		renderTarget = 0;
36
37		setDepthBufferEnable(true);
38		setFillMode(FILL_SOLID);
39		setShadingMode(SHADING_GOURAUD);
40		setDepthWriteEnable(true);
41		setAlphaTestEnable(false);
42		setSourceBlendFactor(BLEND_ONE);
43		setDestBlendFactor(BLEND_ZERO);
44		setCullMode(CULL_COUNTERCLOCKWISE);
45		setDepthCompare(DEPTH_LESSEQUAL);
46		setAlphaReference(0.0f);
47		setAlphaCompare(ALPHA_ALWAYS);
48		setAlphaBlendEnable(false);
49		setFogEnable(false);
50		setSpecularEnable(false);
51		setFogColor(0);
52		setPixelFogMode(FOG_NONE);
53		setFogStart(0.0f);
54		setFogEnd(1.0f);
55		setFogDensity(1.0f);
56		setRangeFogEnable(false);
57		setStencilEnable(false);
58		setStencilFailOperation(OPERATION_KEEP);
59		setStencilZFailOperation(OPERATION_KEEP);
60		setStencilPassOperation(OPERATION_KEEP);
61		setStencilCompare(STENCIL_ALWAYS);
62		setStencilReference(0);
63		setStencilMask(0xFFFFFFFF);
64		setStencilWriteMask(0xFFFFFFFF);
65		setVertexFogMode(FOG_NONE);
66		setClipFlags(0);
67		setPointSize(1.0f);
68		setPointSizeMin(0.125f);
69        setPointSizeMax(8192.0f);
70		setColorWriteMask(0, 0x0000000F);
71		setBlendOperation(BLENDOP_ADD);
72		scissorEnable = false;
73		setSlopeDepthBias(0.0f);
74		setTwoSidedStencil(false);
75		setStencilFailOperationCCW(OPERATION_KEEP);
76		setStencilZFailOperationCCW(OPERATION_KEEP);
77		setStencilPassOperationCCW(OPERATION_KEEP);
78		setStencilCompareCCW(STENCIL_ALWAYS);
79		setColorWriteMask(1, 0x0000000F);
80		setColorWriteMask(2, 0x0000000F);
81		setColorWriteMask(3, 0x0000000F);
82		setBlendConstant(0xFFFFFFFF);
83		setWriteSRGB(false);
84		setDepthBias(0.0f);
85		setSeparateAlphaBlendEnable(false);
86		setSourceBlendFactorAlpha(BLEND_ONE);
87		setDestBlendFactorAlpha(BLEND_ZERO);
88		setBlendOperationAlpha(BLENDOP_ADD);
89		setPointSpriteEnable(true);
90		setColorLogicOpEnabled(false);
91		setLogicalOperation(LOGICALOP_COPY);
92
93		for(int i = 0; i < 16; i++)
94		{
95			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
96			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
97			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
98			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
99			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
100			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
101			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
102		}
103
104		for(int i = 0; i < 4; i++)
105		{
106			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
107			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
108			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
109			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
110			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
111			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
112			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
113		}
114
115		for(int i = 0; i < 6; i++)
116		{
117			float plane[4] = {0, 0, 0, 0};
118
119			setClipPlane(i, plane);
120		}
121	}
122
123	Device::~Device()
124	{
125		if(depthStencil)
126		{
127			depthStencil->release();
128			depthStencil = 0;
129		}
130
131		if(renderTarget)
132		{
133			renderTarget->release();
134			renderTarget = 0;
135		}
136
137		delete context;
138	}
139
140	void Device::clearColor(unsigned int color, unsigned int rgbaMask)
141	{
142		if(!renderTarget)
143		{
144			return;
145		}
146
147		int x0 = 0;
148		int y0 = 0;
149		int width = renderTarget->getWidth();
150		int height = renderTarget->getHeight();
151
152		if(scissorEnable)   // Clamp against scissor rectangle
153		{
154			if(x0 < scissorRect.x0) x0 = scissorRect.x0;
155			if(y0 < scissorRect.y0) y0 = scissorRect.y0;
156			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
157			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
158		}
159
160		renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
161	}
162
163	void Device::clearDepth(float z)
164	{
165		if(!depthStencil)
166		{
167			return;
168		}
169
170		if(z > 1) z = 1;
171		if(z < 0) z = 0;
172
173		int x0 = 0;
174		int y0 = 0;
175		int width = depthStencil->getWidth();
176		int height = depthStencil->getHeight();
177
178		if(scissorEnable)   // Clamp against scissor rectangle
179		{
180			if(x0 < scissorRect.x0) x0 = scissorRect.x0;
181			if(y0 < scissorRect.y0) y0 = scissorRect.y0;
182			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
183			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
184		}
185
186		depthStencil->clearDepthBuffer(z, x0, y0, width, height);
187	}
188
189	void Device::clearStencil(unsigned int stencil, unsigned int mask)
190	{
191		if(!depthStencil)
192		{
193			return;
194		}
195
196		int x0 = 0;
197		int y0 = 0;
198		int width = depthStencil->getWidth();
199		int height = depthStencil->getHeight();
200
201		if(scissorEnable)   // Clamp against scissor rectangle
202		{
203			if(x0 < scissorRect.x0) x0 = scissorRect.x0;
204			if(y0 < scissorRect.y0) y0 = scissorRect.y0;
205			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
206			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
207		}
208
209		depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);
210	}
211
212	egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
213	{
214		if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)
215		{
216			ERR("Invalid parameters");
217			return 0;
218		}
219
220		bool lockable = true;
221
222		switch(format)
223		{
224	//	case FORMAT_D15S1:
225		case FORMAT_D24S8:
226		case FORMAT_D24X8:
227	//	case FORMAT_D24X4S4:
228		case FORMAT_D24FS8:
229		case FORMAT_D32:
230		case FORMAT_D16:
231			lockable = false;
232			break;
233	//	case FORMAT_S8_LOCKABLE:
234	//	case FORMAT_D16_LOCKABLE:
235		case FORMAT_D32F_LOCKABLE:
236	//	case FORMAT_D32_LOCKABLE:
237		case FORMAT_DF24S8:
238		case FORMAT_DF16S8:
239			lockable = true;
240			break;
241		default:
242			UNREACHABLE(format);
243		}
244
245		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable, true);
246
247		if(!surface)
248		{
249			ERR("Out of memory");
250			return 0;
251		}
252
253		return surface;
254	}
255
256	egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
257	{
258		if(height > OUTLINE_RESOLUTION)
259		{
260			ERR("Invalid parameters");
261			return 0;
262		}
263
264		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable, true);
265
266		if(!surface)
267		{
268			ERR("Out of memory");
269			return 0;
270		}
271
272		return surface;
273	}
274
275	void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
276	{
277		if(!bindResources() || !primitiveCount)
278		{
279			return;
280		}
281
282		DrawType drawType;
283
284		if(indexSize == 4)
285		{
286			switch(type)
287			{
288			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
289			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
290			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
291			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP32;      break;
292			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
293			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
294			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;	  break;
295			default: UNREACHABLE(type);
296			}
297		}
298		else if(indexSize == 2)
299		{
300			switch(type)
301			{
302			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
303			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
304			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
305			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP16;      break;
306			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
307			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
308			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
309			default: UNREACHABLE(type);
310			}
311		}
312		else if(indexSize == 1)
313		{
314			switch(type)
315			{
316			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST8;     break;
317			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST8;      break;
318			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP8;     break;
319			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP8;      break;
320			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST8;  break;
321			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP8; break;
322			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN8;   break;
323			default: UNREACHABLE(type);
324			}
325		}
326		else UNREACHABLE(indexSize);
327
328		draw(drawType, indexOffset, primitiveCount);
329	}
330
331	void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
332	{
333		if(!bindResources() || !primitiveCount)
334		{
335			return;
336		}
337
338		setIndexBuffer(0);
339
340		DrawType drawType;
341
342		switch(primitiveType)
343		{
344		case DRAW_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
345		case DRAW_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
346		case DRAW_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
347		case DRAW_LINELOOP:      drawType = sw::DRAW_LINELOOP;      break;
348		case DRAW_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
349		case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
350		case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
351		default: UNREACHABLE(primitiveType);
352		}
353
354		draw(drawType, 0, primitiveCount);
355	}
356
357	void Device::setDepthStencilSurface(egl::Image *depthStencil)
358	{
359		if(this->depthStencil == depthStencil)
360		{
361			return;
362		}
363
364		if(depthStencil)
365		{
366			depthStencil->addRef();
367		}
368
369		if(this->depthStencil)
370		{
371			this->depthStencil->release();
372		}
373
374		this->depthStencil = depthStencil;
375
376		setDepthStencil(depthStencil);
377	}
378
379	void Device::setScissorEnable(bool enable)
380	{
381		scissorEnable = enable;
382	}
383
384	void Device::setRenderTarget(egl::Image *renderTarget)
385	{
386		if(renderTarget)
387		{
388			renderTarget->addRef();
389		}
390
391		if(this->renderTarget)
392		{
393			this->renderTarget->release();
394		}
395
396		this->renderTarget = renderTarget;
397
398		Renderer::setRenderTarget(0, renderTarget);
399	}
400
401	void Device::setScissorRect(const sw::Rect &rect)
402	{
403		scissorRect = rect;
404	}
405
406	void Device::setViewport(const Viewport &viewport)
407	{
408		this->viewport = viewport;
409	}
410
411	bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
412	{
413		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
414		{
415			ERR("Invalid parameters");
416			return false;
417		}
418
419		int sWidth = source->getWidth();
420		int sHeight = source->getHeight();
421		int dWidth = dest->getWidth();
422		int dHeight = dest->getHeight();
423
424		SliceRect sRect;
425		SliceRect dRect;
426
427		if(sourceRect)
428		{
429			sRect = *sourceRect;
430		}
431		else
432		{
433			sRect.y0 = 0;
434			sRect.x0 = 0;
435			sRect.y1 = sHeight;
436			sRect.x1 = sWidth;
437		}
438
439		if(destRect)
440		{
441			dRect = *destRect;
442		}
443		else
444		{
445			dRect.y0 = 0;
446			dRect.x0 = 0;
447			dRect.y1 = dHeight;
448			dRect.x1 = dWidth;
449		}
450
451		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
452		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
453		bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
454		bool alpha0xFF = false;
455
456		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
457		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
458		{
459			equalFormats = true;
460			alpha0xFF = true;
461		}
462
463		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
464		{
465			if(source->hasDepth())
466			{
467				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
468				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
469
470				unsigned int width = source->getWidth();
471				unsigned int height = source->getHeight();
472				unsigned int pitch = source->getInternalPitchB();
473
474				for(unsigned int y = 0; y < height; y++)
475				{
476					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
477
478					sourceBuffer += pitch;
479					destBuffer += pitch;
480				}
481
482				source->unlockInternal();
483				dest->unlockInternal();
484			}
485
486			if(source->hasStencil())
487			{
488				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
489				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
490
491				unsigned int width = source->getWidth();
492				unsigned int height = source->getHeight();
493				unsigned int pitch = source->getStencilPitchB();
494
495				for(unsigned int y = 0; y < height; y++)
496				{
497					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
498
499					sourceBuffer += pitch;
500					destBuffer += pitch;
501				}
502
503				source->unlockStencil();
504				dest->unlockStencil();
505			}
506		}
507		else if(!scaling && equalFormats)
508		{
509			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
510			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
511			unsigned int sourcePitch = source->getInternalPitchB();
512			unsigned int destPitch = dest->getInternalPitchB();
513
514			unsigned int width = dRect.x1 - dRect.x0;
515			unsigned int height = dRect.y1 - dRect.y0;
516			unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat());
517
518			for(unsigned int y = 0; y < height; y++)
519			{
520				memcpy(destBytes, sourceBytes, bytes);
521
522				if(alpha0xFF)
523				{
524					for(unsigned int x = 0; x < width; x++)
525					{
526						destBytes[4 * x + 3] = 0xFF;
527					}
528				}
529
530				sourceBytes += sourcePitch;
531				destBytes += destPitch;
532			}
533
534			source->unlockInternal();
535			dest->unlockInternal();
536		}
537		else
538		{
539			blit(source, sRect, dest, dRect, scaling && filter);
540		}
541
542		return true;
543	}
544
545	bool Device::bindResources()
546	{
547		if(!bindViewport())
548		{
549			return false;   // Zero-area target region
550		}
551
552		return true;
553	}
554
555	bool Device::bindViewport()
556	{
557		if(viewport.width <= 0 || viewport.height <= 0)
558		{
559			return false;
560		}
561
562		if(scissorEnable)
563		{
564			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
565			{
566				return false;
567			}
568
569			sw::Rect scissor;
570			scissor.x0 = scissorRect.x0;
571			scissor.x1 = scissorRect.x1;
572			scissor.y0 = scissorRect.y0;
573			scissor.y1 = scissorRect.y1;
574
575			setScissor(scissor);
576		}
577		else
578		{
579			sw::Rect scissor;
580			scissor.x0 = viewport.x0;
581			scissor.x1 = viewport.x0 + viewport.width;
582			scissor.y0 = viewport.y0;
583			scissor.y1 = viewport.y0 + viewport.height;
584
585			if(renderTarget)
586			{
587				scissor.x0 = max(scissor.x0, 0);
588				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
589				scissor.y0 = max(scissor.y0, 0);
590				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
591			}
592
593			if(depthStencil)
594			{
595				scissor.x0 = max(scissor.x0, 0);
596				scissor.x1 = min(scissor.x1, depthStencil->getWidth());
597				scissor.y0 = max(scissor.y0, 0);
598				scissor.y1 = min(scissor.y1, depthStencil->getHeight());
599			}
600
601			setScissor(scissor);
602		}
603
604		sw::Viewport view;
605		view.x0 = (float)viewport.x0;
606		view.y0 = (float)viewport.y0;
607		view.width = (float)viewport.width;
608		view.height = (float)viewport.height;
609		view.minZ = viewport.minZ;
610		view.maxZ = viewport.maxZ;
611
612		Renderer::setViewport(view);
613
614		return true;
615	}
616
617	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
618	{
619		if(!rect)
620		{
621			return true;
622		}
623
624		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
625		{
626			return false;
627		}
628
629		if(rect->x0 < 0 || rect->y0 < 0)
630		{
631			return false;
632		}
633
634		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
635		{
636			return false;
637		}
638
639		return true;
640	}
641
642	void Device::finish()
643	{
644		synchronize();
645	}
646}
647