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