Device.cpp revision 426cb5e11112c9a9c3a7f145474a29e5e81463ca
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 "common/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 es1
33{
34	using namespace sw;
35
36	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
37	{
38		renderTarget = nullptr;
39		depthBuffer = nullptr;
40		stencilBuffer = nullptr;
41
42		setDepthBufferEnable(true);
43		setFillMode(FILL_SOLID);
44		setShadingMode(SHADING_GOURAUD);
45		setDepthWriteEnable(true);
46		setAlphaTestEnable(false);
47		setSourceBlendFactor(BLEND_ONE);
48		setDestBlendFactor(BLEND_ZERO);
49		setCullMode(CULL_COUNTERCLOCKWISE);
50		setDepthCompare(DEPTH_LESSEQUAL);
51		setAlphaReference(0.0f);
52		setAlphaCompare(ALPHA_ALWAYS);
53		setAlphaBlendEnable(false);
54		setFogEnable(false);
55		setSpecularEnable(true);
56		setLocalViewer(false);
57		setFogColor(0);
58		setPixelFogMode(FOG_NONE);
59		setFogStart(0.0f);
60		setFogEnd(1.0f);
61		setFogDensity(1.0f);
62		setRangeFogEnable(false);
63		setStencilEnable(false);
64		setStencilFailOperation(OPERATION_KEEP);
65		setStencilZFailOperation(OPERATION_KEEP);
66		setStencilPassOperation(OPERATION_KEEP);
67		setStencilCompare(STENCIL_ALWAYS);
68		setStencilReference(0);
69		setStencilMask(0xFFFFFFFF);
70		setStencilWriteMask(0xFFFFFFFF);
71		setVertexFogMode(FOG_NONE);
72		setClipFlags(0);
73		setPointSize(1.0f);
74		setPointSizeMin(0.125f);
75        setPointSizeMax(8192.0f);
76		setColorWriteMask(0, 0x0000000F);
77		setBlendOperation(BLENDOP_ADD);
78		scissorEnable = false;
79		setSlopeDepthBias(0.0f);
80		setTwoSidedStencil(false);
81		setStencilFailOperationCCW(OPERATION_KEEP);
82		setStencilZFailOperationCCW(OPERATION_KEEP);
83		setStencilPassOperationCCW(OPERATION_KEEP);
84		setStencilCompareCCW(STENCIL_ALWAYS);
85		setColorWriteMask(1, 0x0000000F);
86		setColorWriteMask(2, 0x0000000F);
87		setColorWriteMask(3, 0x0000000F);
88		setBlendConstant(0xFFFFFFFF);
89		setWriteSRGB(false);
90		setDepthBias(0.0f);
91		setSeparateAlphaBlendEnable(false);
92		setSourceBlendFactorAlpha(BLEND_ONE);
93		setDestBlendFactorAlpha(BLEND_ZERO);
94		setBlendOperationAlpha(BLENDOP_ADD);
95		setPointSpriteEnable(true);
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
127	Device::~Device()
128	{
129		if(renderTarget)
130		{
131			renderTarget->release();
132			renderTarget = nullptr;
133		}
134
135		if(depthBuffer)
136		{
137			depthBuffer->release();
138			depthBuffer = nullptr;
139		}
140
141		if(stencilBuffer)
142		{
143			stencilBuffer->release();
144			stencilBuffer = nullptr;
145		}
146
147		delete context;
148	}
149
150	// This object has to be mem aligned
151	void* Device::operator new(size_t size)
152	{
153		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
154		return sw::allocate(sizeof(Device), 16);
155	}
156
157	void Device::operator delete(void * mem)
158	{
159		sw::deallocate(mem);
160	}
161
162	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
163	{
164		if(!renderTarget || !rgbaMask)
165		{
166			return;
167		}
168
169		float rgba[4];
170		rgba[0] = red;
171		rgba[1] = green;
172		rgba[2] = blue;
173		rgba[3] = alpha;
174
175		sw::Rect clearRect = renderTarget->getRect();
176
177		if(scissorEnable)
178		{
179			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
180		}
181
182		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
183	}
184
185	void Device::clearDepth(float z)
186	{
187		if(!depthBuffer)
188		{
189			return;
190		}
191
192		z = clamp01(z);
193		sw::Rect clearRect = depthBuffer->getRect();
194
195		if(scissorEnable)
196		{
197			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
198		}
199
200		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
201	}
202
203	void Device::clearStencil(unsigned int stencil, unsigned int mask)
204	{
205		if(!stencilBuffer)
206		{
207			return;
208		}
209
210		sw::Rect clearRect = stencilBuffer->getRect();
211
212		if(scissorEnable)
213		{
214			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
215		}
216
217		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
218	}
219
220	egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
221	{
222		if(height > OUTLINE_RESOLUTION)
223		{
224			ERR("Invalid parameters: %dx%d", width, height);
225			return nullptr;
226		}
227
228		bool lockable = true;
229
230		switch(format)
231		{
232	//	case FORMAT_D15S1:
233		case FORMAT_D24S8:
234		case FORMAT_D24X8:
235	//	case FORMAT_D24X4S4:
236		case FORMAT_D24FS8:
237		case FORMAT_D32:
238		case FORMAT_D16:
239			lockable = false;
240			break;
241	//	case FORMAT_S8_LOCKABLE:
242	//	case FORMAT_D16_LOCKABLE:
243		case FORMAT_D32F_LOCKABLE:
244	//	case FORMAT_D32_LOCKABLE:
245		case FORMAT_DF24S8:
246		case FORMAT_DF16S8:
247			lockable = true;
248			break;
249		default:
250			UNREACHABLE(format);
251		}
252
253		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
254
255		if(!surface)
256		{
257			ERR("Out of memory");
258			return nullptr;
259		}
260
261		return surface;
262	}
263
264	egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
265	{
266		if(height > OUTLINE_RESOLUTION)
267		{
268			ERR("Invalid parameters: %dx%d", width, height);
269			return nullptr;
270		}
271
272		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
273
274		if(!surface)
275		{
276			ERR("Out of memory");
277			return nullptr;
278		}
279
280		return surface;
281	}
282
283	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
284	{
285		if(!bindResources() || !primitiveCount)
286		{
287			return;
288		}
289
290		draw(type, indexOffset, primitiveCount);
291	}
292
293	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
294	{
295		if(!bindResources() || !primitiveCount)
296		{
297			return;
298		}
299
300		setIndexBuffer(nullptr);
301
302		draw(type, 0, primitiveCount);
303	}
304
305	void Device::setScissorEnable(bool enable)
306	{
307		scissorEnable = enable;
308	}
309
310	void Device::setRenderTarget(int index, egl::Image *renderTarget)
311	{
312		if(renderTarget)
313		{
314			renderTarget->addRef();
315		}
316
317		if(this->renderTarget)
318		{
319			this->renderTarget->release();
320		}
321
322		this->renderTarget = renderTarget;
323
324		Renderer::setRenderTarget(index, renderTarget);
325	}
326
327	void Device::setDepthBuffer(egl::Image *depthBuffer)
328	{
329		if(this->depthBuffer == depthBuffer)
330		{
331			return;
332		}
333
334		if(depthBuffer)
335		{
336			depthBuffer->addRef();
337		}
338
339		if(this->depthBuffer)
340		{
341			this->depthBuffer->release();
342		}
343
344		this->depthBuffer = depthBuffer;
345
346		Renderer::setDepthBuffer(depthBuffer);
347	}
348
349	void Device::setStencilBuffer(egl::Image *stencilBuffer)
350	{
351		if(this->stencilBuffer == stencilBuffer)
352		{
353			return;
354		}
355
356		if(stencilBuffer)
357		{
358			stencilBuffer->addRef();
359		}
360
361		if(this->stencilBuffer)
362		{
363			this->stencilBuffer->release();
364		}
365
366		this->stencilBuffer = stencilBuffer;
367
368		Renderer::setStencilBuffer(stencilBuffer);
369	}
370
371	void Device::setScissorRect(const sw::Rect &rect)
372	{
373		scissorRect = rect;
374	}
375
376	void Device::setViewport(const Viewport &viewport)
377	{
378		this->viewport = viewport;
379	}
380
381	bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
382	{
383		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
384		{
385			ERR("Invalid parameters");
386			return false;
387		}
388
389		int sWidth = source->getWidth();
390		int sHeight = source->getHeight();
391		int dWidth = dest->getWidth();
392		int dHeight = dest->getHeight();
393
394		SliceRect sRect;
395		SliceRect dRect;
396
397		if(sourceRect)
398		{
399			sRect = *sourceRect;
400		}
401		else
402		{
403			sRect.y0 = 0;
404			sRect.x0 = 0;
405			sRect.y1 = sHeight;
406			sRect.x1 = sWidth;
407		}
408
409		if(destRect)
410		{
411			dRect = *destRect;
412		}
413		else
414		{
415			dRect.y0 = 0;
416			dRect.x0 = 0;
417			dRect.y1 = dHeight;
418			dRect.x1 = dWidth;
419		}
420
421		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
422		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
423		bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
424		bool alpha0xFF = false;
425
426		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
427		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
428		{
429			equalFormats = true;
430			alpha0xFF = true;
431		}
432
433		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
434		{
435			if(source->hasDepth())
436			{
437				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
438				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
439
440				unsigned int width = source->getWidth();
441				unsigned int height = source->getHeight();
442				unsigned int pitch = source->getInternalPitchB();
443
444				for(unsigned int y = 0; y < height; y++)
445				{
446					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
447
448					sourceBuffer += pitch;
449					destBuffer += pitch;
450				}
451
452				source->unlockInternal();
453				dest->unlockInternal();
454			}
455
456			if(source->hasStencil())
457			{
458				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
459				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
460
461				unsigned int width = source->getWidth();
462				unsigned int height = source->getHeight();
463				unsigned int pitch = source->getStencilPitchB();
464
465				for(unsigned int y = 0; y < height; y++)
466				{
467					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
468
469					sourceBuffer += pitch;
470					destBuffer += pitch;
471				}
472
473				source->unlockStencil();
474				dest->unlockStencil();
475			}
476		}
477		else if(!scaling && equalFormats)
478		{
479			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
480			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
481			unsigned int sourcePitch = source->getInternalPitchB();
482			unsigned int destPitch = dest->getInternalPitchB();
483
484			unsigned int width = dRect.x1 - dRect.x0;
485			unsigned int height = dRect.y1 - dRect.y0;
486			unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat());
487
488			for(unsigned int y = 0; y < height; y++)
489			{
490				memcpy(destBytes, sourceBytes, bytes);
491
492				if(alpha0xFF)
493				{
494					for(unsigned int x = 0; x < width; x++)
495					{
496						destBytes[4 * x + 3] = 0xFF;
497					}
498				}
499
500				sourceBytes += sourcePitch;
501				destBytes += destPitch;
502			}
503
504			source->unlockInternal();
505			dest->unlockInternal();
506		}
507		else
508		{
509			blit(source, sRect, dest, dRect, scaling && filter);
510		}
511
512		return true;
513	}
514
515	bool Device::bindResources()
516	{
517		if(!bindViewport())
518		{
519			return false;   // Zero-area target region
520		}
521
522		return true;
523	}
524
525	bool Device::bindViewport()
526	{
527		if(viewport.width <= 0 || viewport.height <= 0)
528		{
529			return false;
530		}
531
532		if(scissorEnable)
533		{
534			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
535			{
536				return false;
537			}
538
539			sw::Rect scissor;
540			scissor.x0 = scissorRect.x0;
541			scissor.x1 = scissorRect.x1;
542			scissor.y0 = scissorRect.y0;
543			scissor.y1 = scissorRect.y1;
544
545			setScissor(scissor);
546		}
547		else
548		{
549			sw::Rect scissor;
550			scissor.x0 = viewport.x0;
551			scissor.x1 = viewport.x0 + viewport.width;
552			scissor.y0 = viewport.y0;
553			scissor.y1 = viewport.y0 + viewport.height;
554
555			if(renderTarget)
556			{
557				scissor.x0 = max(scissor.x0, 0);
558				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
559				scissor.y0 = max(scissor.y0, 0);
560				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
561			}
562
563			if(depthBuffer)
564			{
565				scissor.x0 = max(scissor.x0, 0);
566				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
567				scissor.y0 = max(scissor.y0, 0);
568				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
569			}
570
571			if(stencilBuffer)
572			{
573				scissor.x0 = max(scissor.x0, 0);
574				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
575				scissor.y0 = max(scissor.y0, 0);
576				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
577			}
578
579			setScissor(scissor);
580		}
581
582		sw::Viewport view;
583		view.x0 = (float)viewport.x0;
584		view.y0 = (float)viewport.y0;
585		view.width = (float)viewport.width;
586		view.height = (float)viewport.height;
587		view.minZ = viewport.minZ;
588		view.maxZ = viewport.maxZ;
589
590		Renderer::setViewport(view);
591
592		return true;
593	}
594
595	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
596	{
597		if(!rect)
598		{
599			return true;
600		}
601
602		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
603		{
604			return false;
605		}
606
607		if(rect->x0 < 0 || rect->y0 < 0)
608		{
609			return false;
610		}
611
612		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
613		{
614			return false;
615		}
616
617		return true;
618	}
619
620	void Device::finish()
621	{
622		synchronize();
623	}
624}
625