• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 namespace es1
32 {
33 	using namespace sw;
34 
Device(Context * context)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 
~Device()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 
clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)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 
clearDepth(float z)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 
clearStencil(unsigned int stencil,unsigned int mask)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 
createDepthStencilSurface(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool discard)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 
createRenderTarget(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool lockable)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 
drawIndexedPrimitive(sw::DrawType type,unsigned int indexOffset,unsigned int primitiveCount)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 
drawPrimitive(sw::DrawType type,unsigned int primitiveCount)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 
setScissorEnable(bool enable)292 	void Device::setScissorEnable(bool enable)
293 	{
294 		scissorEnable = enable;
295 	}
296 
setRenderTarget(int index,egl::Image * renderTarget)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 
setDepthBuffer(egl::Image * depthBuffer)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 
setStencilBuffer(egl::Image * stencilBuffer)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 
setScissorRect(const sw::Rect & rect)358 	void Device::setScissorRect(const sw::Rect &rect)
359 	{
360 		scissorRect = rect;
361 	}
362 
setViewport(const Viewport & viewport)363 	void Device::setViewport(const Viewport &viewport)
364 	{
365 		this->viewport = viewport;
366 	}
367 
stretchRect(sw::Surface * source,const sw::SliceRect * sourceRect,sw::Surface * dest,const sw::SliceRect * destRect,bool filter)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 
bindResources()502 	bool Device::bindResources()
503 	{
504 		if(!bindViewport())
505 		{
506 			return false;   // Zero-area target region
507 		}
508 
509 		return true;
510 	}
511 
bindViewport()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 
validRectangle(const sw::Rect * rect,sw::Surface * surface)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 
finish()607 	void Device::finish()
608 	{
609 		synchronize();
610 	}
611 }
612